基本上我有两个 GPU,我想在每个 GPU 上执行一些内核。我不希望 GPU 在同一个内核上工作,每个内核都执行其中的一部分(我不知道这是否可能),以防万一我什至不想看到这种行为。
我只想确保两个设备都在运行。我已经为它们创建了上下文和命令队列。但我看到只有一个内核被执行,这意味着只有一个设备被使用。我就是这样做的。 . .
cl_device_id *device;
cl_kernel *kernels;
...
// creating context.
context = clCreateContext(0, num_devices, device, NULL, NULL, &error);
...
// creating command queues for all kernels
for(int i = 0; i<num_kenrels; i++)
cmdQ[i] = clCreateCommandQueue(context, *device, 0, &error);
...
// enqueue kernels
error = clEnqueueNDRangeKernel(*cmdQ, *kernels, 2, 0, glbsize, 0, 0, NULL, NULL);
我走的路对吗?
最佳答案
这取决于您实际填充device
数组的方式。如果您正确初始化它,则创建跨设备的 context
是正确的。
不幸的是,您对内核和命令队列的认识是错误的。 内核 是从针对特定上下文的程序创建的。另一方面,队列 用于与特定设备通信。您想要做的是为每个设备而不是内核创建一个队列:
for (int i = 0; i < num_devices; i++)
cmdQ[i] = clCreateCommandQueue(context, device[i], 0, &error);
现在您可以通过相应的命令队列将不同(或相同)的内核入队到不同的设备上:
clEnqueueNDRangeKernel(cmdQ[0], kernels[0], /* ... */);
clEnqueueNDRangeKernel(cmdQ[1], kernels[1], /* ... */);
总结术语:
cl_context
是为特定的cl_platform_id
创建的,就像是设备子集的容器,cl_program
是为cl_context
及其相关设备创建和构建的cl_kernel
是从cl_program
中提取的,但只能在与程序上下文关联的设备上使用,- 为属于特定上下文的特定设备创建一个
cl_command_queue
, - 内存操作和内核调用在命令队列中排队并在相应的设备上执行。
关于opencl - 同时在不同的 GPU 上执行不同的内核,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11658074/