2015-04-17 33 views
8

我写MATLAB代码进行3维积分:为什么批处理模式比parfor快得多?

function [ fint ] = int3d_ser(R0, Rf, N) 
Nr = N; 
Nt = round(pi*N); 
Np = round(2*pi*N); 

rs = linspace(R0, Rf, Nr); 
ts = linspace(0, pi, Nt); 
ps = linspace(0, 2*pi, Np); 

dr = rs(2)-rs(1); 
dt = ts(2)-ts(1); 
dp = ps(2)-ps(1); 

C = 1/((4/3)*pi); 
fint = 0.0; 
for ir = 2:Nr 
    r = rs(ir); 
    r2dr = r*r*dr; 
    for it = 1:Nt-1 
    t = ts(it); 
    sintdt = sin(t)*dt; 
    for ip = 1:Np-1 
     p = ps(ip); 
     fint = fint + C*r2dr*sintdt*dp; 
    end 
    end 
end 

end 

的相关int3d_par(PARFOR)版本,我打开MATLAB游泳池,只是一个parfor更换for。我在更多内核上运行它时速度非常快(我的测试是从2到8个内核)。

然而,当我运行在批处理模式相同的积分有:

function [fint] = int3d_batch_cluster(R0, Rf, N, cluster, ncores) 

%%% note: This will not give back the same value as the serial or parpool version. 
%%%  If this was a legit integration, I would worry more about even dispersion 
%%%  of integration nodes per core, but I just want to benchmark right now so ... meh 

Nr = N; 
Nt = round(pi*N); 
Np = round(2*pi*N); 

rs = linspace(R0, Rf, Nr); 
ts = linspace(0, pi, Nt); 
ps = linspace(0, 2*pi, Np); 

dr = rs(2)-rs(1); 
dt = ts(2)-ts(1); 
dp = ps(2)-ps(1); 

C = 1/((4/3)*pi); 

rns = floor(Nr/ncores)*ones(ncores,1); 
RNS = zeros(ncores,1); 
for icore = 1:ncores 
    if(sum(rns) ~= Nr) 
    rns(icore) = rns(icore)+1; 
    end 
end 
RNS(1) = rns(1); 
for icore = 2:ncores 
    RNS(icore) = RNS(icore-1)+rns(icore); 
end 

rfs = rs(RNS); 
r0s = zeros(ncores,1); 
r0s(2:end) = rfs(1:end-1); 

j = createJob(cluster); 

for icore = 1:ncores 
    r0 = r0s(icore); 
    rf = rfs(icore); 
    rn = rns(icore); 
    trs = linspace(r0, rf, rn); 
    t{icore} = createTask(j, @int3d_ser, 1, {r0, rf, rn}); 
end 

submit(j); 
wait(j); 
fints = fetchOutputs(j); 

fint = 0.0; 
for ifint = 1:length(fints) 
    fint = fint + fints{ifint}; 
end 

end 

我发现它是非常快了很多。为什么要在批处理模式下进行这种集成与在parfor中进行集成不同?

作为参考,我测试了代码N从小数字如10和20(以获得运行时的多项式近似中的常量)到更大的数字,如1000和2000.此算法将按比例进行三次化,因为我将数字在thetaphi方向上的积分节点的数量是给定的N的常数倍数。

对于2000个节点,parfor版本需要大约630秒,而批处理模式下相同数量的节点大约需要19秒(其中大约12秒仅仅是我们为10个集成节点获得的开销通信)。

+2

哪个'for'你换成了parfor?它可能会在嵌套的循环结构中发挥作用(例如,碰到'parfor'并且多次引起并行性设置/拆卸开销,或者做的结果不是理想的片结构)。批处理版本代码似乎在到达并行调用时(即通过预先计算输入块并在每个块内部执行嵌套循环)将嵌套循环结构“展平”,这可能会降低并行开销。 –

+1

另一件事是,如果我明白你在放置'parfor'的位置,那么批处理版本的数据传输量就会减少很多:它只是传递'r0','rf'和'rn'参数,中间变量是在每个worker上本地构造的,但'int3d_ser'内的'parfor'会导致在master上创建的临时变量的子集被编组并被发送给每个worker。 –

+0

例如如果将'int3d_batch_cluster'函数替换为'parfor icore = 1:ncores'将'createTask'调用替换为'int3d_ser'的普通函数,会发生什么?这会告诉你它是否是parfor'机制本身,或者你的代码是如何隐含地构造要发送给工作人员的工作批次。 –

回答

1

Mathworks支持后说,看来我当初如何parfor工作的根本误解。我的印象是,parfor的行为如同openMP,而批处理模式在共享vs分布式内存方面的表现像mpi

原来,parfor实际使用分布式存储器。当我创建4个批处理函数时,创建新进程的开销发生了4次。我认为使用parfor会导致这种开销仅发生一次,并且parfor将发生在同一个内存空间中。不是这种情况。

在我的示例代码中,事实证明,对于parfor的每次迭代,我实际上都会产生创建新线程的开销。当比较“苹果与苹果”时,我应该真的创建相同数量的批次调用,因为我在parfor循环中进行迭代。这就是为什么parfor函数花费的时间更长 - 我为多处理造成了更多的开销。

+0

这是否意味着批处理模式比parfor更快? –

相关问题