数据集比网格大
或出于选择,为了要创建具有超高性能的执行配置,或出于需要,一个网格中的线程数量可能会小于数据集的大小。请思考一下包含 1000 个元素的数组和包含 250 个线程的网格(此处使用极小的规模以便于说明)。此网格中的每个线程将需使用 4 次。如要实现此操作,一种常用方法便是在核函数中使用跨网格循环。
在跨网格循环中,每个线程将在网格内使用 threadIdx + blockIdx*blockDim
计算自身唯一的索引,并对数组内该索引的元素执行相应运算,然后将网格中的线程数添加到索引并重复此操作,直至超出数组范围。例如,对于包含 500 个元素的数组和包含 250 个线程的网格,网格中索引为 20 的线程将执行如下操作:
- 对包含 500 个元素的数组的元素 20 执行相应运算
- 将其索引增加 250,使网格的大小达到 270
- 对包含 500 个元素的数组的元素 270 执行相应运算
- 将其索引增加 250,使网格的大小达到 520
- 由于 520 现已超出数组范围,因此线程将停止工作
CUDA 提供一个可给出网格中线程块数的特殊变量:gridDim.x
。然后计算网格中的总线程数,即网格中的线程块数乘以每个线程块中的线程数:gridDim.x * blockDim.x
。带着这样的想法来看看以下核函数中网格跨度循环的详细示例:
__global void kernel(int *a, int N)
{
int indexWithinTheGrid = threadIdx.x + blockIdx.x * blockDim.x;
//blockIdx.x (0,1,3) blockDim.x(250)
int gridStride = gridDim.x * blockDim.x;
for (int i = indexWithinTheGrid; i < N; i += gridStride)
{
// do work on a[i];
}
}
/*1000个数据使用 32×255个线程跑两次*/
void doubleElements(int *a, int N)
{
/*
* Use a grid-stride loop so each thread does work
* on more than one element in the array.
*/
// 0-31 255 0-255
int idx = blockIdx.x * blockDim.x + threadIdx.x;
// 32 255
int stride = gridDim.x * blockDim.x;
for (int i = idx; i < N; i += stride)
{
a[i] *= 2;
}
}
bool checkElementsAreDoubled(int *a, int N)
{
int i;
for (i = 0; i < N; ++i)
{
if (a[i] != i*2) return false;
}
return true;
}
int main()
{
int N = 10000;
int *a;
size_t size = N * sizeof(int);
cudaMallocManaged(&a, size);
init(a, N);
size_t threads_per_block = 256;
size_t number_of_blocks = 32;
doubleElements<<<number_of_blocks, threads_per_block>>>(a, N);
cudaDeviceSynchronize();
bool areDoubled = checkElementsAreDoubled(a, N);
printf("All elements were doubled? %s\n", areDoubled ? "TRUE" : "FALSE");
cudaFree(a);
}
不同线程时间对比
__global__
void addVectorsInto(float *result, float *a, float *b, int N)
{
int index = threadIdx.x + blockIdx.x * blockDim.x;
int stride = blockDim.x * gridDim.x;
for(int i = index; i < N; i += stride)
{
result[i] = a[i] + b[i];
}
}
addVectorsInto<<<numberOfBlocks, threadsPerBlock>>>(c, a, b, N);
n 2<<24
threadsPerBlock numberOfBlocks nanoseconds
256 1 136793984
256 16 117175743
256 32 117047986
128 1 148998083
128 16 148271881
128 32 126887351
网友评论