1

原始代码是这样的:

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

这会生成一个错误,说parfor由于 H{i,j} 而无法运行。

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

一种可能的解决方案

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

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

4

2 回答 2

2

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

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

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

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

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

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

于 2014-05-05T09:47:13.020 回答
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
于 2014-05-06T06:50:00.190 回答