我不能評論以前的解決方案,因爲我太新了,但延伸了Pavan的解決方案。至少在我使用的Matlab版本(R2012a)中,nnz函數(尚未)針對gpuArrays實施。
一般來說,矢量化Matlab代碼要好得多。但是,在一些情況下,循環代碼可以在Matlab中快速運行,因爲JIT編譯。
檢查從
N = 1000;
randarray_cpu = rand(N,1);
randarray_gpu = gpuArray(randarray_cpu);
threshold = 0.5;
% CPU: looped
g=0;
tic
for i=1:N
if randarray_cpu(i)>threshold
g=g+1;
end
end
toc
% CPU: vectorized
tic
g = nnz(randarray_cpu>threshold);
toc
% GPU: looped
tic
g=0;
for i=1:N
if randarray_gpu(i)>threshold
g=g+1;
end
end
toc
% GPU: vectorized
tic
g_d = sum(randarray_gpu > threshold);
g = gather(g_d); % I'm assuming that you want this in the CPU at some point
toc
哪一個是結果(我的酷睿i7 +的GeForce 560TI):
Elapsed time is 0.000014 seconds.
Elapsed time is 0.000580 seconds.
Elapsed time is 0.310218 seconds.
Elapsed time is 0.000558 seconds.
所以我們從這個案例看到的是:
循環在Matlab是不被認爲是好的實踐,但在你的特定情況下,它運行速度很快,因爲Matlab以某種方式「內部預編譯」它。我把你的門檻從10提高到了0.5,因爲蘭特永遠不會給你一個高於1的值。
循環的GPU版本表現糟糕,因爲在每次循環迭代時,啓動內核(或從GPU中讀取數據,但是TMW實現了......),這是很慢的。在計算基本上沒有什麼的時候,很多小內存傳輸是人們可以在GPU上做的最糟糕的事情。
從最後一個(最佳)GPU結果來看,答案是:除非數據已經在GPU上,否則在GPU上計算這些數據是沒有意義的。由於您的操作的算術複雜性基本上不存在,因此內存傳輸開銷無法以任何方式回報。如果這是更大的GPU計算的一部分,那就沒問題。如果沒有...更好地堅持CPU;)
所以我應該避免如果/然後像使用CUDA時的魔鬼? – 2012-01-29 18:12:36
RRs_Ghost,這將是一個好主意。當你使用if/while和其他命令時,它會將mem拷貝回主機。在for循環中一堆小(1個元素)mem副本是一個壞主意。 – 2012-01-29 18:23:51
@Pavan:我不相信PCT中的當前gpuArray實現支持nnz。 – talonmies 2012-01-29 19:08:59