Re: [運算] 多層for迴圈簡化 與 GPU加速

作者: Absolitude (別再睡了起床了愛麗)   2017-12-20 05:04:25
真不好意思,才隔一天就又上來問..
昨天問的東西其實是我要算的東西的第二步,原本他才是瓶頸,但是板上高手一下就解決
了,我現在想不用for處理第一步,也就是求出昨天的atot (m*n,k)
atot中的元素是用一個m*n二維座標(x,y)和三個一組的數字(a1,a2,a3)帶入一個函數
f(x,y,a1,a2,a3)求得,三個一組的數字共有k組,所以最後atot的維度是(m*n,k)
https://imgur.com/CTjyecs
程式上先用meshgrid建立座標,再產生k組數字
m=15;
n=19;
k=10000;
[X,Y]=meshgrid(1:m,1:n);
ini=randn(k,3);
為了方便起見這裡f就先用sin和多項式來舉例
f(x,y,a1,a2,a3)=sin(x+y^2+a1+a2^2+a3^3)
目前想了一個辦法是用arrayfun配上reshape
atotpr=arrayfun(@(x,y) sin(x+y^2+ini(:,1)+ini(:,2).^2+ini(:,3).^3),X,Y,'un',0);
atotmid=cell2mat(atotpr);
atot=reshape(atotmid,k,m*n);
這樣確實比用三層for loop快很多了,隨便試幾個m,n,k都快一個數量級以上,不過想知道
有沒有更好的方法。另外這樣寫gpu也沒有辦法算,matlab的gpu不接受non UniformOutput
,雖然說以目前的速度來看,gpu似乎也不是很有必要了....但還是希望能多學一點
感恩
作者: sunev (Veritas)   2017-12-20 07:50:00
這裡xy和a剛好可以拆開,所以atot=bsxfun(@plus,X(:)+Y(:).^2,(ini(:,1)+ini(:,2).^2)')atot=reshape(sin(atot),[m*n k]);另外我印象中arrayfun沒有比for-loop快,你可以check一下
作者: Absolitude (別再睡了起床了愛麗)   2017-12-20 22:11:00
原來可以用(:),我要算的有交叉項,不過剛剛弄出來了感恩!!晚點再看看FOR的
作者: sunev (Veritas)   2017-12-22 16:13:00
真要快還是得用C,不然就是用gpu
作者: profyang (prof)   2017-12-22 20:02:00
2016b以後的matlab不用bsxfun也可以做到2F的事情了直接X(:)+Y(:).^2+(ini(:,1)+ini(:,2).^2)'應該就可以
作者: Absolitude (別再睡了起床了愛麗)   2017-12-24 01:31:00
對程式語言的本質不瞭解 C真的一定比MATLAB快嗎P大感恩,不過我目前的版本沒那麼新
作者: LiamIssac (Madchester)   2017-12-24 15:06:00
如果要跟文獻拼速度可能需要計較(在同一個環境下) 但如果只是要結果 時間基本不會差到哪(order of 1) 就看程式的寫法 那些arrayfun背後也都是迴圈寫成的 只是經過優化而已可以到mathworks的論壇去看看 很多高手在那討論
作者: profyang (prof)   2017-12-24 18:23:00
用bsxfun的話應該不會比C慢

Links booklink

Contact Us: admin [ a t ] ucptt.com