如何`parfor`嵌套循环?

时间:2014-05-05 03:23:54

标签: matlab parallel-processing parfor

原始代码是这样的:

for i = 1 : size(H, 1)
    for j = 1 : size(H, 2)
        H{i,j} blabla

我尝试将其改编为并行代码,如下所示:

parfor ind = 1 : numel(H)
    [i, j] = ind2sub(ind);
    H{i,j} blabla

由于H {i,j}而生成错误,导致parfor无法运行。

那么这里的错误是什么?我如何将嵌套循环调整为parfor?

一种可能的解决方案

for i = 1 : size(H, 1)
    parfor j = 1 : size(H, 2)
        H{i,j} blabla

但是我怀疑在另一个循环中使用parfor会增加parfor的开销,从而导致额外的计算时间

2 个答案:

答案 0 :(得分:2)

我认为使用parfor的错误是Matlab无法通过循环检测到[i,j]是唯一的,因为它是函数的结果。因此,对于引擎,您可以多次访问H{i,j},迭代不会被分析为彼此独立。

编辑:正如patrik所提到的,你必须确保两次迭代之间没有依赖关系,这里H{i,j}不依赖于H{k,l}i!=k and j!=l,也不是迭代中的变量值用于另一次迭代。除了reduction assignment之外,此要求是允许parfor的基本要求。

除此之外,如果您想并行运行独立计算,并且如果值得,请始终选择parfor最外层循环。除此之外,请提醒Matlab does not allow nested parfor;相反,如果要并行化内部for循环,则必须创建一个运行parfor的函数。内循环的并行化可能不会带来加速(取决于parpool中有多少工人)。

根据我的经验,不建议运行并行内循环。作为一个例子(在Matlab之外),我会引用LibSVM,如果你想加速计算,建议只使用openmp并行化最外层循环,而不是其他内部循环。

这个建议的原因是你有一个有限的工人池,工人可能被视为线程;如果添加线程,则存在一个限制,由于线程之间切换的时间,计算运行速度较慢。 Matlab可以很好地管理这部分,但关键是你将拥有一个有限的工人池。如果每个最外面的迭代需要花费很多时间,并且如果你有很多迭代,那么你将没有时间来并行化内部循环,因为每个工作者都将忙于运行整个迭代(包括内部循环)。

尽管如此,测试每个选项总是一件好事,其中一些可能会反直觉地更适合您的问题!

答案 1 :(得分:1)

为什么不简单地使用线性索引分配到H?例如:

H = cell(4, 4);
parfor idx = 1:16
  [i, j] = ind2sub([4, 4], idx);
  H{idx} = rand(i, j); % or whatever
end

否则,最好将最外层循环设为PARFOR循环。以下也有效:

H = cell(4, 4);
parfor r = 1:4
  for c = 1:4
    H{r, c} = rand(r, c);
  end
end