Re: [讨论] for循环改用.cpp的mex函数加速问题

楼主: celestialgod (天)   2016-02-23 20:11:28
※ 引述《w0005151 (蓝厅)》之铭言:
: 各位先进好
: 小弟用matlab写FDTD(一种将电磁波的偏微分方程离散化求解的数值方法)
: 这个程式的架构很简单
: 一开始先定义完各项参数后最后以一个for循环作结
: 循环里面做的事情为矩阵运算
: 大概长得像这样
: for t=1:tnum %tnum大约为10000~50000
: Ez(a:b,c:d)=A.*Ez(a:b,c:d)+B.*(Hx(a+1:b+1,c:d)-Hx(a:b,c:d));
: Hx(a:b,c:d)=C.*Hx(a:b,c:d)+D.*(Ez(a+1:b+1,c:d)-Ez(a:b,c:d));
: end
: Ez,Hx,A,B,C,D都是矩阵
: 他们的大小视运算需求为定
: 循环里面没有其他循环
: 就只是把几个矩阵做叠代运算而已
: 当然实际的code循环里不是只有两行而已
: 大约有10行左右,全都是这类的运算
: 一般来说这些矩阵的大小在600*600以内的计算速度都还可以接受
: 但是到1000*1000以上后又要跑较大的tnum时就会满慢的了
: 最大的问题是这个程式写到三维版本时,这些矩阵全部变成三维矩阵
: 循环仍然为单一循环里,但运算式的量也大约变成三倍,其计算速度令人难以接受
: 曾经跑过一个三维的版本,矩阵大小约为500*400*100
: 一跑下去没个三天以上是不会好的
: 最近在想因为matlab可以使用以C/C++编译的.mex档函数
: 我想知道若把这个for循环全部包成一个.mex档执行的话能明显提升运算速度吗
: 虽然在simulink的时候把一些功能包成C的S-function的确大大提升速度
: 但二维矩阵运算用C的话每个运算都会变成两层的循环
: 三维就变成三层...我实在不确定这样能否提升效率
: 因为这是一个满浩大的工程所以不想要到最后做半天反而速度更慢
: 有大大能提供意见吗?感激不尽
MatLab code: http://pastebin.com/FvSHk45D (test_c.cpp后来懒惰没写)
C++ code: http://pastebin.com/tfYwbhBA
environment: i7-5820K@4.0GHz, windows 7 SP1, Visual Studio 2013,
Intel Parallel Studio XE 2015, MatLab R2015b, armadillo 6.5000.5
MatLab版本: Elapsed time is 60.614941 seconds.
C++版本: Elapsed time is 48.771419 seconds.
C++版本,我比较偷懒直接用armadillo的class比较快,就不用手写一个个乘...
看的出来,只是每个矩阵对乘加速有限
最后,如果用GPU的话,加速效果较佳
下面测试是用i7-3770K@4.4GHz with nVidia GTX 670
% MATLAB gpu
Ez_gpu = gpuArray(Ez);
Hx_gpu = gpuArray(Hx);
A_gpu = gpuArray(A);
B_gpu = gpuArray(B);
C_gpu = gpuArray(C);
D_gpu = gpuArray(D);
tic
for t=1:tnum
Ez_gpu(a:b,c:d)=A_gpu.*Ez_gpu(a:b,c:d) + ...
B_gpu.*(Hx_gpu(a+1:b+1,c:d)-Hx_gpu(a:b,c:d));
Hx_gpu(a:b,c:d)=C_gpu.*Hx_gpu(a:b,c:d) + ...
D_gpu.*(Ez_gpu(a+1:b+1,c:d)-Ez_gpu(a:b,c:d));
end
toc
gpuArray: Elapsed time is 7.242466 seconds.
PS: 编译所需的intel_cpp_15_vs2013.xml来自:
https://gist.github.com/amroamroamro/414abe0b2a6002cd8945
作者: sunev (Veritas)   2016-02-23 21:18:00
用GPU应是正解,另外自己写mex的问题是,没办法多核心这种BLAS程度的东西,matlab应该有多核心喔喔,但是intel mkl要再花钱买?不过gpu也是要花钱买显卡就是了....

Links booklink

Contact Us: admin [ a t ] ucptt.com