原始代码是这样的:
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
的开销,从而导致额外的计算时间。
答案 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