如何在spmd块中索引codistributed数组

时间:2014-01-14 17:33:50

标签: matlab parallel-processing distributed-computing spmd

我正在做一个非常大的计算(大气吸收),它有很多个别的窄峰,最后都会加起来。对于每个峰值,我已经预先计算了峰值形状函数的值高于我选择的阈值的范围,然后我逐行进行并将峰值添加到我的光谱中。下面给出了一个最小的例子:

X = 1:1e7;
K = numel(a); % count the number of peaks I have.
spectrum = zeros(size(X));
for k = 1:K
    grid = X >= rng(1,k) & X <= rng(2,k);
    spectrum(grid) = spectrum(grid) + peakfn(X(grid),a(k),b(k),c(k)]);
end

此处,每个峰都有一些参数可以定义位置和形状(abc)以及计算范围({{1} })。这很好用,在我的机器上它的基准测试大约需要220秒来完成一个完整的数据集。但是,我有一个4核机器,我最终想在集群上运行它,所以我想将它并行化并使其可扩展。

因为每个循环都依赖于前一次迭代的结果,所以我不能使用rng,所以我迈出了学习如何使用parfor块的第一步。我的第一次尝试看起来像这样:

spmd

这几乎可行。该程序在最后一行崩溃,因为X = 1:1e7; cores = matlabpool('size'); K = numel(a); spectrum = zeros(size(X),cores); spmd n = labindex:cores:K N = numel(n); for k = 1:N grid = X >= rng(1,n(k)) & X <= rng(2,n(k)); spectrum(grid,labindex) = spectrum(grid,labindex) + peakfn(X(grid),a(n(k)),b(n(k)),c(n(k))]); end end finalSpectrum = sum(spectrum,2); 的类型为spectrum,而Composite的文档在如何将2013a数据转换为矩阵({{1不起作用)。这也不能很好地扩展,因为我拥有的核心越多,矩阵越大,并且必须将大矩阵复制到每个工作者,然后忽略大多数数据。 问题1:如何将Composite数据类型转换为可用数组?

我尝试的第二件事是使用Composite数组。

cell2mat

这告诉我每个工人都有一个大小为[K 1]的矢量,我相信这就是我想要的,但当我尝试将上述方法融合时

codistributed

我收到spmd spectrum = codistributed.zeros(K,cores); disp(size(getLocalPart(spectrum))) end 错误。因为它是在一个并行块中,所以我不能使用我的正常调试拐点来逐步遍历循环并查看每个块的大小在每个点以查看正在发生的事情。 问题2:spmd spectrum = codistributed.zeros(K,cores); n = labindex:cores:K N = numel(n); for k = 1:N grid = X >= rng(1,n(k)) & X <= rng(2,n(k)); spectrum(grid) = spectrum(grid) + peakfn(X(grid),a(n(k)),b(n(k)),c(n(k))]); end finalSpectrum = gather(spectrum); end finalSpectrum = sum(finalSpectrum,2); 块中索引进出分配数组的正确方法是什么?

1 个答案:

答案 0 :(得分:4)

关于问题#1,客户端中的Composite变量基本上是指存储在worker上的非分布式变量数组。您可以通过{}访问每个工作人员的数组 - 使用相应的labindex建立索引(例如:spectrum{1}spectrum{2},..)。

对于您的代码:finalSpectrum = sum(cat(2,spectrum{:}), 2);


现在我使用随机数据自己尝试了这个问题。以下是三个要比较的实现(请参阅此处以了解distributed and nondistributed arrays之间的差异)。首先,我们从常见数据开始:

len = 100;    % spectrum length
K = 10;       % number of peaks
X = 1:len;

% random position and shape parameters
a = rand(1,K); b = rand(1,K); c = rand(1,K);

% random peak ranges (lower/upper thresholds)
ranges = sort(randi([1 len], [2 K]));

% dummy peakfn() function
fcn = @(x,a,b,c) x+a+b+c;

% prepare a pool of MATLAB workers
matlabpool open

1)串行for循环:

spectrum = zeros(size(X));
for i=1:size(ranges,2)
    r = ranges(:,i);
    idx = (r(1) <= X & X <= r(2));
    spectrum(idx) = spectrum(idx) + fcn(X(idx), a(i), b(i), c(i));
end
s1 = spectrum;

clear spectrum i r idx

2)具有复合数组的SPMD

spmd
    spectrum = zeros(1,len);
    ind = labindex:numlabs:K;
    for i=1:numel(ind)
        r = ranges(:,ind(i));
        idx = (r(1) <= X & X <= r(2));
        spectrum(idx) = spectrum(idx) + ...
            feval(fcn, X(idx), a(ind(i)), b(ind(i)), c(ind(i)));
    end
end
s2 = sum(vertcat(spectrum{:}));

clear spectrum i r idx ind

3)具有共分布阵列的SPMD

spmd
    spectrum = zeros(numlabs, len, codistributor('1d',1));
    ind = labindex:numlabs:K;
    for i=1:numel(ind)
        r = ranges(:,ind(i));
        idx = (r(1) <= X & X <= r(2));
        spectrum(labindex,idx) = spectrum(labindex,idx) + ...
            feval(fcn, X(idx), a(ind(i)), b(ind(i)), c(ind(i)));
    end
end
s3 = sum(gather(spectrum));

clear spectrum i r idx ind

所有三个结果应该相等(在可接受的小误差范围内)

>> max([max(s1-s2), max(s1-s3), max(s2-s3)])
ans =
   2.8422e-14