2017-05-04 42 views
0

我有兩個幾乎相同的OpenCL內核,我想用GFLOPS來計算它們的性能。內核#1:兩個幾乎相同的OpenCL內核之間的性能差距

__kernel void Test41(__global float *data, __global float *rands, int index, int rand_max){ 

    float16 temp; 
    int gid = get_global_id(0); 

    temp = data[gid]; 
    temp = (float) rands[1] * temp; 
    temp = (float) rands[2] * temp; 
    temp = (float) rands[3] * temp; 
    temp = (float) rands[4] * temp; 
    . 
    . 
    . 
    temp = (float) rands[497] * temp; 
    temp = (float) rands[498] * temp; 
    temp = (float) rands[499] * temp; 
    data[gid] = temp.s0; 

} 

第二核心是:

__kernel void Test42(__global float *data, __global float *rands, int index, int rand_max){ 

    float16 temp[500]; 
    int gid = get_global_id(0); 

    temp[0] = data[gid]; 
    temp[1] = (float) rands[1] * temp[0]; 
    temp[2] = (float) rands[2] * temp[1]; 
    temp[3] = (float) rands[3] * temp[2]; 
    temp[4] = (float) rands[4] * temp[3]; 
    . 
    . 
    . 
    temp[497] = (float) rands[497] * temp[496]; 
    temp[498] = (float) rands[498] * temp[497]; 
    temp[499] = (float) rands[499] * temp[498]; 
    data[gid] = temp[index].s0; 

} 

正如你可以在代碼中看到的,我使用的16流大小每個內核具有500線運營,其中的每一個其中只有一個浮點操作。我還總共部署了大約1048576個內核,因此我將有大約1048576個工作項目並行執行。

爲了計算我做的觸發器:

flops = #numWorkItems(1048576) * (500) * StreamSize(16)/timeTaken; 

不幸的是,第一個內核我避開1.4 TFLOPs的,但對於第二個內核,我得到38個GFLOPS。我無法解釋這個巨大的差距。使用一個溫度矢量而不是單個溫度似乎是一個巨大的交易。也似乎真正的應用程序大多像第二個內核。第一個內核對於真正的應用來說太簡單了。

任何人都可以幫助我理解這裏究竟發生了什麼,以及第二個內核性能如何能夠達到第一個?一般來說,如果我要對我的設備進行基準測試,我希望看到性能接近理論值嗎?

P.S.我知道我需要將rands複製到__local內存中,但現在讓我們跳過。

+3

在第二個內核中有大量寄存器被分配給500個float16值的數組,所以很可能內核佔用率下降導致內核運行緩慢。 – sgarizvi

+0

500 * 16 * 4 = 32kB僅適用於單線程。由於內存使用情況,即使每個工作組的單個工作項目也會很慢。 –

+0

每個工作項目的合理內存使用量是多少?我只是想在設計我的基準時有更好的把握。 – saman

回答

-1

有兩個可能的問題:

  • 你宣佈float16臨時緩衝區爲__private {這是OpenCL的默認},並最有可能將在global內存空間與相當高的訪問延遲進行分配。如果它適合您的設備本地內存,您可能會嘗試將其聲明爲__local float16
  • 添加temp緩衝創造了編譯器的一些問題...原代碼是在某些GPU架構易於量化的(英特爾爲例),並通過添加store + load

其實我提交添加人工的依賴爲編譯器發佈報告。編譯器應該很容易找出依賴關係,進行優化,甚至擺脫您的temp緩衝區。

+0

感謝elal。我有一些關於你的評論的問題:1)你說我分配的'__private'內存很可能分配在全局內存空間中。這是什麼原因? 2)我添加了一個依賴項,因爲我希望我的基準測試能夠做到這一點。基本上我希望每個內核的內容都是數據依賴的。在我的內核中,編譯器如何進一步優化它? – saman

+0

@saman 1)OpenCL規範2)我沒有看到有任何具體的理由要這樣做,而不是找出OpenCL編譯器有多好,而且看起來像是被吸引。 – Elalfer

+0

嗨Elal。我正在查看OpenCL規格表,但我無法準確檢測到在'__global'內存中可以分配'__private'內存的地方。你能否提一下哪個頁面包含這些信息? – saman

0

由於@pmdj在評論中提出,第二個內核的主要問題是註冊壓力:您正在使用大量硬件寄存器,這會減少同時執行的工作組數量。 一般來說,大型私有數組在OpenCL/CUDA中並不是一個好主意。 在這種情況下,編譯器可以做的很少,以優化性能。 您可以使用本地內存作爲陣列,但是您需要添加適當的同步來訪問它。

+0

我已經基本上將'temp'數組的大小從500減少到了10,但是像以前一樣保持了內核的大小。仍然看不到任何性能數字的差異。看起來像第二個內核中的某些東西給GPU加速它帶來了重大問題。 – saman

+0

你有沒有使用一些分析器工具?它可能會給你一些關於註冊溢出的信息。包含10個元素的float16數組對於您的硬件來說可能仍然太多。 – Ruyk

+0

我明白了。你知道我可以用於Nvidia Tesla GPU的OpenCL profiler嗎?好像nvidia-smi不再支持OpenCL。 – saman