Matlab GPU文档格式.docx
- 文档编号:16958824
- 上传时间:2022-11-27
- 格式:DOCX
- 页数:20
- 大小:29.44KB
Matlab GPU文档格式.docx
《Matlab GPU文档格式.docx》由会员分享,可在线阅读,更多相关《Matlab GPU文档格式.docx(20页珍藏版)》请在冰豆网上搜索。
0.036;
height
0.027;
x_min
0.34;
y_min
0.57;
x_r
/
im_w;
y_r
im_h;
max_iter
128;
tic
Z0
bsxfun(@plus,
...
linspace(x_min,
x_min+width-x_r,
im_w),
1j
*
linspace(y_min+height-y_r,
y_min,
im_h).'
output
calcidx(input)
calc
index
value
for
each
element
in
Z0
z
0;
k
0
:
max_iter-1
+
input;
if
abs(z)
>
2,
break;
end
k;
end
idx
arrayfun(@calcidx,
Z0);
toc
figure;
imshow(idx,
map);
deltas
(idx
-
double(I)).'
;
deltas(deltas
==
0)
[];
+16)
-16)
1;
reshape(deltas,
[23,
73]);
imshow(imresize(deltas.'
10,
'
box'
));
看看其中矩阵Z0的构造和idx的计算,我觉得都挺适合并行化的。
就拿Level31开刀,试试GPUPoweredMatlab到底有多厉害。
问题一解决。
问题二:
如何在Matlab中使用GPU?
之前没有做过,同时完全的CUDA零经验。
粗略看看MatlabParallelToolbox,意外地发现好像并不难。
立刻开工,开始对之前的level31.m进行修改,意外地发现只做了极少的修改,代码速度就获得了极大的提升!
代码如下:
level31_gpu
Powered
2013.03.24
PM
09:
08
gpuArray.linspace(x_min,
gpuArray.linspace(y_min+height-y_r,
Create
matrix
and
put
the
memory
of
GPU
complex(0,
0);
For
GPU.
Declare
that
is
a
complex
number.
Initialize
k,
or
there
will
be
error
gather(idx);
Data
transfer.
GPU'
s
=>
CPU'
与之前的代码相比,有如下的几处改动
一、构造矩阵Z0时,使用gpuArray的静态方法linspace在显存上创建了数组。
不需要对bsxfun进行修改,因为一旦参数包含gpuArray类型,Matlab会自动使用对应的bsxfun。
二、在calcidx中,对k和z进行了初始化。
如果不初始化k,会报错:
ErrorusinggpuArray/arrayfun
Useofapotentiallyuninitializedvariable(s):
k
erroratline:
37
如果不使用complex函数初始化z,会报错:
Variable'
z'
changedcomplexity.ConsiderdeclaringitCOMPLEXbeforelooporif-elsebody.erroratline:
35
由于这里的calcidx会被arrayfun施加到gpuArray的实例上,因此它再也不是一个普通的Matlab函数了,而是一个kernel。
我猜Matlab的ParralelToolbox采用了类似Aparapi的机制,由字节码反推AST,再遍历AST生成可被GPU执行的代码。
三、计算完成后,使用gather将显存中的结果导入到内存中
由于普通的,和GPU加速的代码都加了计时代码tic-toc,看看效果。
我现在很紧张,因为之前听说过很多GPU加速大失败的案例,而且我也没什么这方面的经验,虽然之前在《玩了玩ATIStream》小试过一把,不过失败了。
几次level31.m的运行结果
clearall
level31
Elapsedtimeis1.705742seconds.
Elapsedtimeis1.711330seconds.
Elapsedtimeis1.730576seconds.
Elapsedtimeis1.707733seconds.
Elapsedtimeis1.717991seconds.
再看看level31_gpu.m的效果
Elapsedtimeis1.029675seconds.
Elapsedtimeis0.021065seconds.
Elapsedtimeis0.021019seconds.
Elapsedtimeis0.021232seconds.
Elapsedtimeis0.021126seconds.
第一次不怎么快(应该是编译消耗了不少时间),之后,和CPU版的level31.m相比,它就像是注射了类固醇的种马一样。
忘了说一句,CPU是i7-3770。
GPU的相关信息如下
gpuDevice
ans=
CUDADevicewithproperties:
Name:
'
GeForceGTX660'
Index:
1
ComputeCapability:
3.0'
SupportsDouble:
DriverVersion:
5
ToolkitVersion:
MaxThreadsPerBlock:
1024
MaxShmemPerBlock:
49152
MaxThreadBlockSize:
[1024102464]
MaxGridSize:
[2.1475e+096553565535]
SIMDWidth:
32
TotalMemory:
1.6106e+09
FreeMemory:
1.3412e+09
MultiprocessorCount:
6
ClockRateKHz:
888500
ComputeMode:
Default'
GPUOverlapsTransfers:
KernelExecutionTimeout:
CanMapHostMemory:
DeviceSupported:
DeviceSelected:
没有对之前的level31.m做什么重大的修改,就实现了GPU加速,这真是一件令人心旷神怡的事情。
Matlab
(二)
itmatlabgpupythonchallenge
《GPUPoweredMatlab
(一)》中,第一次试验了在Matlab中使用GPU计算,结果非常令人满意,仅仅对代码进行了细微的修改,就实现了大约80倍的提速。
所以今天又小小的尝试了一番。
用什么作为试验的任务呢?
还是想起了PythonChallenge,因为其中包含了不少图像处理的关卡。
就拿Level16开刀吧。
这一关有一副图像,需要根据粉红色块的位置,对每一行的像素进行循环移动,才能得到有意义的图像。
我的设想是这样的:
用一个线程处理一行,由于图像有480行,所以需要480个线程。
线程内部实现粉红色块的搜索和像素的循环移动。
由于这一关的运算量并不大,因此我不期望使用GPU会有多少速度提升,只是想验证一下我设想的代码是否能像期望中那样运行。
由于每个线程的处理稍微有些复杂,似乎无法使用纯Matlab来描述,所以我试着使用CUDAC描述了对图像每一行的操作,如下
__global__
void
rotpixel(const
unsigned
char
imin,
imout,
int
w,
h)
{
row_num
threadIdx.x;
first_pink
(row_num
<
(int
n=0;
n<
w;
++n)
(imin[w*row_num+n]
195)
n;
}
(first_pink)
w-first_pink;
++n)
imout[w*row_num+n]
imin[w*row_num+n+first_pink];
first_pink;
imout[w*row_num+w-first_pink+n]
imin[w*row_num+n];
在Matlab的CommandWindow中编译上面这段代码
!
nvcc-ptxlevel16.cu
构造CUDAKernel对象
ko=parallel.gpu.CUDAKernel('
level16.ptx'
'
level16.cu'
构造的时候为什么同时需要编译得到的ptx文件和源代码文件呢?
我猜大概是由于ptx没有提供足够的元信息,比如参数个数,参数类型等,Matlab需要通过分析源代码来得到这些必需的信息。
看看ko的属性
ko
ko=
CUDAKernelwithproperties:
ThreadBlockSize:
[111]
GridSize:
SharedMemorySize:
0
EntryPoint:
_Z8rotpixelPhS_ii'
MaxNumLHSArguments:
NumRHSArguments:
4
ArgumentTypes:
{'
inuint8vector'
inoutuint8vector'
inint32scalar'
主要ArgumentTypes这个属性。
由于使用了const修饰第一个参数,所以它就是in参数,而第二个参数没有使用const,它是inout。
非指针类型的参数大抵都是in类型了。
下面是使用这个kernel的Matlab通关代码:
level16_gpu
level
16
2013.03.25
07:
06
persistent
ko;
cmap]
mozart.gif'
isempty(ko)
ko
parallel.gpu.CUDAKernel('
[h,
w]
ko.ThreadBlockSize
h;
imout
gpuArray.zeros(w,
h,
uint8'
feval_r(ko,
I'
h);
imshow(imout'
cmap);
值得注意的是代码中需要人工指定ThreadBlockSize,这一点在文档中有相应的说明。
代码中使用了tic-toc计时,看看加速效果
Elapsedtimeis0.001373seconds.
Elapsedtimeis0.000951seconds.
Elapsedtimeis0.000435seconds.
Elapsedtimeis0.000436seconds.
Elapsedtimeis0.000448seconds.
一如既往的第一次有点慢。
作为比较,将之前《xialulee大战pythonchallenge——level16》中的代码加入了tic-toc,如下
level16
2012.03.03
10:
34
Ic
mat2cell(I,
ones(1,
h),
w);
I2
cellfun(@rotpixels,
Ic,
UniformOutput'
false);
I3
cell2mat(I2);
imshow(I3,
line
rotpixels(
)
find(line==195,
1,
first'
idx
[line(idx+1:
end),
line(1:
idx)];
看看时间消耗
level16
Elapsedtimeis0.021690seconds.
Elapsedtimeis0.013120seconds.
Elapsedtimeis0.012727seconds.
Elapsedtimeis0.012552seconds.
Elapsedtimeis0.013115seconds.
通过比较发现使用GPU确实比之前的快了。
符合期望,不过之前的代码并不能反映CPU的真实水准,构造cell和cellfun什么的做法估计效率是比较低下的。
反正这一次试验的目的不在于加速,只是想增加一些对GPU的了解。
Matlab(三)——关于Matlab的eps函数
Matlabcudagpu相对浮点精度
为了了解eps函数的运作方式,我们先后用MATLAB的typecast,C/C++的位段,Pythonctypes的位段,以及Java提供的ulp实现了相对浮点精度的运算。
但是Matlab自身究竟是如何实现eps的我们依然无从得之,因为它不是开源的。
有时候想看看Octave是如何实现的,结果我翻了半天Octave的C++代码,什么也没找着。
今天突然想到,可以看看MATLABCoder会将eps函数翻译成怎样的C代码,于是编写了如下的Matlab函数:
y
testeps(x)
2012.04.03
assert(isa(x,
double'
eps(x);
因为Matlab和C分别属于动态类型和静态类型语言,为了解决冲突,MATLABCoder要求使用assert的方式来指定变量的类型,只有知道了类型才能生成相应的C代码。
使用codegen函数进行翻译,由于翻译的过程中会保留原Matlab代码中的注释,所以可以很容易找到“y=eps(x)”对应的C代码的位置。
看看,发现没有什么稀奇的,既没有用普通的位操作,也没有使用位段,而是使用了<
math.h>
中两个操作浮点数的函数:
frexp和ldexp。
虽然《关于Matlab的eps函数》系列中已经解释过算法的原理好多次,这里还是再简要提一句吧。
对于64位的754浮点数,其在内存中的布局为:
SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
符号位1位,带偏移的指数域11位,尾数位52位。
其代表的数值由下式计算:
1.M×
2E-1023
其中1023是偏移量。
计算相对浮点精度很简单,将所有M置0,将指数减去52(52为尾数部分的长度),即可。
利用之前在《在Matlab中方便地操
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Matlab GPU