你如何打破并行循环?平行休息

时间:2009-08-18 14:33:56

标签: parallel-processing wolfram-mathematica

在下面的代码片段中,如果你用ParallelDo替换Do,它将以3 SLOWER的系数计算,因为现在循环只会在两个内核中的一个中断。

ParallelEvaluate[NN = 10070];
SetSharedVariable[res]
Module[{a, b, c},
  Do[
   c = NN - a - b;  
   If[a a + b b == c c, res = a b c; Break[]]
   , {a, 1, NN}, {b, a + 1, NN}
   ];
  res
  ] // AbsoluteTiming

调用ParallelAbort可以解决问题,但这是禁止的。还有什么?

1 个答案:

答案 0 :(得分:4)

您需要为每次迭代指明方法 找到答案的所有其他迭代。 我使用“退出”标志对其进行建模,最初设置 为false,在任何迭代时设置为true 决定完成。每次迭代同样具有 检查退出条件。

我的Mathematica生锈了15年,我没有 之前见过Parallelxxx形式,但是很好的猜测 循环应该如何改变如下 代码的变化:

ParallelEvaluate[NN = 10070];
SetSharedVariable[res,quit]
Module[{a, b, c},
    quit=false;
   Do[ c = NN - a - b;  
       If[quit, Break[]];
       If[ a a + b b == c c, quit=true; res = a b c; Break[]],
       {a, 1, NN}, {b, a + 1, NN}
     ];
     res
   ] // AbsoluteTiming

额外的If在某种程度上减慢了循环,但这就是价格 同步。

我怀疑金额 你在每次迭代中所做的工作已经很小了 与并行执行每次迭代的成本相比, 所以这个循环可能是低效的,你可能得不到 Do Parallel的任何实际价值。 如果你不这样做,那么你可以使每个Do迭代操作几个值 a和b的一个(例如,使用{a,1,NN,10},并且对于每个都使用类似的b) 迭代并将10宽子范围作为子循环处理 每次并行迭代)。相比之下,保持退出测试退出开销很小 在每个循环体中完成的工作。 为读者留下了重新训练的运动。

您的代码还有另一个问题:设置中存在竞争条件 水库。在ceratin情况下,两次迭代都可以决定设置res。 如果您不关心产生哪个答案,并且res的商店是“原子”, 这可以。如果res是更复杂的数据结构,则更新 它花了多个Mathematica语句,你肯定会有数据竞争 并且你的循环会在很长一段时间内产生糟糕的结果 调试会非常困难。理想情况下,你需要某种原子 测试以保护退出条件。我不知道MMa是什么, 所以你必须要查找它,但我想象一个“原子[...]”形式 坚持认为它的主体只由许多并行线程中的一个执行。 (也许MMa有一个可以用来实现原子的信号量]。 如果是这样,那么您的代码应如下所示:

ParallelEvaluate[NN = 10070];
SetSharedVariable[res,quit]
Module[{a, b, c},
    quit=false;
   Do[ c = NN - a - b;  
       If[quit, Break[]];
       If[ a a + b b == c c, 
           atomic[If[not[quit]; quit=true; res = a b c;]; Break[]],
       {a, 1, NN}, {b, a + 1, NN}
     ];
     res
   ] // AbsoluteTiming