我正在并行循环并在满足条件时更改变量。超级惯用的代码,我相信每个人都写了一百遍:
trials = 100;
greatest_so_far = 0;
best_result = 0;
for trial_i = 1:trials
[amount, result] = do_work();
if amount > greatest_so_far
greatest_so_far = amount;
best_result = result;
end
end
如果我想将for
替换为parfor
,那么在检查是否应该替换greatest_so_far
时,如何确保没有竞争条件?有没有办法将此变量锁定在支票之外?也许就像:
trials = 100;
greatest_so_far = 0;
best_result = 0;
parfor trial_i = 1:trials
[amount, result] = do_work();
somehow_lock(greatest_so_far);
if amount > greatest_so_far
greatest_so_far = amount;
best_result = result;
end
somehow_unlock(greatest_so_far);
end
答案 0 :(得分:2)
回答错误。它并不能完全解决您的问题,但它可能会帮助您避免它。
如果你能负担得起内存将do_work()
的输出存储在某些向量中,那么你只需在此函数上运行parfor
,存储结果,然后在结束(在循环之外):
amount = zeros( trials , 1 ) ;
result = zeros( trials , 1 ) ;
parfor trial_i = 1:trials
[amount(i), result(i)] = do_work();
end
[ greatest_of_all , greatest_index ] = max(amount) ;
best_result = result(greatest_index) ;
编辑/评论 :( 想把它放在你的问题的评论中,但它太长了,抱歉)。
我熟悉.net
并完全理解您的锁定/解锁请求。我自己尝试过多次尝试在很长的parfor
循环中实现一种进度指示......但无济于事。
如果我正确理解了Matlab classification of variable,那么您分配greatest_so_far
(在greatest_so_far=amount
中)这一事实会让Matlab将其视为临时变量,将在每次循环迭代开始时清除并重新初始化(因此无法用于您的目的)。
因此,一个简单的锁定变量可能不是我们现在可以简单实现的概念。一些复杂的类事件或文件写入/检查可能会有所作为,但我担心时间会受到很大影响。如果每次迭代都需要很长时间才能执行,那么开销可能是值得的,但是如果你使用parfoor
来加速大量的短执行迭代,那么复杂的解决方案会让你失速超过帮助......
您可以查看此堆叠交换问题,您可能会发现您感兴趣的内容:Semaphores and locks in MATLAB
答案 1 :(得分:2)
Hoki的解决方案是解决问题的正确方法。但是,当您询问有关竞争条件并在循环迭代相互依赖时阻止它们时,您可能需要调查spmd
and the various lab*
functions。
答案 2 :(得分:1)
您需要使用SPMD来执行此操作 - SPMD允许工作人员之间的通信。像这样:
bestResult = -Inf;
bestIndex = NaN;
N = 97;
spmd
% we need to round up the loop range to ensure that each
% worker executes the same number of iterations
loopRange = numlabs * ceil(N / numlabs);
for idx = 1:numlabs:loopRange
if idx <= N
local_result = rand(); % obviously replace this with your actual function
else
local_result = -Inf;
end
% Work out which index has the best result - use a really simple approach
% by concatenating all the results this time from each worker
% allResultsThisTime will be 2-by-numlabs where the first row is all the
% the results this time, and the second row is all the values of idx from this time
allResultsThisTime = gcat([local_result; idx]);
% The best result this time - consider the first row
[bestResultThisTime, labOfBestResult] = max(allResultsThisTime(1, :));
if bestResultThisTime > bestResult
bestResult = bestResultThisTime;
bestIndex = allResultsThisTime(2, labOfBestResult);
end
end
end
disp(bestResult{1})
disp(bestIndex{1})