【问题标题】:Less strict alternative to parfor in matlab?在matlab中对parfor不太严格的替代方案?
【发布时间】:2013-05-02 05:27:34
【问题描述】:

我的代码在结构上类似于 Matlab 中的以下代码:

bestConfiguration = 0;
bestConfAwesomeness = 0;

for i=1:X
    % note that providing bestConfAwesomeness to the function helps it stop if it sees the current configuration is getting hopeless anyway
    [configuration, awesomeness] = expensive_function(i, bestConfAwesomeness);
    if awesomeness > bestConfAwesomeness
        bestConfAwesomeness = awesomeness;
        bestConfiguration = configuration;
    end
end

还有更多内容,但基本结构如上。 X 可以非常 大。我试图让这段代码并行运行,因为expensive_function() 需要很长时间才能运行。

问题在于,Matlab 不允许我将 for 更改为 parfor,因为它不喜欢我在循环中更新最佳配置。

到目前为止,我所做的是:

[allConfigurations, allAwesomeness] = deal(cell(1, X));

parfor i=1:X
    % note that this is not ideal because I am forced to use 0 as the best awesomeness in all cases
    [allConfigurations{i}, allAwesomeness{i}] = expensive_function(i, 0);
end

for i=1:X
    configuration = allConfigurations{i};
    awesomeness = allAwesomeness{i};
    if awesomeness > bestConfAwesomeness
        bestConfAwesomeness = awesomeness;
        bestConfiguration = configuration;
    end
endfor

这在运行时间方面更好;但是,对于大型输入,它会占用大量内存,因为始终保存所有配置。另一个问题是使用parfor 迫使我始终提供0 作为最佳配置,即使可能知道更好的配置。

Matlab 是否提供了更好的方法来做到这一点?

基本上,如果我不必使用 Matlab 并且可以自己管理线程,我会有一个中心线程来为工人提供工作(即让他们运行expensive_function(i)),一旦工人返回,看看它产生的数据并将其与迄今为止发现的最佳数据进行比较并相应地更新它。无需保存所有配置,这似乎是使parfor 工作的唯一方法。

有没有办法在Matlab中做到以上几点?

【问题讨论】:

  • 为了能够在调用expensive_function 时使用先验知识,您可以将parfor 的范围拆分为更小的扫描(例如,i=1:floor(X/2),然后是i=floor(X/2):X)并使用第一次扫描的最佳结果是播种以下对expensive_function 的调用。请注意,此解决方案的可行性取决于对expensive_function 的知情调用所节省的运行时间与拥有一个parfor 与拥有多个连续parfors 所节省的时间之间的权衡。
  • @H.Muster:我正在考虑这个问题,但这并不理想,因为expensive_function 可能需要很长时间才能进行某些输入,即第一次扫描可能会不必要地等待一小部分当它已经可以从另一部分运行作业时完成它
  • 正如我所说,这取决于权衡。作为一种解决方法,expensive_function 可以将其部分结果保存到文件中。然后,在每次调用时,该函数可以检查结果文件是否已经可用,如果是,则利用此先验知识。
  • 您的循环迭代不是独立的,因为您使用的是以前迭代的知识(即 bestConfAwesomeness)。这不是一个专门的 MATLAB 问题 - PARFOR 只是在保护您免受竞争条件的影响。
  • @Edric:是的,但不是严格需要 bestConfAwesomeness;它只是为了加快速度,而不是提供它不会改变输出。 IE。如果您一直传递 0,它将给出完全相同的结果,但速度较慢。这是一个 Matlab 问题,因为在大多数其他语言中,您可以执行我在上一段中描述的操作。

标签: multithreading matlab parallel-processing parfor


【解决方案1】:

每次循环使用bestConfAwesomeness 意味着循环的迭代不是顺序无关的,因此PARFOR 不满意。您可以采取的一种方法是使用SPMD 并让每个工作人员并行执行expensiveFunction,然后进行通信以更新bestConfAwesomeness。像这样的:

bestConfiguration = 0;
bestConfAwesomeness = 0;
spmd
  for idx = 1:ceil(X/numlabs)
    myIdx = labindex + ((idx-1) * numlabs);
    % should really guard against myIdx > X here.
    [thisConf, thisAwesome] = expensiveFunction(myIdx, bestConfAwesomeness);
    % Now, we must communicate to see if who is best
    [bestConfiguration, bestAwesomeness] = reduceAwesomeness(...
        bestConfiguration, bestConfAwesomeness, thisConf, thisAwesome);
  end
end

function [bestConf, bestConfAwesome] = reduceAwesomeness(...
    bestConf, bestConfAwesome, thisConf, thisAwesome)
% slightly lazy way of doing this, could be optimized
% but probably not worth it if conf & awesome both scalars.
allConfs = gcat(bestConf);
allAwesome = gcat(thisAwesome);
[maxThisTime, maxLoc] = max(allAwesome);
if maxThisTime > bestConfAwesome
    bestConfAwesome = maxThisTime;
    bestConf = allConfs(maxLoc);
end
end

【讨论】:

    【解决方案2】:

    我不确定 Matlab 是否可以对线程进行控制。但是,由于X 非常大,因此可能值得执行以下操作,这会花费您对expensiveFunction 的一次迭代:

    %# calculate awesomeness
    parfor i=1:X
       [~,awesomeness(i)] = expensiveFunction(i);
    end
    %# find the most awesome i
    [mostAwesome,mostAwesomeIdx] = min(awesomeness);
    %# get the corresponding configuration
    bestConfiguration = expensiveFunction(mostAwesomeIdx);
    

    【讨论】:

    • 谢谢,真的,这可能有助于降低内存成本。我正在寻找更好的选择的原因是,通过某种方式将迄今为止发现的最知名的令人敬畏的功能传递给昂贵的功能,这对我来说也很有用,for 可能是parfor 所不具备的。现在编辑问题以反映这一点(我之前忘了提)
    猜你喜欢
    • 2011-09-22
    • 1970-01-01
    • 2021-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-26
    • 2013-12-19
    • 1970-01-01
    相关资源
    最近更新 更多