2016-07-24 70 views
2

我具有以下在C++代碼:C++ AMP是慢

float Neuron::feedForward(std::vector<Neuron>& previousLayer){ 
float sum=0.0f; 
for(int i=0;i<(int)previousLayer.size();i+=1){ 
    sum+=previousLayer[i].getOutput()*weigths[i]; 
} 
output=Neuron::transferFunction(sum); 
return output; 

}; 

我轉化成這樣的:

float Neuron::feedForward(std::vector<Neuron>& previousLayer){ 
float sum=0.0f; 
extent<1> e((int)previousLayer.size()); 

std::vector<float> ops(previousLayer.size()); 
for (int i = 0; i<(int)previousLayer.size(); i += 1) { 
    ops[i] = previousLayer[i].getOutput(); 
} 

array_view<const float, 1>_outputs(e, ops); 
array_view<const float, 1>_weigths(e, weigths); 
array_view<float> _sum(e); 
_sum.discard_data(); 


parallel_for_each(e, [=](index<1> idx) restrict(amp) { 
    _sum[idx] = _outputs[idx] * _weigths[idx]; 

}); 

for (int i = 0; i < e[0]; i += 1) { 
    sum += _sum[i]; 
} 

output=Neuron::transferFunction(sum); 
return output; 

};

現在程序運行的代碼非常慢。不只是幾毫秒慢,但實際上慢幾秒​​。

我也試圖具有AMP碼內總和(僅改變):

array_view<float> _sum(1); 
_sum.discard_data(); 

... 

parallel_for_each(e, [=](index<1> idx) restrict(amp) { 
_sum[0] += _outputs[idx] * _weigths[idx]; 

});

... 

/*for (int i = 0; i < e[0]; i += 1) { 
sum += _sum[i]; 
} 
*/ 

output=Neuron::transferFunction(_sum[0]); 

但最後,代碼就是這樣:這麼慢,我會用手計算器更快。現在的問題是:爲什麼?我認爲如果我有一個2000個體重的神經元,那麼讓GPU計算一切就會很棒。我錯過了什麼,還是我必須學習OpenCL或CUDA?

PS。緩慢是非常糟糕的。就像它花費的時間超過10萬次(同時我可以計算20 000個神經網絡10次,使用AMP我可以計算2個完全相同的網絡)。

+0

您可以嘗試在parallel_for_each塊之後的e上添加同步調用。根據此處的C++ AMP教程https://msdn.microsoft.com/en-us/magazine/hh882446.aspx,應該自動執行同步。但是,如果你不明確地調用synchronize(),你將失去異常,所以這可能會導致一些事情發生。 – hacoo

+0

我懷疑你不知道如何使用AMP。看起來你堅持要將一定數量的產品積累到一個標量_sum [0]中。如果我理解了這個權利,那麼您就迫使生成的代碼將所有產品發送到持有sum [0](「多次通信」)的特定處理器,並且/或者強制執行全局鎖定的所有更新(「大量的鎖干擾「)。這些都不是有效的。我認爲你會花點時間閱讀數據並行編程,技術和陷阱,然後利用這些知識修改AMP的程序。 –

+0

我不知道我是否可以在e上調用同步,但在_sum上沒有觸發std :: exception。是否有可能,因爲我在筆記本電腦上運行,GPU以某種方式處於睡眠模式,並且AMP退回到CPU?儘管我的CPU使用率約爲10%,這意味着我的電腦上的一個線程正在運行其90%的功能。 – Nyxeria

回答

1

您的代碼使用sum[0]幾乎肯定會給出不正確的結果,因爲許多線程正在同時更新sum[0]

天真的實現應該可以工作,但效率非常低,因爲將數據移入和移出GPU的拷貝開銷很大,而且計算量很小。

但是,由於它的速度與您所說的一樣慢,您可能正在CPU上的WARP加速器上運行。您可以使用以下代碼查看可用的加速器。

https://ampbook.codeplex.com/SourceControl/latest#Samples/ShowAmpDevices/ShowAmpDevices.cpp

什麼,你在這裏做的是減少。有很多關於如何在GPU上高效完成這些工作的文章。您可以在此處找到顯示幾種不同實現的C++ AMP代碼:

C++ AMP: Accelerated Massive Parallelism with Microsoft Visual C++ on CodePlex。

他們在隨代碼一起的書中有充分的解釋。

+0

_sum [0]是其中一個測試,我也嘗試過_sum [idx]。我知道這還不是最優的代碼,但它對我來說是一個學習AMP的簡單方塊(稍後我計劃將數據移動到GPU,並計算所有內容,但現在我用它來學習該過程)。 我添加了手動選擇GPU的代碼,GeForce 570.我也試過了你鏈接的代碼,我的設備說:專用內存:1.2mb,有display = true,is_debug和is_emulated都是假的,它支持有限的雙精度。我要去嘗試CUDA,以防AMP的問題。 – Nyxeria