上次咱们谈到了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
上创建一个task
,createTask
这个函数有这么几个参数:
第一个参数是你创建的
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
上编写时不是这样的,请读者谅解。