只要SM有足够的未使用资源来支持新块,就可以立即安排新块。在安排新块之前,不必将SM完全排干块。正如评论中指出的那样,如果您现在要求公共文档支持这个断言,我不确定我能指出它。但是,您可以创建一个块专用内核,启动许多块。每个SM上的第一个块将使用原子操作发现和声明自己。这些块将“持久存在”,直到所有其他块完成,使用块完成计数器(再次使用原子操作,类似于threadfence reduction示例代码)。在给定SM上没有第一个启动的其他块将简单退出。与其挂起,这种代码的完成将是其他块即使仍驻留一些块也可以被调度的证明。以下是一个完整的工作示例:
$ cat t743.cu
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define NB 1000
#define MAX_SM 32
#define HANG_TEST 0
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
static __device__ __inline__ uint32_t __smid(){
uint32_t smid;
asm volatile("mov.u32 %0, %%smid;" : "=r"(smid));
return smid;}
__device__ volatile int blocks_completed = 0;
__device__ int first_SM[MAX_SM];
__global__ void tkernel(int num_blocks, int num_SMs){
int my_SM = __smid();
int im_not_first = atomicCAS(first_SM+my_SM, 0, 1);
if (!im_not_first){
while (blocks_completed < (num_blocks-num_SMs+HANG_TEST));
}
atomicAdd((int *)&blocks_completed, 1);
}
int main(int argc, char *argv[]){
unsigned my_dev = 0;
if (argc > 1) my_dev = atoi(argv[1]);
cudaSetDevice(my_dev);
cudaCheckErrors("invalid CUDA device");
int tot_SM = 0;
cudaDeviceGetAttribute(&tot_SM, cudaDevAttrMultiProcessorCount, my_dev);
cudaCheckErrors("CUDA error");
if (tot_SM > MAX_SM) {printf("program configuration error\n"); return 1;}
printf("running on device %d, with %d SMs\n", my_dev, tot_SM);
int temp[MAX_SM];
for (int i = 0; i < MAX_SM; i++) temp[i] = 0;
cudaMemcpyToSymbol(first_SM, temp, MAX_SM*sizeof(int));
cudaCheckErrors("cudaMemcpyToSymbol fail");
tkernel<<<NB, 1>>>(NB, tot_SM);
cudaDeviceSynchronize();
cudaCheckErrors("kernel error");
}
$ nvcc -o t743 t743.cu
$ ./t743 0
running on device 0, with 15 SMs
$ ./t743 1
running on device 1, with 1 SMs
$ ./t743 2
我已在Linux上使用CUDA 7在K40c,C2075和Quadro NVS 310 GPU上测试了上述代码。它不会挂起。
回答您的第二个问题,一个块通常会保留在其最初调度的SM上。 CUDA动态并行性的一个可能的例外情况。