返回首页

用于并行人的快速问题,我有下面的一段代码,没有什么花哨:

var result = Parallel.For(0, 10, (i) =>

    {

        Console.WriteLine(DateTime.Now.ToLongTimeString() + "Start sleep: " + i);

        Thread.Sleep(i * 1000);

        Console.WriteLine(DateTime.Now.ToLongTimeString() + "Done sleep: " + i);

    });

 

Console.WriteLine("DONE!");

和我预料到9秒左右,也许更多一点取决于调度。但它发生在任何地方从12至25秒,有人可以解释为什么?
下面是一个示例输出到20多岁和我的意见。为什么调度发射前最后一个等待这么长的时间呢?有大量的时间来启动它。此外,有时做得很好,迅速(早)...为什么巨大的差异呢?没有太大的改变就在我身边,从运行运行。
五点10分24秒PMStart睡眠:5 - GT 5
五点10分24秒PMStart睡眠:0 - GT 5 0
五点10分24秒PMDone睡眠:0 - GT 5
五点10分24秒PMStart睡眠:1 - GT 5 1
五点10分24秒PMStart睡眠:3 - > 5 1 3
5时10分25秒PMStart睡眠:6 - > 5 1 3 6
5时10分25秒PMDone睡眠:1 - > 5 3 6
5时10分25秒PMStart睡眠:2 - > 5 3 6 2
5时10分26秒PMStart睡眠:4 - > 5 3 6 2 4
5点10分27秒PMStart睡眠:7 - GT 5 3 6 2 4 7
5点10分27秒PMDone睡眠:2 - > 5 3 6 4 7
5点10分27秒PMStart睡眠:8 - > 5 3 6 4 7 8
5点10分27秒PMDone睡眠:3 - > 5 6 4 7 8
5点10分29秒PMDone睡眠:5 - > 6 4 7 8
5时10分三十秒PMDone睡眠:4 - > 6 7 8
5点10分31秒PMDone睡眠:6 - > 7 8
五点10分34秒PMDone睡眠:7 - > 8
5时10分35秒PMDone睡眠:8 - GT;空的
5时10分35秒PMStart睡眠:9 - GT; 9
5时10分44秒PMDone睡眠:9 - GT;空的
DONE!

回答

评论会员:Jimmanuel 时间:2012/02/06
我想从你排队的工作项目与启动专用线程的线程池的事实是大多数的差异。在一个方法中,您为每个项目建立专门的线程立即运行,但在ThreadPool不起作用的方式。

当你到池的队列项目最初开始只有这么多线程和增加最多2第二个(最后,我选中),如果没有足够的线程来执行队列中的所有工作项目。 (或在池的初始线程的系统规格不同而定。)

编辑
早该"其实检查前发布后,{S0的}而不是

排队项目时创建的线程池线程,直到它击中的"最佳线程数会有所不同,根据系统规格。根据我的参考,它是系统中的处理器数量 - NET 3.5。它击中后,限制它扼杀创建新的线程最多每半秒。添加线程的精确算法是不是ThreadPool的用户应该不用担心,它的设计是好的,在大多数情况下足够。
/编辑

一旦这些线程被创建时,池中保持他们的位左右的情况下,它再次需要他们。当你调用在循环的第一次迭代"素数"为您的ThreadPool ExecuteTests;它创造一切必要的线程,以便有足够的已存在来处理所有的项目在随后的电话排队。第一次迭代需要更多的时间,因为它开始太少的线程来处理所有的项目和需要时间多了起来旋转。SAKryukov
评论会员:游客 时间:2012/02/06
否,预计非平行的时间约45秒,不计的开销是!你为什么乘以索引的睡眠时间?我的顺序代码相同的45秒,有的在并行代码18至27秒2核心系统。这是绝对不精彩。另外,我用更好的计时工具,使用System.Diagnostics.Stopwatch:{C}指数乘法,如果我删除,我得到顺序代码9-10秒,3秒左右的并行代码。你知道睡在这种并行代码毫无意义。我希望你只为做实验。此外,你应该明白并行执行并不总是提高吞吐量。你需要多码的CPU或多个CPU和任务,这使得在并行执行的意识。此外,其他进程可以减少的效果。沉重的CPU负载,你可能不会得到性能改进。mdash;SA:rld1971||我改变了我的一点点代码测试的几种方法。我的结果告诉现在一个不同的故事......任务(或Parallel.For)最终打开了,开始第二轮的结果更接近我的预期(9秒的运行时间)。对我来说这是一个调度问题,也许做初始化。有人知道吗?代码codeprelang="cs"spanclass="code-keyword"private/spanspanclass="code-keyword"void/spanRunTest(){spanclass="code-keyword"for/span(spanclass="code-keyword"int/spani=spanclass="code-digit"0/span;i<spanclass="code-digit"5/span;i++)ExecuteTests();} spanclass="code-keyword"private/spanspanclass="code-keyword"void/spanExecuteTests(){Stopwatchsw=spanclass="code-keyword"new/spanStopwatch();sw.Start(); ExecParallel();Log(spanclass="code-string""/spanspanclass="code-string"Paralleldone"/span,sw);ExecTasks();Log(spanclass="code-string""/spanspanclass="code-string"Tasksdone"/span,sw);ExecThreads();Log(spanclass="code-string""/spanspanclass="code-string"Threadsdone"/span,sw);ExecThreadPool();Log(spanclass="code-string""/spanspanclass="code-string"ThreadPooldone"/span,sw);} spanclass="code-keyword"private/spanspanclass="code-keyword"static/spanspanclass="code-keyword"void/spanExecParallel(){spanclass="code-keyword"var/spanresult=Parallel.For(spanclass="code-digit"0/span,spanclass="code-digit"10/span,(i)=>{DoWork(i);});} spanclass="code-keyword"private/spanspanclass="code-keyword"static/spanspanclass="code-keyword"void/spanExecTasks(){spanclass="code-keyword"var/spantasks=spanclass="code-keyword"new/spanTask[spanclass="code-digit"10/span];spanclass="code-keyword"for/span(spanclass="code-keyword"int/spani=spanclass="code-digit"0/span;i<spanclass="code-digit"10/span;i++){tasks[i]=Task.Factory.StartNew(()=>DoWork(i));} Task.WaitAll(tasks);} spanclass="code-keyword"private/spanspanclass="code-keyword"static/spanspanclass="code-keyword"void/spanExecThreads(){spanclass="code-keyword"var/spanthreads=spanclass="code-keyword"new/spanThread[spanclass="code-digit"10/span];spanclass="code-keyword"for/span(spanclass="code-keyword"int/spani=spanclass="code-digit"0/span;i<spanclass="code-digit"10/span;i++){threads[i]=spanclass="code-keyword"new/spanThread(()=>DoWork(i));threads[i].Start();} spanclass="code-keyword"foreach/span(spanclass="code-keyword"var/spantspanclass="code-keyword"in/spanthreads)t.Join();} spanclass="code-keyword"private/spanspanclass="code-keyword"static/spanspanclass="code-keyword"void/spanExecThreadPool(){spanclass="code-keyword"var/spanthreads=spanclass="code-keyword"new/spanThread[spanclass="code-digit"10/span];spanclass="code-keyword"var/spandoneEvents=spanclass="code-keyword"new/spanManualResetEvent[spanclass="code-digit"10/span]; spanclass="code-keyword"for/span(spanclass="code-keyword"int/spani=spanclass="code-digit"0/span;i<spanclass="code-digit"10/span;i++){spanclass="code-keyword"int/spanj=i;doneEvents[j]=spanclass="code-keyword"new/spanManualResetEvent(spanclass="code-keyword"false/span);ThreadPool.QueueUserWorkItem((spanclass="code-keyword"object/spanctx)=>{DoWork(j);doneEvents[j].Set();});} spanclass="code-keyword"foreach/span(spanclass="code-keyword"var/spanespanclass="code-keyword"in/spandoneEvents)e.WaitOne();spanclass="code-comment"///spanspanclass="code-comment"WaitHandle.WaitAll(doneEvents);//inSTAthread.../span} spanclass="code-keyword"private/spanspanclass="code-keyword"static/spanspanclass="code-keyword"void/spanDoWork(spanclass="code-keyword"int/spani){Thread.Sleep(i*spanclass="code-digit"1000/span);} spanclass="code-keyword"private/spanspanclass="code-keyword"void/spanLog(spanclass="code-keyword"string/spans,Stopwatchsw){Console.Out.WriteLine(spanclass="code-string""/spanspanclass="code-string"[Elapsedtime:{0:##.00}s]{1}"/span,sw.ElapsedMilliseconds/1000f,s);sw.Restart();}/pre/code结果{体C3}
rld1971:所以这是有道理的...也许我们不知道确切的参数,但我看到现在工作的逻辑。我提出ExecThreadPool的()是第一,然后其余的人采取尽可能多的时间预期。不断学习新的东西!有没有更好的办法做到这一点