2012-01-29 56 views
3

發言,我有以下的MATLAB代碼:MATLAB如果與CUDA

randarray = gpuArray(rand(N,1)); 
N = 1000; 

tic 
g=0; 
for i=1:N 

    if randarray(i)>10 
     g=g+1; 
    end 

end 
toc 

secondrandarray = rand(N,1); 
g=0; 

tic 
for i=1:N 

    if secondrandarray(i)>10 
     g=g+1; 
    end 

end 
toc 



Elapsed time is 0.221710 seconds. 
Elapsed time is 0.000012 seconds. 

1)爲什麼if語句在GPU上這麼慢?它正在放慢我所有的優化嘗試

2)我能做些什麼來解決這個限制?

感謝

回答

6

無論你在cpu還是gpu上做這件事,這都是一件壞事。

以下將是您正在查看的操作的好方法。

N = 1000; 
randarray = gpuArray(100 * rand(N,1)); 
tic 
g = nnz(randarray > 10); 
toc 

我沒有PCT,我無法驗證這是否真的有效(GPU支持的功能數量相當有限)。

但是,如果你有Jacket,你一定能夠做到以下幾點。

N = 1000; 
randarray = gdouble(100 * rand(N, 1)); 
tic 
g = nnz(randarray > 10); 
toc 

完全披露:我是開發夾克的工程師之一。

+0

所以我應該避免如果/然後像使用CUDA時的魔鬼? – 2012-01-29 18:12:36

+0

RRs_Ghost,這將是一個好主意。當你使用if/while和其他命令時,它會將mem拷貝回主機。在for循環中一堆小(1個元素)mem副本是一個壞主意。 – 2012-01-29 18:23:51

+0

@Pavan:我不相信PCT中的當前gpuArray實現支持nnz。 – talonmies 2012-01-29 19:08:59

1

Matlab的gpuArray實施專家,但我懷疑的是,在第一循環的每個randarray(i)訪問觸發PCI-E事務中獲取從GPU內存的值,這將招致非常大的延遲罰款。通過調用gather可以更好地服務於在單個事務中傳輸整個陣列,然後循環遍歷主機內存中的本地副本。

1

上現在比較舊的GPU(特斯拉C1060)使用MATLAB R2011b和並行計算工具箱,這是我看到:

>> g = 100*parallel.gpu.GPUArray.rand(1, 1000); 
>> tic, sum(g>10); toc 
Elapsed time is 0.000474 seconds. 

操作上gpuArray一次一個標量元素總是將是速度慢,因此使用sum方法要快得多。

0

我不能評論以前的解決方案,因爲我太新了,但延伸了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;)