和許多多執行緒並行問題一樣,cuda也存在互斥訪問的問題,即當乙個執行緒改變變數x,而另外乙個執行緒在讀取變數x的值,執行原子操作類似於有乙個自旋鎖,只有等x的變數在改變完成之後,才能執行讀操作,這樣可以保證每一次讀取的都是最新的值.
在kernel 程式中,做統計累加,都需要使用原子操作:atomicadd();
原子操作很明顯的會影響程式效能,所以可以的話,盡可能避免原子操作.
cuda原子操作api:
c.1.1 atomicadd()
int atomicadd(int* address, int val);
unsigned int atomicadd(unsigned int* address,
unsigned int val);
unsigned long long int atomicadd(unsigned long long int* address,
unsigned long long int val);
讀取位於全域性或共享儲存器中位址address 處的32 位或64 位字old,計算(old + val),並將結果儲存在儲存器的同一位址中。這三項操作在一次原子事務中執行。該函式將返回old。
只有全域性儲存器支援64 位字。
c.1.2 atomicsub()
int atomicsub(int* address, int val);
unsigned int atomicsub(unsigned int* address,
unsigned int val);
讀取位於全域性或共享儲存器中位址address 處的32 位字old,計算(old - val),並將結果儲存在儲存器的同一位址中。這三項操作在一次原子事務中執行。該函式將返回old。
c.1.3 atomicexch()
int atomicexch(int* address, int val);
unsigned int atomicexch(unsigned int* address,
unsigned int val);
unsigned long long int atomicexch(unsigned long long int* address,
unsigned long long int val);
float atomicexch(float* address, float val);
讀取位於全域性或共享儲存器中位址address 處的32 位或64 位字old,並將val 儲存在儲存器的同一位址中。這兩項操作在一次原子事務中執行。該函式將返回old。
只有全域性儲存器支援64 位字。
c.1.4 atomicmin()
int atomicmin(int* address, int val);
unsigned int atomicmin(unsigned int* address,
unsigned int val);
讀取位於全域性或共享儲存器中位址address 處的32 位字old,計算old 和val 的最小值,並將結果儲存在儲存器的同一位址中。這三項操作在一次原子事務中執行。該函式將返回old。
c.1.5 atomicmax()
int atomicmax(int* address, int val);
unsigned int atomicmax(unsigned int* address,
unsigned int val);
讀取位於全域性或共享儲存器中位址address 處的32 位字old,計算old 和val 的最大值,並將結果儲存在儲存器的同一位址中。這三項操作在一次原子事務中執行。該函式將返回old。
c.1.6 atomicinc()
unsigned int atomicinc(unsigned int* address,
unsigned int val);
讀取位於全域性或共享儲存器中位址address 處的32 位字old,計算 ((old >= val) ? 0 : (old+1)),並將結果儲存在儲存器的同一位址中。這三項操作在一次原子事務中執行。該函式將返回old。
c.1.7 atomicdec()
unsigned int atomicdec(unsigned int* address,
unsigned int val);
讀取位於全域性或共享儲存器中位址address 處的32 位字old,計算 (((old == 0) | (old > val)) ? val : (old-1)),並將結果儲存在儲存器的同一位址中。這三項操作在一次原子事務中執行。該函式將返回old。
c.1.8 atomiccas()
int atomiccas(int* address, int compare, int val);
unsigned int atomiccas(unsigned int* address,
unsigned int compare,
unsigned int val);
unsigned long long int atomiccas(unsigned long long int* address,
unsigned long long int compare,
unsigned long long int val);
讀取位於全域性或共享儲存器中位址address 處的32 位或64 位字old,計算 (old == compare ? val : old),並將結果儲存在儲存器的同一位址中。這三項操作在一次原子事務中執行。該函式將返回old(比較並交換)。
只有全域性儲存器支援64 位字。
c.2 位邏輯函式c.2.1 atomicand()
int atomicand(int* address, int val);
unsigned int atomicand(unsigned int* address,
unsigned int val);
讀取位於全域性或共享儲存器中位址address 處的32 位字old,計算 (old & val),並將結果儲存在儲存器的同一位址中。這三項操作在一次原子事務中執行。該函式將返回old。
c.2.2 atomicor()
int atomicor(int* address, int val);
unsigned int atomicor(unsigned int* address,
unsigned int val);
讀取位於全域性或共享儲存器中位址address 處的32 位字old,計算 (old | val),並將結果儲存在儲存器的同一位址中。這三項操作在一次原子事務中執行。該函式將返回old。
c.2.3 atomicxor()
int atomicxor(int* address, int val);
unsigned int atomicxor(unsigned int* address,
unsigned int val);
讀取位於全域性或共享儲存器中位址address 處的32 位字old,計算 (old ^ val),並將結果儲存在儲存器的同一位址中。這三項操作在一次原子事務中執行。該函式將返回old。
CUDA atomic原子操作
cuda的原子操作可以理解為對乙個變數進行 讀取 修改 寫入 這三個操作的乙個最小單位的執行過程,這個執行過程不能夠再分解為更小的部分,在它執行過程中,不允許其他並行執行緒對該變數進行讀取和寫入的操作。基於這個機制,原子操作實現了對在多個執行緒間共享的變數的互斥保護,確保任何一次對變數的操作的結果的...
CUDA atomic原子操作
cuda的原子操作可以理解為對乙個變數進行 讀取 修改 寫入 這三個操作的乙個最小單位的執行過程,這個執行過程不能夠再分解為更小的部分,在它執行過程中,不允許其他並行執行緒對該變數進行讀取和寫入的操作。基於這個機制,原子操作實現了對在多個執行緒間共享的變數的互斥保護,確保任何一次對變數的操作的結果的...
通過muduo的Atomic h學習原子操作
最新在讀muduo原始碼,想寫乙個原始碼閱讀的系列,就以這個為開篇吧 原始碼如下 templateclass atomicintegert noncopyable uncomment if you need copying and assignment atomicintegert const at...