【问题标题】:What is the total thread count(executed over time, not parallel) for CUDA?CUDA 的总线程数(随时间执行,而不是并行执行)是多少?
【发布时间】:2014-12-19 09:40:12
【问题描述】:

我需要执行一个函数大约 10^11 次。该函数是自包含的,需要一个整数作为输入,我们称之为 f(n)。 n 的范围实际上是 0

我想使用 CUDA 运行这个函数,但我在概念上遇到了麻烦。也就是说,我知道如何使用块和线程索引来模拟上面提到的 n。如幻灯片 40 所示,nVidia Tutorial 但是,当 n>TotalNumberOfThreadsPer_CUDA_Call 时会发生什么。

基本上,每次调用我在 CUDA 上运行函数时,线程数和块数是否都会重置?如果是这样,是否有一种简单的方法来模拟 n,如前所述,用于任意大的 n?

谢谢。

【问题讨论】:

  • 进行几个内核调用并传递一个偏移量作为参数? myKernel(size_t startOffset) { size_t idx = startOffset + blockIdx.x * blockDim.x + threadIdx.x; ... } 或者在你的内核中做一个循环。 for (size_t idx = blockDim.x * ...; idx < 10^11; idx += blockDim.x * gridDim.x) { ... }
  • @ParkYoung-Bae 你真的应该写更多的答案来清除未回答的标签上的问题。为您的评论 +1
  • @MichaelHaidl 抱歉,我确实有这个坏习惯。

标签: c++ cuda parallel-processing


【解决方案1】:

当您想要处理的元素多于线程数时,一种常见的模式是简单地以网格大小的块循环遍历您的数据:

__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 位。

【讨论】:

  • 这两个选项可以帮到我。谢谢。
【解决方案2】:

如果您必须存储数据而不仅仅是计算数据,则需要以迭代方法进行。任何类型的 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
}

【讨论】:

  • 对于每个 CUDA 调用,结果都存储在内存中,发送到 RAM,然后写入文件。所以我存储、移动、复制、清除和重复。感谢您的建议。
猜你喜欢
  • 2021-10-16
  • 2011-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-22
  • 1970-01-01
  • 2015-11-05
相关资源
最近更新 更多