2014-10-02 50 views
2

我在C++ AMP中處理大型數組(大於65536個元素)時遇到問題。我使用C++放大器來計算多邊形列表的法線,正切和雙切線向量。輸入由一個位置數組(每個位置3個浮點數)和uv座標數組(每個頂點2個浮點數)組成。在我的parallel_for_each函數中,我計算法線,切線和比特(每組3個頂點中的每一個)。我將它們寫回到數組(封裝在array_view中)。該算法如下所示:使用C++ AMP處理大型陣列(65536+個元素)AMP

concurrency::extent<2> ePositions(positionsVector.size()/3, 3); 
concurrency::array_view<const float, 2> positions(ePositions, positionsVector); 
concurrency::extent<2> eUVs(uvsVector.size()/2, 2); 
concurrency::array_view<const float, 2> UVs(eUVs, uvsVector); 
concurrency::extent<2> eNormalDirections(normalDirectionsVector.size()/3, 3); 
concurrency::array_view<float, 2> normalDirections(eNormalDirections, normalDirectionsVector); 
normalDirections.discard_data(); 
concurrency::extent<2> eTangentDirections(tangentDirectionsVector.size()/3, 3); 
concurrency::array_view<float, 2> tangentDirections(eTangentDirections, tangentDirectionsVector); 
tangentDirections.discard_data(); 
concurrency::extent<2> eBitangentDirections(bitangentDirectionsVector.size()/3, 3); 
concurrency::array_view<float, 2> bitangentDirections(eBitangentDirections, bitangentDirectionsVector); 
bitangentDirections.discard_data(); 

concurrency::parallel_for_each(eNormalDirections.tile<1, 3>(), [=](concurrency::tiled_index<1, 3> t_idx) restrict(amp) 
{ 
    < ... calculate the normals, tangents and bitangents and write them back ... > 
} 

normalDirections.synchronize(); 
tangentDirections.synchronize(); 
bitangentDirections.synchronize(); 

原始數據包含在positionsVectoruvsVector。輸出存儲在normalDirectionsVector,tangentDirectionsVectorbitangentDirectionsVector。三個位置(和相關的uv對)形成一個多邊形。由於每個多邊形只需要一個法線,切線和雙切線,所以輸出矢量的大小比輸入矢量的大小小三倍。所有向量都封裝在第一個代碼塊的array_view中。

算法工作正常,只要法線的數量來計算比65536小隻要我需要65536個以上的正常人,我得到以下異常:

併發:: parallel_for_each(平鋪):不支持的計算域, 計算域的尺寸0(65536的程度)超過 獨家極限(65536)

正如我想處理由多於65536個多邊形的幾何形狀,這個限制對我來說是一個問題。我無法想象C++ AMP僅限於處理少於65536個元素。因此,我想知道我在我的方法中犯了什麼錯誤,以及如何處理超過65536個元素的數組。

+0

如果使用GPGPU的組合,陣列的大小可以適合在GPU存儲器是有限的,並且因此存在於你可以工作的數據量的硬性限制在任何時間。您需要將數據分成更小的塊,這些塊可以放入線程的本地共享內存中並處理這些內存,將它們傳輸到全局內存中並獲取下一批數據。這是GPGPU的主要瓶頸。 – 2014-10-02 14:52:38

+0

啊,所以array_views沒有存儲在全局內存中?我假定array_views存儲在全局內存中,並且可以通過將數據複製到parallel_for_each循環內的tile_local變量來將數據移動到本地內存。那麼我的問題的解決方案是以50000個元素的塊來處理數組嗎? – 2014-10-02 15:32:04

+0

我無法找到任何有關Microsoft已發佈的規範中的特定錯誤的參考(http://download.microsoft.com/download/4/0/E/40EA02D8-23A7-4BD2-AD3A-0BFFFB640F28/ CppAMPLanguageAndProgrammingModel.pdf),這就是爲什麼我沒有發佈這個答案,只是做了一個評論。我認爲如果您將數據分解爲小於上述限制的任何塊都可以使用,或者可以使用2D或3D範圍,而不是每個維度都小於其對應的限制,以便您可以在每次傳遞時獲得更多數據。 – 2014-10-02 15:38:00

回答

2

大多數GPU至少有一個GB的全局內存,arrayarray_view都將數據存儲在全局內存中。在array_view的情況下,它會自動與主機(CPU)內存中的數據同步。他們也有tile_static內存,這是非常有限的。在這種情況下,我不相信你會遇到任何與內存相關的限制。

計算域是extent傳遞給parallel_for_each並描述了在GPU上使用的線程數。 GPU只能執行有限數量的總線程。這是錯誤消息中所描述的限制。更改計算域的維度數量並不能解決您的問題,無論它們是如何安排的,它都是問題的總數。這是GPU硬件的一般侷限性(您也會發現CUDA也有類似的限制)。

你有幾種方法來解決這個問題。

1)您可以將計算分解爲小於總線程限制的塊。這可能會讓您隱藏前一個塊的計算的開銷。

2)讓計算域中的每個線程計算多個多邊形的結果。這將允許您增加每個線程完成的工作量,如果實際上受到數據傳輸的限制,這可能會提高整個算法的效率。

3)1 & 2.

+0

非常感謝您的明確解釋。我嘗試了增加維數的解決方案,但它確實沒有奏效。解決此限制的方法也非常感謝! – 2014-10-05 08:30:08