为什么批处理模式比parfor快得多?

drj*_*rm3 8 performance matlab runtime parfor

我正在编写matlab代码来执行3维积分:

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
Run Code Online (Sandbox Code Playgroud)

对于关联的int3d_par(parfor)版本,我打开一个matlab池,只需for用a 替换parfor.我在更多内核上运行它得到了相当不错的加速(我的测试是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
Run Code Online (Sandbox Code Playgroud)

我注意到它更快,更快.为什么在批处理模式下进行此集成与执行此操作不同parfor

作为参考,我使用N从10和20这样的小数字(以获得运算符的多项式近似中的常数)来测试代码到更大的数字,如1000和2000.此算法将立即缩放,因为我分配了集成节点的数量theta并且phi方向是给定的常数倍N.

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

drj*_*rm3 1

在与支持人员交谈后Mathworks,我似乎对parfor工作原理产生了根本性的误解。我的印象parfor是,openMP批处理模式的作用类似于mpi共享内存与分布式内存。

事实证明,它parfor实际上也使用了分布式内存。当我创建 4 个批处理函数时,创建新进程的开销会发生 4 次。我认为使用 aparfor会导致该开销仅发生 1 次,然后parfor将在同一内存空间中发生。不是这种情况。

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