首页 > 解决方案 > 将双循环并行化为数组作业(Matlab + bash)

问题描述

我在 Matlab 中有一个双循环。我希望您的帮助将其作为数组作业bash 文件并行化为我大学 HPC中的qsub

重要 1:我不能使用 parfor,因为我没有 Matlab 并行工具箱。

重要2:请不要太注意代码的内容。这是一个愚蠢的例子,它显然不需要任何并行化。我的实际代码要复杂得多,我不能在这里报告。我可以向您保证,并行化作为数组作业是针对我的具体案例最有效的解决方案。


这是我想要并行化的原始 Matlab 文件。

clear
rng default

m=4;
n=2;
A=randn(m,n);
g=5;
B=randn(g,n);

result=cell(m,1);
for i=1:m %LOOP 1
    result{i}=zeros(g,n);
    for h=1:g %LOOP 2
        result{i}(h,:)=A(i,:)+B(h,:);
    end
end

我知道如何将外循环(LOOP 1)作为数组作业并行化。我可以这样做。

1) 文件 main.m

clear
rng default

m=4;
n=2;
A=randn(m,n);

g=5;
B=randn(g,n);

workers=m; %number of parallel workers
jobs=1; %number of jobs per parallel worker

2) 文件 f_s.m

%% Select local part of A
idtemp=str2double(getenv('SGE_TASK_ID'));
A_local=A(jobs*(idtemp-1)+1: idtemp*jobs,:);

%% Do the job
result=zeros(g,n);
for h=1:g
    result(h,:)=A_local+B(h,:);
end

%% Save the job                      
filename = sprintf('result.%d.mat', ID);
save(filename,'result')  

2) qsub 在 HPC 终端中的以下 bash 文件:

#$ -S /bin/bash
#$ -l h_vmem=3G
#$ -l tmem=3G
#$ -l h_rt=480:0:0
#$ -cwd
#$ -j y

#Run 4 tasks where each task has a different $SGE_TASK_ID ranging from 1 to 4
#$ -t 1-4

#$ -N example
date
hostname


#Output the Task ID
echo "Task ID is $SGE_TASK_ID"

/share/apps/matlabR2018b/bin/matlab -nodisplay -nodesktop -nojvm -nosplash -r "main; ID = $SGE_TASK_ID; f_s; exit"

问题:如何使用上述相同的数组作业技术NOT PARFOR )并行化内部循环(LOOP 2 )?基本上,我想从f_s.m. 我不确定的是如何设置新的 SGE_TASK_ID。

标签: bashmatlab

解决方案


您说“不适合”,但我将忽略这一点,因为您的评论表明(至少对我而言)这parfor绝对是适合这里工作的工具(我会说,当我编写我要介绍的功能时建议您使用 ;) )。但我将保持简短,因为如果您没有可用的 MATLAB Parallel Server 许可证,那么以下内容将无法解决。但是,如果 MATLAB Parallel Server 可用,您会执行以下操作。(这将在幕后使用 SGE 作业数组,并让您使用漂亮的parfor语法进行设置)

  1. 将您的代码构建为一个parfor循环,并在本地进行测试以确保它在小范围内都能正常工作
  2. 按照此处的说明设置您的客户端,使其可以与您的 SGE 集群通信。
  3. 使用parforOptions扩大到直接在集群上运行parfor循环,有点像这样。

pfo = parforOptions(parcluster('mySgeProfile'));
parfor (idx = 1:N, pfo)
    out(idx) = myLongRunningThing(idx);
end

parforOptions对象使您可以对集群上的运行方式进行大量自定义。


推荐阅读