Matlab并行计算方法(下)

       上次咱们谈到了Matlab的并行计算,用的是parfor的并行方式,详情查看:Matlab并行计算方法(上)。

       parfor并行计算比较方便,但是也要注意几点:一是分配给每个核的任务不能有相互调用,否则会出问题;二是存放数据的数组需要预分配,在这里要注意,预分配的数组只能是向量的形式,二维的数组不能用来存放数据,至少我在使用时出现了这种情况,解决方法就是先开一个一维向量存放数据,然后再根据需要转成二维的数组。

       科研中并行计算不限于导师给的(破)台式机,一般这些台式机的CPU核心数不会很多,开不了太多线程来跑程序,这样子进行测试还可以,如果要进行大量的计算(比如参数扫描)的话,恐怕还是不太够,那么这时候就需要把任务提交到学校的服务器上进行计算。这时候并行计算用parfor就不太方便,事实上,在服务器上调用parfor只能在管理节点上进行计算,这样不太好,除非你就是管理员。

       那么废话不多说,我们来看一下如何在服务器上运行matlab

1、安装

       要想跑matlab程序,那你首先要在服务器上安装matlab,这里不讲安装的事情,可自行百度或者联系管理员安装,如果自行安装强烈建议安装破解版matlab,因为学校的服务器不一定能连接外网;并且破解版功能全面,安装较快。

2、编写程序

       这里我会详细的说明相应的流程,请各位看的仔细一点。

2.1、将程序封装成函数

       譬如我写了一段计算的代码,接下来我想要放到服务器上并行计算,那么第一步我就要封装自己写的代码,比如:

function c = myCode(a)
  xxx;
  xxx;
  xxx;
  xxx;
  c = xxxxx;
end

       这里的xxx就是你自己写的代码,c是你输入参数a从而想要得到的输出结果,封装函数的好处有两个:一是可以随时随地调用;二是分离代码,使得整个代码框架变得简洁易懂。这一步不难,学过python或者C的同学应该十分清楚。

2.2、编写并行计算框架

       函数封装之后,接下来是最重要的并行计算框架搭建:

       首先规定你要调用的计算机核数:

% 比如你要调用30个核心,这里cpu_core只是一个变量名而已,没有其他意思
cpu_core = 30;

       接下来采用函数parcluster创建一个集群:

c = parcluster();

       注意这里不像之前是创建进程池parpool哦!

       然后规定这个集群上的核心数,aka你之前创立的核心数变量:

c.NumWorkers = cpu_core;

       在这个集群之上创建job

job = createJob(c);

       到这里,革命已经成功了一半,剩下的是根据你自己的程序来改写,这里举个例子:

       比如我需要扫描参数a_scan,该参数范围:,也就是说我要把参数a_scan扫描100次(),根据输入的不同a来得到不同的c,那么程序可以这么写:

for i = 1:length(a_scan)
  a = a_scan(i);
  parameter = {a};
  t = createTask(job,@myCode,1,parameter)
end

       OK,我知道各位想赶紧编写程序的同学已经迷糊了,这里解释一下:

       首先for循环是很清楚的,就是每次提取一个参数a然后把函数放在某个核上面跑(是哪个核不用管)。

       然后,parameter这个玩意,正如其名,就是你自己的函数myCode的参数。

最后,在job上创建一个taskcreateTask这个函数有这么几个参数:

  • 第一个参数是你创建的job,这个不用作改动

  • 第二个参数是调用刚才你封装的函数myCode,要注意有一个@.

  • 第三个参数是:你调用的函数需要返回的参数个数,比如说,这里你的函数myCode由于只有一个参数c需要返回,所以你就写上1就可以了,记住是返回的参数个数!

  • 最后一个参数就是函数的输入参数,也就是刚才定义的parameter.

       有人可能觉得我这里这个parameter非常多余,相信我,如果你的参数有10个以上,这绝对不是多余的,要时刻记住代码的可读性简洁性是非常重要的,方便自己也方便他人阅读。

       编写完这个,最后再加上几个函数:

 % 提交job
submit(job);
 
 % 等待服务器算完结果
wait(job);
 
 % 提取结果
output = fetchOutputs(job);

最后千万别忘了保存计算结果!

% save函数保存结果,注意都需要引号
save("myData.mat","output")

       那么并行计算框架就搭好了!接下来通过pbs作业脚本提交到服务器上就可以运行了!


3、总结

       读者诸君不难发现,这里的并行计算实际上可以分为三部分:

       1. 创建集群,并在集群上创建job

       2. 根据自己的情况根据参数依次分配任务

       3. 提交任务


       第一部分不需要作太多改动,只要改动你需要的核心数cpu_core

       第二部分则需要作出改动,但是思路已经全部告诉各位了

       第三部分不需要改动(当然你可以改动保存的文件名称)


4、附录

       最后附上整个框架:

 % 第一部分
cpu_core = 30;
 
c = parcluster();
 
c.NumWorkers = cpu_core;
 
job = createJob(c);
 
 % 第二部分
a_scan = 0:0.01:100;

for i = 1:length(a_scan)
  a = a_scan(i);
  parameter = {a};
  t = createTask(job,@myCode,1,parameter);
end
 
 % 第三部分
submit(job);

wait(job);

output = fetchOutputs(job);
save("myData.mat","output")
 
 %% =======================封装的函数============================
function c = myCode(a)
  xxx;
  xxx;
  xxx;
  xxx;
  c = xxxxx;
end

       上面这个是最为简单的并行计算的框架,请各位根据自身的情况酌情修改,有问题可以在下面留言讨论。
       另外:上的markdown显示出来的结果比较奇怪,比如英文字母和中文大小不一样;代码的颜色变化显得支离破碎,我在typora上编写时不是这样的,请读者谅解。

你可能感兴趣的:(Matlab并行计算方法(下))