簡體   English   中英

了解浮動上減少OpenCL的方法

[英]Understanding the method for OpenCL reduction on float

通過此鏈接 ,我嘗試了解內核代碼的操作(此內核代碼有2個版本,一個版本具有volatile local float *source ,另一個版本具有volatile global float *source ,即localglobal版本)。 下面我以local版本:

float sum=0;
void atomic_add_local(volatile local float *source, const float operand) {
    union {
        unsigned int intVal;
        float floatVal;
    } newVal;

    union {
        unsigned int intVal;
        float floatVal;
    } prevVal;

    do {
        prevVal.floatVal = *source;
        newVal.floatVal = prevVal.floatVal + operand;
    } while (atomic_cmpxchg((volatile local unsigned int *)source, prevVal.intVal, newVal.intVal) != prevVal.intVal);
}

如果我理解得很好,由於限定符“ volatile ”,每個工作項都共享對source變量的訪問,不是嗎?

之后,如果我使用一個工作項,則代碼會將operand數值添加到newVal.floatVal變量中。 然后,在執行此操作之后,我調用atomic_cmpxchg函數,該函數檢查先前的賦值( preVal.floatVal = *source;newVal.floatVal = prevVal.floatVal + operand; )是否已經完成,即通過將存儲在地址source處的值與preVal.intVal

在此原子操作期間(根據定義,它不是不可中斷的),因為source存儲的值不同於prevVal.intVal ,所以source存儲的新值是newVal.intVal ,它實際上是一個浮點數(因為它被編碼為4個字節,例如整數)。

我們可以說每個工作項都具有對位於source address處的值的互斥訪問(我是指鎖定訪問)。

但是對於each work-item線程, while loop是否只有一個迭代?

我認為會有一次迭代,因為比較“ *source== prevVal.int ? newVal.intVal : newVal.intVal ”總是將newVal.intVal值分配給存儲在source address值,不是嗎?

歡迎任何幫助,因為我還不了解此內核代碼的所有技巧。

更新1:

抱歉,我幾乎了解所有這些實用程序,尤其是在while loop

第一種情況:對於給定的單線程,在調用atomic_cmpxchg之前,如果prevVal.floatVal仍等於*source ,那么atomic_cmpxchg將更改source指針中包含的值並返回old pointer包含的值,該值等於prevVal.intVal ,因此我們從while loop中斷。

第二種情況:如果在prevVal.floatVal = *source; 指令和對atomic_cmpxchg的調用,值*source已更改(由另一個線程??),然后atomic_cmpxchg返回的old值不再等於prevVal.floatVal ,因此while loop的條件為true,我們一直待在此循環中,直到以前的條件不再檢查。

我的解釋是正確的嗎?

謝謝

如果我理解得很好,由於限定符“ volatile ”,每個工作項都共享對源變量的訪問,不是嗎?

volatile是C語言的關鍵字,可防止編譯器優化對內存中特定位置的訪問(換句話說,在該內存位置的每次讀取/寫入時強制進行加載/存儲)。 它對基礎存儲的所有權沒有影響。 在這里,它用於強制編譯器在每次循環迭代時從內存中重新讀取source (否則編譯器將被允許將負載移到循環外,這會破壞算法)。

do {
    prevVal.floatVal = *source; // Force read, prevent hoisting outside loop.
    newVal.floatVal = prevVal.floatVal + operand;
} while(atomic_cmpxchg((volatile local unsigned int *)source, prevVal.intVal, newVal.intVal) != prevVal.intVal)

刪除限定符(為簡單起見)並重命名參數后, atomic_cmpxchg的簽名如下:

int atomic_cmpxchg(int *ptr, int expected, int new)

它的作用是:

atomically {
    int old = *ptr;

    if (old == expected) {
        *ptr = new;
    }

    return old;
}

總而言之,每個線程分別執行以下操作:

  1. *source當前值從內存加載到preVal.floatVal
  2. newVal.floatVal計算*sourcenewVal.floatVal
  3. 執行上述原子比較交換(使用類型化的值)
  4. 如果atomic_cmpxchg == newVal.intVal的結果表示比較交換成功,則中斷。 否則,交換不會發生,請轉到1,然后重試。

上面的循環最終終止,因為最終 ,每個線程都成功完成了atomic_cmpxchg

我們可以說每個工作項都具有對位於源地址的值的互斥訪問(我是指鎖定訪問)。

互斥鎖是鎖,而這是一種無鎖算法。 OpenCL可以使用自旋鎖(也可以通過原子實現)來模擬互斥鎖,但這不是一個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM