2017-01-29 26 views
0

我需要使用一個整數(0-99)作爲參數以相同的數據運行我的GPU內核(ALEA庫)100次。我試圖在內核中實現這個循環,但是我得到了奇怪的結果。我不得不採取環出內核和周圍的GPULaunch函數是這樣的:環繞GPULaunch或者使用ALEA庫在內核中循環

var lp = new LaunchParam(GridDim, BlockDim); 
for (int i= 0; i < 100; i++) 
{ 
    GPULaunch(TestKernel, lp, Data, i); 
} 

代碼的CPU版本是高度優化和有效地使用4芯(%100)。根據合併內存訪問原則重組內存中的數據後,我可以獲得%92佔用率和%96全局負載效率。但是,GPU版本只比CPU版本快50%。我懷疑循環GPULaunch是否有效。

正如您在下面的圖表中看到的,我在NVIDIA Visual Profilier中看不到重複的內存傳輸。一旦我將數據加載到GPU(未在圖中看到但對我不重要),我會在右端看到一個100循環輸出的短內存傳輸。所以我的問題是:

  1. 這種在循環中調用GPULaunch的方法有一個看不見的內存傳輸相同的數據嗎?
  2. 如果有這樣的開銷,我需要在內核中有這個循環。我該怎麼做。我嘗試過但結果不穩定,認爲這種方法不適合GPU並行編程架構。

在此先感謝

NVIdia Visual Profiler resutl

+0

看起來您仍然在使用AleaGPU 2.x,最新版本是AleaGPU 3.x,但是API更改(www.aleagpu .COM)。此外,「HOIndex」是什麼類型,「Data」是什麼類型? –

+0

我重新安裝了Alea.IL.dll,因此它現在是3.0.0.0版本,但其他版本是根據Nuget信息的最新版本。 HOIndex實際上是整數「i」我忘了改變它,我用它替換了它。數據表示兩個輸入數組和兩個輸出數組。這是一個簡化的模板。總之它不會影響循環。我再次嘗試了內核循環,這次我不知道爲什麼。 –

回答

0

我試圖實現在內核一次循環,它的工作。我不確定這次有什麼不同。這裏是顯而易見的代碼(只是模板不是工作代碼):

public class GPUModule : ILGPUModule 
{ 

    public GPUModule (GPUModuleTarget target) : base(target) 
    { 
    } 

    [Kernel] 
    Public MyKernel(deviceptr<int> Data) 
    { 
    var start = blockIdx.x * blockDim.x + threadIdx.x; 
    int ind = threadIdx.x; 

    for (int i=0;i<100;i++) 
    { 
     //Kernel Code here 
    } 
    } 

    public void Dilimle_VerilerB(deviceptr<int> Data 
    { 
    ... 
    var lp = new LaunchParam(GridDim, BlockDim); 
    GPULaunch(TestKernel, lp, Data, HOIndex); 
    ... 
    } 
} 

內核的唯一補充是整數「我」上的循環。不幸的是,它導致寄存器/線程數從26跳到42,導致佔用率從%100下降到%50,這將執行時間從2.1秒略微增加到2.3秒。因此,如果保持%100佔用率,則將循環加入內核將提高性能,從而大大減少GPULaunch開銷。

圍繞GPULaunch循環的%100佔用率與1024個線程/塊一起工作。在更改爲內核內核循環後,我將其更改爲128個線程/塊。這增加了Ocuppancy到62%,並導致執行時間爲1.1秒。因此,作爲一個結論,在內核中進行這樣一個循環提供了兩倍的GPU性能提升。

所以問題是爲什麼內核的寄存器/線程數從26增加到42,並在內核中增加了一個整數循環。如果寄存器數量大約爲30,那麼我認爲佔用率仍然可能接近100%。