【问题标题】:How does CUDA handle thread offset as in OpenCL?CUDA 如何处理 OpenCL 中的线程偏移?
【发布时间】:2018-07-07 08:13:03
【问题描述】:

例如,我可以在 OpenCL 中启动带有线程 id 偏移量的内核,因此当使用多个 GPU 时,第二个 GPU 线程可以直接从任意整数值开始:

GPU1: thread idx 0 to k
GPU2: thread idx k+1 to N

所有 GPU 的内核看起来都完全相同:

__kernel(..)
{
   int threadId=get_global_id(0); // this starts from k+1 for GPU2
   ..
}

驱动 API 中调用内核时,在 CUDA 中什么是等效的?

OpenCL 有

cl_int clEnqueueNDRangeKernel ( cl_command_queue command_queue,
    cl_kernel kernel,
    cl_uint work_dim,
    const size_t *global_work_offset, // this can be given k+1
    const size_t *global_work_size,
    const size_t *local_work_size,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event)

我是否必须自己在内核中嵌入偏移量,例如下面的示例才能在多 GPU 上使用外观最相似的内核?

__global__ void vecAdd(.., int * gpuParams)
{
    int offset=gpuParams[0];
    int threadId = offset + blockIdx.x * blockDim.x + threadIdx.x;
}

(这是用于扁平缓冲区访问和内核)

这个偏移量会在每次内核启动之前动态改变,所以我猜我不能使用#define。

Cuda 驱动 api 有这个用于启动内核:

CUresult cuLaunchKernel ( CUfunction f, unsigned int  gridDimX, 
                unsigned int  gridDimY, unsigned int  gridDimZ, 
                unsigned int  blockDimX, unsigned int  blockDimY, 
                unsigned int  blockDimZ, unsigned int  sharedMemBytes, 
                CUstream hStream, void** kernelParams, void** extra )

【问题讨论】:

  • 我知道 CUDA 不是 OpenCL,但 Nvidia 确实运行 OpenCL 并使用其线程偏移量,我需要做 Nvidia 在后台所做的事情吗?这是黑客级别的东西吗?我可以使用网格作为多个块大小的偏移量,但是如何在第一个块中添加线程偏移量?

标签: cuda opencl offset


【解决方案1】:

CUDA 中没有与之等效的功能,但您也不需要它。

在标准 CUDA 模型中,您无法通过单个 API 调用在多个设备上启动内核(从技术上讲,您也无法通过单个 API 调用在多个设备上分配内存)。每个 GPU 都是有效独立的。

NVIDIA 已引入多设备启动和同步方法作为 CUDA 9 中新的 cooperative groups 功能的一部分,但这些与您所询问的完全不同。

【讨论】:

  • 我正在使用 CUDA 8.0 第一次更新,但我会检查它,我记得我以前见过它,但认为它仅适用于双 GPU 显卡。
  • 发现cudaMemcpyToSymbol 可以在不借助内核参数的情况下进行隐式偏移数组初始化,并且内核对于所有gpus 看起来都相同,并添加了get_global_cuda_offset(dimension) 函数的实现。
  • @huseyintugrulbuyukisik 你也不需要那个。任何 CUDA 指针类型都支持算术。您可以直接将偏移量添加到任何指针,并将该偏移量传递给内核。唯一不能这样做的是符号,这就是 API 调用有偏移量的原因。
  • 你说得对,它更容易,但如果所有 gpus 还需要访问同一数组的元素 1、2、3、4、5(读取)以及它们自己的范围(写入)(之后他们自己的偏移量)?那么这个指针技巧会让 1,2,3,4,5 无法访问吗?一个例子可以是 nbody 算法所有对(但没有写入)。我的意图是为所有设备提供完全相同的 cuda 内核字符串。(但在该内核之前自动添加一些定义是可以的)
猜你喜欢
  • 2015-03-18
  • 1970-01-01
  • 2014-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多