Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parallel processing 分布式阵列的Matlab慢速并行处理_Parallel Processing_Distributed_Distributed Computing_Matlab - Fatal编程技术网

Parallel processing 分布式阵列的Matlab慢速并行处理

Parallel processing 分布式阵列的Matlab慢速并行处理,parallel-processing,distributed,distributed-computing,matlab,Parallel Processing,Distributed,Distributed Computing,Matlab,我不熟悉在matlab中使用分布式和协同分布式阵列。我制作的并行代码可以工作,但是比串行版本慢得多,我不知道为什么。下面的代码示例根据体积数据计算hessian矩阵的特征值 序列版本: S = size(D); Dsmt=imgaussian(D,2,20); [fx, fy, fz] = gradient(Dsmt); DHess = zeros([3 3 S(1) S(2) S(3)]); [DHess(1,1,:,:,:), DHess(1,2,:,:,:), DHess(1,3,:,:,

我不熟悉在matlab中使用分布式和协同分布式阵列。我制作的并行代码可以工作,但是比串行版本慢得多,我不知道为什么。下面的代码示例根据体积数据计算hessian矩阵的特征值

序列版本:

S = size(D);
Dsmt=imgaussian(D,2,20);
[fx, fy, fz] = gradient(Dsmt);
DHess = zeros([3 3 S(1) S(2) S(3)]);
[DHess(1,1,:,:,:), DHess(1,2,:,:,:), DHess(1,3,:,:,:)] = gradient(fx);
[DHess(2,1,:,:,:), DHess(2,2,:,:,:), DHess(2,3,:,:,:)] = gradient(fy);
[DHess(3,1,:,:,:), DHess(3,2,:,:,:), DHess(3,3,:,:,:)] = gradient(fz);

d = zeros([3 S(1) S(2) S(3)]);
for i = 1 : S(1)
    fprintf('Slice %d out of %d\n', i, S(1));
    for ii = 1 : S(2)
        for iii = 1 : S(3)
            d(:,i,ii,iii) = eig(squeeze(DHess(:,:,i,ii,iii)));
        end
    end
end
S = size(D);
Dsmt=imgaussian(D,2,20);
[fx, fy, fz] = gradient(Dsmt);
DHess = zeros([3 3 S(1) S(2) S(3)]);
[DHess(1,1,:,:,:), DHess(1,2,:,:,:), DHess(1,3,:,:,:)] = gradient(fx);
[DHess(2,1,:,:,:), DHess(2,2,:,:,:), DHess(2,3,:,:,:)] = gradient(fy);
[DHess(3,1,:,:,:), DHess(3,2,:,:,:), DHess(3,3,:,:,:)] = gradient(fz);
CDHess = distributed(DHess);
spmd  
    d = zeros([3 S(1) S(2) S(3)], codistributor('1d',4));
    for i = 1 : S(1)
        fprintf('Slice %d out of %d\n', i, S(1));
        for ii = 1 : S(2)
            for iii = drange(1 : S(3))
                d(:,i,ii,iii) = eig(squeeze(CDHess(:,:,i,ii,iii)));
            end
        end
    end
end
并行版本:

S = size(D);
Dsmt=imgaussian(D,2,20);
[fx, fy, fz] = gradient(Dsmt);
DHess = zeros([3 3 S(1) S(2) S(3)]);
[DHess(1,1,:,:,:), DHess(1,2,:,:,:), DHess(1,3,:,:,:)] = gradient(fx);
[DHess(2,1,:,:,:), DHess(2,2,:,:,:), DHess(2,3,:,:,:)] = gradient(fy);
[DHess(3,1,:,:,:), DHess(3,2,:,:,:), DHess(3,3,:,:,:)] = gradient(fz);

d = zeros([3 S(1) S(2) S(3)]);
for i = 1 : S(1)
    fprintf('Slice %d out of %d\n', i, S(1));
    for ii = 1 : S(2)
        for iii = 1 : S(3)
            d(:,i,ii,iii) = eig(squeeze(DHess(:,:,i,ii,iii)));
        end
    end
end
S = size(D);
Dsmt=imgaussian(D,2,20);
[fx, fy, fz] = gradient(Dsmt);
DHess = zeros([3 3 S(1) S(2) S(3)]);
[DHess(1,1,:,:,:), DHess(1,2,:,:,:), DHess(1,3,:,:,:)] = gradient(fx);
[DHess(2,1,:,:,:), DHess(2,2,:,:,:), DHess(2,3,:,:,:)] = gradient(fy);
[DHess(3,1,:,:,:), DHess(3,2,:,:,:), DHess(3,3,:,:,:)] = gradient(fz);
CDHess = distributed(DHess);
spmd  
    d = zeros([3 S(1) S(2) S(3)], codistributor('1d',4));
    for i = 1 : S(1)
        fprintf('Slice %d out of %d\n', i, S(1));
        for ii = 1 : S(2)
            for iii = drange(1 : S(3))
                d(:,i,ii,iii) = eig(squeeze(CDHess(:,:,i,ii,iii)));
            end
        end
    end
end

如果有人能解释一下这个问题,我将非常感激你没有指定你在哪里打开了你的matlabpool,这将是决定你的加速率的主要因素

如果您使用的是“本地”调度程序,那么使用分布式阵列通常没有任何好处。特别是,如果耗时的操作在MATLAB中已经是多线程的,那么在使用本地调度器时,它们几乎肯定会变慢,因为matlabpool workers在单线程模式下运行

若您在另一台机器上使用其他调度程序和工人,那个么您可能能够获得加速,但这取决于您正在做什么。这里有一个例子显示了MATLAB的
\
操作符的一些基准测试


最后,值得注意的是,不幸的是,索引分布式数组的速度相当慢,特别是与MATLAB的内置索引相比。如果您可以在spmd块内提取codistributed数组的“本地部分”并专门处理这些数组,这可能也会有所帮助。

这是您重新编写的代码版本。我把工作分成了最外层的循环,而不是像你的情况那样——最内层的循环。我还明确地分配了
d
结果向量的局部部分,以及Hessian矩阵的局部部分

在您的代码中,您依靠
drange
来分割工作,并直接访问分布式阵列以避免提取本地部分。诚然,如果MATLAB做的一切都正确,它不应该导致如此大的减速。底线是,我不知道为什么你的代码这么慢——很可能是因为MATLAB做了一些远程数据访问,尽管你分发了矩阵

无论如何,下面的代码在我的计算机上运行,并使用4个实验室提供了相当好的加速。我已经生成了合成的随机输入数据,以便进行处理。看看评论。如果有什么不清楚的地方,我可以稍后再详细说明

clear all;

D = rand(512, 512, 3);
S = size(D);
[fx, fy, fz] = gradient(D);

% this part could also be parallelized - at least a bit.
tic;
DHess = zeros([3 3 S(1) S(2) S(3)]);
[DHess(1,1,:,:,:), DHess(1,2,:,:,:), DHess(1,3,:,:,:)] = gradient(fx);
[DHess(2,1,:,:,:), DHess(2,2,:,:,:), DHess(2,3,:,:,:)] = gradient(fy);
[DHess(3,1,:,:,:), DHess(3,2,:,:,:), DHess(3,3,:,:,:)] = gradient(fz);
toc

% your sequential implementation
d = zeros([3, S(1) S(2) S(3)]);
disp('sequential')
tic
for i = 1 : S(1)
    for ii = 1 : S(2)
        for iii = 1 : S(3)
            d(:,i,ii,iii) = eig(squeeze(DHess(:,:,i,ii,iii)));
        end
    end
end
toc

% my parallel implementation
disp('parallel')
tic
spmd
    % just for information
    disp(['lab ' num2str(labindex)]);

    % distribute the input data along the third dimension
    % This is the dimension of the outer-most loop, hence this is where we
    % want to parallelize!
    DHess_dist  = codistributed(DHess, codistributor1d(3));
    DHess_local = getLocalPart(DHess_dist);

    % create an output data distribution - 
    % note that this time we split along the second dimension
    codist = codistributor1d(2, codistributor1d.unsetPartition, [3, S(1) S(2) S(3)]);
    localSize = [3 codist.Partition(labindex) S(2) S(3)];

    % allocate local part of the output array d
    d_local = zeros(localSize);

    % your ordinary loop, BUT! the outermost loop is split amongst the
    % threads explicitly, using local indexing. In the loop only local parts
    % of matrix d and DHess are accessed
    for i = 1:size(d_local,2)
        for ii = 1 : S(2)
            for iii = 1 : S(3)
                d_local(:,i,ii,iii) = eig(squeeze(DHess_local(:,:,i,ii,iii)));
            end
        end
    end

    % assemble local results to a codistributed matrix
    d_dist = codistributed.build(d_local, codist);
end
toc

isequal(d, d_dist)
以及输出

Elapsed time is 0.364255 seconds.
sequential
Elapsed time is 33.498985 seconds.
parallel
Lab 1: 
  lab 1
Lab 2: 
  lab 2
Lab 3: 
  lab 3
Lab 4: 
  lab 4
Elapsed time is 9.445856 seconds.

ans =

     1

编辑我已检查了重塑矩阵的性能
DHess=[3x3xN]
。性能没有好多少(10%),因此它不是实质性的。但是,也许您可以以稍微不同的方式实现
eig
?毕竟,这些是您正在处理的
3x3
矩阵。

一次迭代需要多长时间?您是否正在打开matlabpool?@Jonas串行版本上的一次迭代(在变量i上)大约需要1.7秒。并行版本上的单个迭代无法在超过5分钟内完成,此时我已终止执行。@Rasman是的,我忘了提到我正在使用带有6个Labs的“本地”配置文件打开matlabpool。非常感谢您的回复。我忘了提到我正在使用6个实验室的“本地”配置文件打开matlabpool,但是使用串行版本进行一次迭代大约需要1.7秒,而并行版本不会在5分钟内完成一次迭代。操作(eig)本身不是多线程的,不需要这样,因为作为输入的矩阵只有3x3。不过,它可以将每个外环或内环分配给一个单独的核心,从而受益匪浅。我将尝试你提出的关于提取“本地部分”的想法,并向你汇报。很高兴你花时间提供了这个示例,因为我将能够在未来的许多项目中使用这些想法。有几个问题:我在代码中使用了“drange”,如果必须使用“getLocalPart”,它的用途是什么。使用您的代码,我得到一个错误:“在序列化过程中使用distcompserialize时出错”,行DHess_dist=codDistributed(DHess,codDistributor1d(3));我的输入D的大小大约是512x512x200,也许大小是个问题;虽然看起来数组有多大并不重要,因为这是并行处理的一个主要目的,但我也应该声明D是双精度的。@Hampycalc很抱歉,我显然没有注意到您使用了
drange
。我将编辑我的答案-毕竟你确实划分了你的工作。我的坏。@Hampycalc我已经尝试了其他维度的代码,它没有抱怨<代码中的code>D也是类型
double
,因此没有问题。我不使用
drange
提取矩阵的局部部分,以仅对局部数据进行显式操作。在你的例子中,你依靠MATLAB进行工作分解,这显然是相当糟糕的。是的,我会按照你的建议做,并在将来首先提取局部部分。我仍然像以前一样得到错误,但我将在别处寻找解决方案,因为您已经回答了我最初的问题。奇怪的是,我使用的是一个大于50GB内存的x64系统和Matlab2012A x64,所以如果是内存问题,我会感到惊讶。无论如何,再次感谢你的帮助。