在使用matlab处理大数据,编程需要注意两个问题:并行运算和释放内存。matlab也提供了并行计算的功能,甚至能用GPU加速。并行计算工具箱,叫做parallel computing toolbox.它的使用方法,可以从matlab的帮助获得。
Parallel Computing Toolbox(并行计算工具箱)中加入了并行循环parfor-loops,对于每一步可以独立于其他步的循环,计算效率可以有较大幅度的提高。以前简单的for循环for-loop是顺序的(sequentially)执行每一步循环体(statement),parfor-loop是通过将各个循环体分配到不同的节点上进行并行计算。所以parfor的要求是循环体之间相互独立,结果各不影响,Matlab的编辑器会自动帮你检查循环体的结果是否影响。
当你初始化一个matlab进程时,这个进程被称为Matlab Client,它起着和用户交互和调度的作用。在并行计算工具箱中,通过matlabpool可以打开多个matlab进程,这些进程被称为Matlab Worker。并行循环parfor-loop的各个循环就是随机的分配到这些Matlab Worker上进行同时的计算。最后再返回给Matlab Client. 在一个多核桌面上可以本地同时运行四个 worker ,如果与 MATLAB Distributed Computing Server 集成,就可以使用集群中任意数量的机器作为worker了。
parfor就是paralle+for,也就是并行的for循环,怎么个并行法?简单理解就是,matlab会弄出几个虚拟的小pc,比如一个算i=1:50部分循环,一个算i=51:90部分循环,再来一个算i=91:100部分循环,当然数字是瞎编的,这主要想说matlab将一个大循环分成小块,然后这些小块并行计算,最后再合在一起。这样有一个问题,因为普通的循环是从i=1算到i=100,一个接一个算,如果下一次循环要依赖上一次循环怎么办?如果出现这种情况,那就不能用matlab的parfor了。用parfor的前提条件就是,循环的每次迭代独立,不相互依赖。
parfor关键字的使用
(1). 由于for关键字引导的循环通常为串行运行,如果改为parfor则可以由多个worker以并行方式执行。
(2). parfor可以将n次循环分解为独立不相关的m部分,然后将各部分分别交给一个worker执行。
(3). 循环执行的结果应该与n次循环执行的顺序无关。
parfor中的变量类型
(1). 简约变量
一般parfor中各次循环对应的运算应该相互独立,但简约操作可以在多次循环内同时对一个变量操作。这种变量称为简约变量。例如下方代码中a就是简约变量。
a = 0;
for i = 1:1000a = a+i;
end
简约操作包括+ - * .* & | [,] [;] {,} {;} min max union intersect。
同一个parfor循环对简约变量的操作必须一致,即必须是同一种简约操作符。而且与操作符的相对位置也必须一致。
简约变量赋值表达式应该满足结合律和交换律。* [] {}底层有特殊处理保证结果的正确性。
(2). 切片变量
parfor中可能需要读取或写入parfor之外的矩阵,读取写入位置与循环变量相关。这样就需要向worker传输大量的数据。
矩阵如果被Matlab识别为切片变量,则数据可以分段传输到各worker,提高传输效率。
切片变量矩阵的大小是不可在parfor中改变的,且为了保证Matlab识别正确,每次循环中只能读取由同一个索引值索引的切片,如a[i] a[i+1]同时出现则a不被识别为切片变量。
(3). 临时变量
作用域局限于parfor内,parfor结束后不存在。不影响parfor之前声明的同名变量。
(4). 循环变量
如上例中的i,表示当前循环的id。
(5). 广播变量
在parfor之前赋值,在parfor内只进行读取操作。
(6). 各种变量区分的例子
下例中,parfor中的tmp是临时变量,parfor结束后tmp的值依然是5,不受临时变量的影响。
broadcast是广播变量,每次循环中的值不变。
redued是简约变量,Matlab对其的值将分段由各worker计算后送回主进程处理。
sliced为切片变量,数据传输有优化提升。
i为循环变量
tmp = 5;
broadcast = 1;
reduced = 0;
sliced = rand(1, 10);
parfor i = 1:10tmp = i;reduced = reduced + i + broadcast;sliced(i) = sliced(i) * i;
end
worker配置
在运行程序之前,需要配置worker。否则如前文所说,parfor循环将以普通for循环的形式运行,无法并行。
启动和关闭并行计算功能
启动:
CoreNum=7; %调用的处理器个数
if matlabpool('size')<=0 %之前没有打开matlabpool('open','local',CoreNum);
else %之前已经打开disp('matlab pool already started');
end
关闭:
matlabpool close
如果代码还在调试阶段,可以暂时不关闭matlabpool,反复开关浪费时间得很。另外,matlab关闭后,matlabpool也会自动关闭,所以如果不是海量代码,可以不用关闭的
一个使用parfor-loop的例子:
%example of parfor-loop
%本地worker数通常等于cpu的核数
matlabpool open local 2;
parfor i=1:1024
A(i) = sin(i*2*pi/1024);
end
plot(A);
matlabpool close;
这里讲述的方法仅针对多核机器做并行计算的情况。设机器的CPU核心数量是CoreNum双核机器的CoreNum2,依次类推。CoreNum以不等于核心数量,但是如果CoreNum小于核心数量则核心利用率没有最大化,如果CoreNum大于核心数量则效率反而可能下降。因此单核机器就不要折腾并行计算了,否则速度还更慢。
matlab使用并行计算常出现的问题
(1). 用parfor的运算时间反而比用for的时间更长
parfor 对于执行时间很短的循环没有时间提升甚至会更慢,因为把任务分配到每一个并行线程里面也要时间,说白了就是核心程序耗时太短,分配任务以及matlab和worker之间的通信可能占据了主要时间。好比去坐飞机到一个地方,如果机场比较远,而且要去的目的地不是很远,虽然飞机节约下来时间,但是去机场路上的时间就把省下来的时间又耗出去了。要计算足够复杂的问题才能看出提速的效果,简单的计算反而更慢。
(2). matlab并行运算错误,透明度违例错误
Error using parallel_function. Transparency violation error. See Parallel Computing Toolbox documentation about Transparency.
可能循环程序中使用了clear, 可将需要clear掉的编程,使用空集来代替。比如
clear A 换成 A= []; 注意 A在程序中的位置。
下面给出查询CPU信息。
Linux 关于如何查询CPU核心数
(1). 查看逻辑CPU个数
cat /proc/cpuinfo |grep "processor"|sort -u|wc -l
(2). 由于有超线程技术有必要查看一下物理CPU个数
grep "physical id" /proc/cpuinfo|sort -u|wc -l
grep "physical id" /proc/cpuinfo|sort -u
(3). 查看每个物理CPU内核个数
grep "cpu cores" /proc/cpuinfo|uniq
(4). 每个物理CPU上逻辑CPU个数
grep "siblings" /proc/cpuinfo|uniq
(5). 判断是否开启了抄超线程
如果多个逻辑CPU的”physical id”和”core id”均相同,说明开启了超线程
或者换句话说
逻辑CPU个数 > 物理CPU个数 * CPU内核数 开启了超线程
逻辑CPU个数 = 物理CPU个数 * CPU内核数 没有开启超线程
(6). 一次性查询所有信息
#!/bin/bash
physicalNumber=0
coreNumber=0
logicalNumber=0
HTNumber=0logicalNumber=$(grep "processor" /proc/cpuinfo|sort -u|wc -l)
physicalNumber=$(grep "physical id" /proc/cpuinfo|sort -u|wc -l)
coreNumber=$(grep "cpu cores" /proc/cpuinfo|uniq|awk -F':' '{print $2}'|xargs)
HTNumber=$((logicalNumber / (physicalNumber * coreNumber)))echo "****** CPU Information ******"
echo "Logical CPU Number : ${logicalNumber}"
echo "Physical CPU Number : ${physicalNumber}"
echo "CPU Core Number : ${coreNumber}"
echo "HT Number : ${HTNumber}"echo "*****************************"
下面给出判断电脑的系统性能,并开启并行运算
%--------------------------------------------------------------------------
clear;clc;close all%--------------------------------------------------------------------------
% Load an example dataset provided with matlab
load house_dataset
In = houseInputs';
Out = houseTargets';%--------------------------------------------------------------------------
% Find capabilities of computer so we can best utilize them.% Find if gpu is present
ngpus=gpuDeviceCount;
disp([num2str(ngpus) ' GPUs found'])
if ngpus>0lgpu=1;disp('GPU found')useGPU='yes';
elselgpu=0;disp('No GPU found')useGPU='no';
end% Find number of cores
ncores=feature('numCores');
disp([num2str(ncores) ' cores found'])% Find number of cpus
import java.lang.*;
r=Runtime.getRuntime;
ncpus=r.availableProcessors;
disp([num2str(ncpus) ' cpus found'])if ncpus>1useParallel='yes';
elseuseParallel='no';
end[archstr,maxsize,endian]=computer;
disp([...'This is a ' archstr ...' computer that can have up to ' num2str(maxsize) ...' elements in a matlab array and uses ' endian ...' byte ordering.'...])% Set up the size of the parallel pool if necessary
npool=ncores;% Opening parallel pool
CoreNum=npool; %调用的处理器个数
if matlabpool('size')<=0 %之前没有打开matlabpool('open','local',CoreNum);
else %之前已经打开disp('matlab pool already started');
end
方法二,直接替换 %Opening parallel pool 下面的代码即可
% Opening parallel pool
if ncpus>1ticdisp('Opening parallel pool')% first check if there is a current poolpoolobj=gcp('nocreate');% If there is no pool create oneif isempty(poolobj)command=['parpool(' num2str(npool) ');'];disp(command);eval(command);elsepoolsize= poolobj.NumWorkers;disp(['A pool of ' poolsize ' workers already exists.'])end% Set parallel optionsparoptions = statset('UseParallel',true);tocend
本文参考:
http://blog.sina.com.cn/s/blog_6295beb60101dl8o.html
http://blog.csdn.net/yuzg86/article/details/7542056
http://www.ilovematlab.cn/thread-332708-1-1.html
http://zhidao.baidu.com/question/1367310944286874379.html
http://blog.csdn.net/caozhk/article/details/38234293?utm_source=tuicool&utm_medium=referral
http://blog.sina.com.cn/s/blog_866e7fa70101cv08.html
http://blog.renren.com/share/254666329/11478405569?from=0101010202&ref=hotnewsfeed&sfet=102&fin=6&ff_id=254666329
http://blog.sina.com.cn/s/blog_45eac6860100lzlk.html
http://www.cnblogs.com/dongzhiquan/archive/2012/02/16/2354977.html