作者kanonehilber (隐居处)
看板MATLAB
标题[讨论] GPU 迭代计算 观念以及做法
时间Wed Sep 27 13:40:03 2017
不好意思,前几天才来问现在又跑来问了,还是很多东西搞不太清楚
我要算的题目跟这个很类似
https://en.wikipedia.org/wiki/Standard_map
从一组初始位置(p_0, theta_0)开始,每一次操作就是代入那个关系式一次,不过还需要
一点随机过程,最後结果大概是这样
p_n+1 = p_n + K sin(theta_n) + D * 随机数
theta_n+1 = theta_n + p_n+1
目标是要有几万个不同的初始位置(随机的初始位置),然後分别操作一两百万次
用MATLAB写出来大概是这样
turns=200; % 操作次数
ne=10000; % 初始位置数量
lp=gpuArray(zeros(ne,2));
rseed=1;
rand('seed',rseed)
randn('seed',rseed)
lp(:,1,:) = (rand(ne,1))*2*pi; % 产生随机初始位置 theta
lp(:,2,:) = (rand(ne,1)-0.5)*0.1; % 产生随机初始位置 p
k=gpuArray(0.5);
dn=gpuArray(0.001);
tic;
for i=1:turns
lp(:,2) = lp(:,2) + k*sin(lp(:,1))+dn*randn(ne,1,'gpuArray');
lp(:,1) = mod(lp(:,1) + lp(:,2),2*pi); % 让结果在2 pi以内
end
t=toc;
t
figure(1)
plot(lp(:,1),lp(:,2),'.');
===============
不用GPU版本
turns=200;
ne=10000;
lp=zeros(ne,2);
rseed=1;
rand('seed',rseed)
randn('seed',rseed)
lp(:,1,:) = (rand(ne,1))*2*pi;
lp(:,2,:) = (rand(ne,1)-0.5)*0.1;
k=0.5;
dn=0.001;
tic;
for i=1:turns
lp(:,2) = lp(:,2) + k*sin(lp(:,1))+dn*randn(ne,1);
lp(:,1) = mod(lp(:,1) + lp(:,2),2*pi);
end
t=toc;
t
figure(1)
plot(lp(:,1),lp(:,2),'.');
我看上一篇文章说尽量不要用for loop,要用内建函数,不过我输入methods gpuArray好
像没有找到类似的函数,我找的关键字是iteration、recursive和nest这类的关键字,所
以我还是先暂时用for来写,发现ne大约小於10000的时候不用gpu比较快,但是随着ne的
增加,gpu的速度几乎不变,甚至ne=1e6计算速度都跟ne=1e4差不多,而使用cpu计算的计
算时间跟ne大致上成正比增加,所以gpu运算在ne很大的时候可以大幅缩短计算时间,以
我的电脑为例ne=1e6大概可以快快要两个数量级
不过我需要的不是ne很大(ne大约几万就可以了,不会超过10万),而是操作次数turns很
大(需要上百万),目前这种写法增加turns用gpu算时间是随turns成正比增加,请问该如
何优化这个程式,看起来就是不要用for,可是我也不知该如何处理
其实我是因为现在这个研究主题从其他人那里拿了他用MATLAB写的程式才开始使用MATLAB
,现在还有很多MATLAB观念都搞不太清楚,谢谢各位版有指教
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 140.114.253.248
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/MATLAB/M.1506490811.A.87F.html
看起来MATLAB无法很自然的平行化迭代这种运算,所以是要想办法写成每一个初始条件丢
给不同的CORE让他们各自迭代吗? 感恩
※ 编辑: kanonehilber (140.114.253.31), 09/27/2017 17:03:24
1F:推 sunev: lp直接拆成两个变数可能方便一些,theta不需要mod09/27 18:21
2F:→ sunev: 还有你是要用cpu还是要用gpu ?09/27 18:22
3F:→ kanonehilber: 想用gpu,其实写成这样也是参考别人原本用cpu的算法09/27 18:48
4F:→ kanonehilber: 写的 09/27 18:48
5F:推 sunev: 这边出现的for是迭代,没什麽好方法,也无法平行化09/27 20:20
6F:→ sunev: 有一个隐性的for已经被你用(:,1)的方式处理了 09/27 20:21
7F:→ sunev: 如果你极端追求速度,matlab不会是最好的选择09/27 20:21
谢谢你的回答!
方便在这里问一个观念吗? 就我对GPU粗浅的理解,GPU是由很多核心构成,比起我用单核
CPU把一整件事情(迭代100万次)重复做一万次,如果把这一万次分配给GPU很多核心,每
个
核心各只做一整件事情几次,应该可以减少计算时间,可是我目前的结果看起来基本没有
节省什麽时间,想请问是我的观念完全搞错了吗?还是只是MATLAB不支援这种作法?
感恩
※ 编辑: kanonehilber (140.114.235.65), 09/27/2017 20:42:12
还是我说的分配已经被你说的(:,1)用掉了?
※ 编辑: kanonehilber (140.114.235.65), 09/27/2017 21:05:35
8F:推 sunev: gpu一个核心做事的速度有可能比cpu慢,所以还是要跑了才知 09/27 21:17
9F:→ sunev: 道,另外matlab把compile和execute混在一起,加上不是 09/27 21:18
10F:→ sunev: open source,所以不适合去做细致的分析,这也是我不推荐 09/27 21:18
11F:→ sunev: 你用matlab的原因。 09/27 21:19
12F:→ kanonehilber: 原来如此 了解了 谢啦 09/28 04:21