Parallel.For和Break()误会?
我正在研究For循环中的Parallelism Break。
阅读本文后 ,我仍然有一个问题:
我希望这段代码:
Parallel.For(0, 10, (i,state) => { Console.WriteLine(i); if (i == 5) state.Break(); }
最多产生 6个数字(0..6)。 他不仅没有这样做,而且结果长度不同:
02351486 013542 0135642
很烦人。 (这里的地狱是Break(){5之后}这里??)
所以我看了msdn
Break可以用于与循环通信,在当前迭代之后不需要运行其他迭代。 如果从for循环的第100次迭代调用Break从0到1000并行迭代,则仍应运行小于100的所有迭代,但不需要从101到1000的迭代。
问题#1:
哪个迭代? 整个迭代计数器? 还是每个线程? 我很确定这是每个post。 请批准。
问题2 :
让我们假设我们使用并行+范围分区(由于元素之间没有cpu成本变化),因此它在线程之间划分数据。 所以如果我们有4个核心(并且它们之间有完美的划分):
core #1 got 0..250 core #2 got 251..500 core #3 got 501..750 core #4 got 751..1000
所以core #1
的线程有时会遇到value=100
并且会中断。 这将是他的迭代次数100
。 但core #4
的线程获得了更多量子,现在他已经达到了900
。 他超越了他的第100'th
次迭代。 他没有指数少于100被阻止!! – 所以他会告诉他们所有人。
我对吗 ? 这就是我在我的例子中获得超过5个元素的原因吗?
问题#3:
如果我真的打破了(i == 5)
?
PS
我的意思是,来吧! 当我做Break()
,我希望循环停止。 正如我在常规For
循环中所做的那样。
最多产生6个数字(0..6)。
问题是这不会产生最多6个数字 。
当您点击索引为5的循环时,会发送“中断”请求。 Break()
将导致循环不再处理任何>5
值,但处理所有值<5
。
但是,任何已经启动的大于5的值仍将被处理。 由于各个索引并行运行,因此不再对它们进行排序,因此您可以进行各种运行,其中一些值>5
(例如示例中的8)仍在执行中。
哪个迭代? 整个迭代计数器? 还是每个线程? 我很确定这是每个post。 请批准。
这是传递给Parallel.For的索引。 Break()不会阻止处理项目,但可以保证最多100个项目得到处理,但100以上的项目可能会或可能不会被处理。
我对吗 ? 这就是我在我的例子中获得超过5个元素的原因吗?
是。 如果你使用像你所示的分区器,只要你调用Break()
,你破坏的项目之外的项目将不再被安排。 但是,已经安排的项目( 整个分区 )将得到完全处理。 在您的示例中,这意味着您可能始终处理所有1000个项目。
我怎么能真正打破(i == 5)?
你是 - 但是当你并行运行时,情况会发生变化。 这里的实际目标是什么? 如果您只想处理前6项(0-5),则应在通过LINQ查询或类似项循环之前限制项。 然后,您可以在Parallel.For
或Parallel.ForEach
处理6个项目,而不需要Break()
并且无需担心。
我的意思是,来吧! 当我做Break()时,我希望循环停止。 正如我在常规For循环中所做的那样。
如果你想让事情尽快停止,你应该使用Stop()
而不是Break()
。 这不会阻止已经运行的项目停止,但不会再安排任何项目(包括枚举中较低索引或较早的项目,而不是当前位置)。
如果从for循环的第100次迭代调用Break,则从0到1000并行迭代
循环的第100次迭代不一定(实际上可能不是)具有索引99的那次。
您的线程可以并将以不确定的顺序运行。 遇到.Break()指令时,不会再启动循环迭代。 究竟何时发生这种情况取决于特定运行的线程调度的细节。
我强烈建议阅读
并行编程模式
(来自微软的免费PDF)
了解进入TPL的设计决策和设计权衡。
哪个迭代? 整个迭代计数器? 还是每个线程?
关闭计划(或尚未安排)的所有迭代。
请记住,委托可能无序运行,不能保证迭代i == 5
将是第六个执行,相反,除非在极少数情况下这种情况不太可能。
Q2:我是对的吗?
不,调度不是那么简单。 而是将所有任务排队,然后处理队列。 但是每个线程都使用自己的队列,直到它们从其他线程中窃取时为空。 这导致无法预测哪个线程将处理哪个委托。
如果委托是非常简单的,它可能都会在原始调用线程上处理(没有其他线程有机会窃取工作)。
Q3:当我(i == 5)时,我真的打破了怎么样?
如果您想要线性(特定)处理,请不要同时使用。
Break
方法用于支持推测性执行:尝试各种方法并在任何一个完成后立即停止。