【问题标题】:Executing different kernels on different GPUs simultaneously同时在不同的 GPU 上执行不同的内核
【发布时间】:2012-07-26 04:44:17
【问题描述】:

基本上我有两个 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);

我走对了吗?

【问题讨论】:

    标签: opencl


    【解决方案1】:

    这取决于您实际填充device 数组的方式。如果您正确初始化它,创建跨越设备的context 是正确的。

    很遗憾,您对内核和命令队列有错误的认识。 kernel 是从针对特定上下文的程序创建的。另一方面,queue 用于与某个设备进行通信。您要做的是为每个设备创建一个队列不是内核:

    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_context 及其关联设备创建和构建cl_program
    • cl_kernel 是从cl_program 中提取的,但只能在与程序上下文关联的设备上使用,
    • cl_command_queue 是为属于特定上下文的特定设备创建的,
    • 内存操作和内核调用被排入命令队列并在相应的设备上执行。

    【讨论】:

    • 同意。另请注意,不同的实现处理跨多个设备分配工作负载的方式不同(有时甚至会阻止 clEnqueueNDRangeKernel stackoverflow.com/questions/11562543/…) - 在某些情况下可能性能较低。要真正跨两个设备分离处理并自行控制,您可以使用两个上下文,每个上下文都由一个设备创建。
    • 谢谢。只是一个简单的问题,我可以不使用单个 clEnqueueNDRangeKernel 语句来启动两个内核吗?
    • 不,不是。但在 OpenCL 程序中,如果您真的只是想拆分逻辑,您可以调用同一程序中定义的其他函数。
    • @matthias :我尝试按照您建议的方式在不同设备上运行内核。我什至为每个设备维护了不同的上下文。第一个内核正确执行,但遇到第二个 NDRangeKernel 时出现“访问冲突读取位置”错误。我看到内存分配正确,没有空指针。为什么会发生这个错误?
    猜你喜欢
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 2021-09-21
    • 2022-01-17
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    相关资源
    最近更新 更多