我需要执行大约10 ^ 11次的函数。该函数是自包含的,需要一个整数作为输入,我们称之为f(n)。 n的范围实际上是0 我想使用CUDA运行此功能,但我在概念上遇到了麻烦。也就是说,我知道如何使用块和线程索引来模拟上面提到的n。如幻灯片40中所示,nVidia Tutorial但是,当n> TotalNumberOfThreadsPer_CUDA_Call时会发生什么。 基本上,我为在CUDA上运行函数而进行的每次调用都会重置线程计数和块计数吗?如果是这样,是否有一种简单的方法来模拟n,如前所述,对于任意大的n? 感谢。
答案 0 :(得分:4)
当你想处理比线程更多的元素时,一种常见的模式是简单地以网格大小的块循环数据:
__global__ void kernel(int* data, size_t size) {
for (size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
idx < size;
idx += gridDim.x * blockDim.x) {
// do something with data[idx] ...
}
}
另一种选择是使用起始偏移量启动几个连续的内核:
__global__ void kernel(int* data, size_t size, size_t offset) {
size_t idx = blockIdx.x * blockDim.x + threadIdx.x + offset;
if (idx < size) {
// do something with data[idx] ...
}
}
// Host code
dim3 gridSize = ...;
dim3 blockSize = ...;
for (size_t offset = 0; offset < totalWorkSize; offset += gridSize * blockSize) {
kernel<<<gridSize, blockSize>>>(data, totalWorkSize, offset);
}
在这两种情况下,您都可以处理“任意大”的元素。您仍然受size_t
限制,因此对于10 ^ 11个元素,您需要编译64位代码。
答案 1 :(得分:0)
如果您必须存储数据而不是仅计算数据,则需要以迭代方法进行。 10 ^ 11任何类型的值都不适合GPU内存。
我还没有编译这段代码,但希望你能得到这个要点。
__device__ double my_function(int value);
__global__ void my_kernel(int* data, size_t offset, size_t chunk_size) {
size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
size_t stride = gridDim.x*blockDim.x;
while(idx<chunk_size){
data[idx]=my_function(idx+offset);
idx+=stride;
}
}
void runKernel(size_t num_values){
size_t block_size = 128;
size_t grid_size = 1024;
size_t free_mem, total_mem;
cudaMemGetInfo(&free, &total);
size_t chunk_size = sizeof(double)/free_mem;
double *data;
cudaMalloc(&data, chunk_size);
for(size_t i=0; i<num_values; i+=chunk_size){
my_kernel<<<grid_size, block_size>>>(data, i, chunk_size);
//copy to host and process
//or call another kernel on device to process further
}
//process remainder of values that need to be run assuming num_values%chunk_size!=0
}