我写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.此算法将按比例进行三次化,因为我将数字在theta
和phi
方向上的积分节点的数量是给定的N
的常数倍数。
对于2000个节点,parfor
版本需要大约630秒,而批处理模式下相同数量的节点大约需要19秒(其中大约12秒仅仅是我们为10个集成节点获得的开销通信)。
哪个'for'你换成了parfor?它可能会在嵌套的循环结构中发挥作用(例如,碰到'parfor'并且多次引起并行性设置/拆卸开销,或者做的结果不是理想的片结构)。批处理版本代码似乎在到达并行调用时(即通过预先计算输入块并在每个块内部执行嵌套循环)将嵌套循环结构“展平”,这可能会降低并行开销。 –
另一件事是,如果我明白你在放置'parfor'的位置,那么批处理版本的数据传输量就会减少很多:它只是传递'r0','rf'和'rn'参数,中间变量是在每个worker上本地构造的,但'int3d_ser'内的'parfor'会导致在master上创建的临时变量的子集被编组并被发送给每个worker。 –
例如如果将'int3d_batch_cluster'函数替换为'parfor icore = 1:ncores'将'createTask'调用替换为'int3d_ser'的普通函数,会发生什么?这会告诉你它是否是parfor'机制本身,或者你的代码是如何隐含地构造要发送给工作人员的工作批次。 –