Matlab 简单的并行化运算

本文只是对于多核CPU运行单一程序的优化,以及简单的GPU运算(非CUDA)
部分内容引自:http://blog.sina.com.cn/s/blog_6b597bfb01018wa5.html
并行化计算通过client-workers体系,client负责分发任务,workers(数量等于CPU核数)负责完成任务

1、使用parfor循环

parfor循环把变量分为五类:循环变量*、广播变量临时变量分段变量以及简约变量
举例如下:

a = 100;
s = 0;
parfor k = 1 : 100 % k为循环变量

if a > 10 % 广播变量
b = 10; % 临时变量
end

c(k) = k; % 分段变量,输入属性
d = 1e3; % 临时变量
s = s + k; % 简约变量
end

循环变量:即代码中的k。
广播变量:该变量不是由worker产生,而是当client把任务分配给worker时传给worker的,每个worker都会接收到此类变量。
临时变量:在worker中产生,worker执行完任务之后clear掉,也不会传递给client的变量。
分段变量:这是parfor中最为重要的变量,可以具有输入和输出两类属性。
简约变量:循环执行的先后次序无关的操作在MATLAB中叫简约循环,也能在MATLAB中并行化。。

  • 并行开启(执行parfor语句自动开启)
  delete(gcp('nocreate'));     % 确保没有并行池运行 
  parpool ;                   %打开并行池
  parpool(2);                  %打开特定大小的池
  p = gcp;  delete(p);         %删除当前并行池
  • 首先使用for循环写好对于程序,在进行如下判断

若要并行,必须满足以下2个条件之一:每次循环之间是相互独立的;循环执行完之后的结果和循环执行的先后次序无关。

  • 加速要点
  • 并行运算变量不需要预先分配内存空间;因为一旦在parfor之前预分配内存了,该分段变量就具备了输入属性,已在client中生成了,client再将其分段传递给不同的worker,这会消耗额外的时间。所以,我们的原则是:分段变量能不增加输入属性就不增加。(只针对并行运算)

一般编程注意
1、多使用列向量。
2、a(a>0.5) = 0; % 逻辑索引、a(find(a>0.5)) = 0; % 数值索引、毫无疑问,前者的代码执行速度更快。
3、对于通信算法SNR仿真,可以使用break语句,在性能符合要求的SNR跳出。

  • 直接将for改为parfor,根据提示修改程序
    一般被赋值变量的索引应该从1开始且顺序存储,被调用广播变量等也尽量从1开始。(经验)

    2、简单的GPU加速

    • 将需要GPU运算的变量使用gpuArray()转换写入GPU,在GPU计算完成后使用gather()将需要收集的变量读入Matlab工 作区内存空间进行下一步操作。(考虑到内存读写,此方法只对某些方法加速效果良好)
    • 使用arrayfun()函数
      1、例:d = arrayfun(@myfunction,a,b,c);,myfunction为当前调用函数,在GPU进行处理,a、b、c为输入gpuArray类型参数(可以按照函数要求添加多个参数,每个参数维度一致;如果c不是gpuArray类型,函数运行开始将自动转为gpuArray)。
      2、使用gather可以收集d。不支持数组输出(标量输入输出)。

非gpuArray情况
1、支持数组输出(如输入参数a、b、c分别为1、2、3;输出为[1,2],'UniformOutput’设置为‘false’),输出为cell类型;对于cell类型,通过()访问cell数组时访问到的是cell单元,通过{}访问cell数组时访问到的是cell单元储存的内容。
2、同理数组输入也需要使用cell类型,或者struct结构体;
3、可以使用num2cell(matrix,dismension),将输入矩阵转为cell类型,将dismension维度合并,如A为3x2矩阵,2维度,转换后B为3x1cell类型,B{1} = A(1,:) 。
4、对于结构体类型,例a(1).x = [1 2];a(2).x = [ 2 3];以a输入,a.x读取即可。

%% 定义函数
function a = add(b,c)
a = b + c;
end
%% arrayfun 三种函数使用方法
l = @(b,c) b+c;
d = arrayfun(@add,[1 2 3],[2 3 4]) ;       
d = arrayfun(@(b,c) b+c,[1 2 3],[2 3 4]) ;
d = arrayfun(l,[1 2 3],[2 3 4]) ;
%%gpuArray
d = arrayfun(l,gpuArray([1 2 3]),gpuArray([2 3 4])) ;(输入输出均为标量)

3、batch批处理

  • 主要用于集群等,简单语句说明一下,未深入了解
job = batch('mywave');      %批处理,不阻塞当前程序继续运行,使用默认集群
%可以设置'Pool'参数,定义使用并行池数量,需要先关闭之前开启的并行池
wait(job)                   %强行阻塞等待
diary(job);                 %打印子程序的打印信息Command Window Output
load(job,'A');              %加载job中变量到当前工作区,原始数据类型
delete(job);                %删除数据
clear job;                  %删除工作空间

job_function = batch(fcn,N,{x,y,z,...});          %批处理函数,fcn为函数句柄,N为输出参数数量,x,y,z,...为输入参数
%可以设置'Pool'参数,定义使用并行池数量,需要先关闭之前开启的并行池
wait(job_function);
if(job_function.State == 'finished')
   job_function_out = fetchOutputs(job_function); % 加载返回数据到工作区,cell类型
   class(job_function_out{1})                     %返回数据类型
end

微信公众号:通信随笔XIDIAN

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xidian_hxc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值