設備和主機之間的同步
//顯式同步,阻塞直到該語句前得所有kernel調用執行完畢
cudaError_t cudaDeviceSynchronize(void);
//隱式同步
cudaError_t cudaMemcpy(void* dst, const void* src, size_t count, cudaMemcpyKind kind);
線程塊內的同步
同一線程塊內的同步方式有兩種:
Barriers
Memory Fences__device__ void __syncthreads(); __device__ void __threadfence_block();
- Weakly-Ordered Memory Model指的是gpu對內存的寫入操作未必是立即完成的,線程可能等到需要讀取該段內存時,纔將這之前的寫入操作完成
當線程同步語句包含在執行分支中時,要確保同一線程束內的所有線程都執行相同的分支,否則程序可能僵死
if(threadIdx.x % 2 == 0) { __syncthreads(); } else { __syncthreads(); }
實際上,memory fence支持塊內同步,網格內同步,主機-設備,設備-設備同步。調用memory fence的線程會阻塞直到對應的線程集合中所有對全局內存,共享內存,頁鎖定內存,其他設備的全局內存的寫入都完成
void __threadfence_block(); //塊同步 void __threadfence(); //網格同步 void __threadfence_system(); //系統同步
線程塊之間同步
- cuda不直接支持塊間barrier,但由於同一stream中的多個kernel的執行是串行的,可以把需要塊間同步的kernel分割成多個kernel,每個分割點對應一個barrier