如何使用多个并行运行的工作项调用单个工作组?

时间:2014-04-30 07:36:01

标签: opencl

我正处于OpenCl的初创公司,仍然在学习。

内核代码:

__kernel void gpu_kernel(__global float* data)
{
    printf("workitem %d invoked\n", get_global_id(0));
    int x = 0;
    if (get_global_id(0) == 1) {
        while (x < 1) {
            x = 0;
        }
    }
    printf("workitem %d completed\n", get_global_id(0));
}

用于调用内核的C代码

size_t global_item_size = 4; // number of workitems total
size_t local_item_size = 1; // number of workitems per group
ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);

输出继电器:

workitem 3 invoked
workitem 3 completed
workitem 0 invoked
workitem 0 completed
workitem 1 invoked
workitem 2 invoked
workitem 2 completed

## Here code is waiting on terminal for Workitem #1 to finish, which will never end

这清楚地表明,所有工作项都是平行的(但在不同的工作组中)。

另一个用于调用内核的C代码(用于具有4个工作项的1个工作组)

size_t global_item_size = 4; // number of workitems total
size_t local_item_size = 4; // number of workitems per group
ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);

输出继电器:

workitem 0 invoked
workitem 0 completed
workitem 1 invoked
## Here code is waiting on terminal for Workitem #1 to finish, which will never end

这清楚地表明,这是按顺序运行的(这就是为什么它完成了第一个工作项目然后被困在第二个和休息状态永远不会被执行)

我的问题:

我需要调用1个工作组,其中包含4个并行运行的工作项。所以我可以在我的代码中使用屏障(我猜这只能在单个工作组中使用)?

任何帮助/建议/指针都将受到赞赏。

1 个答案:

答案 0 :(得分:3)

您的第二个主机代码段正确启动包含4个工作项的单个工作组。您无法保证这些工作项将并行运行,因为硬件可能没有资源来执行此操作。但是,他们同时运行 ,这正是您需要的,以便能够使用工作组同步构造(如障碍)。有关并行性和并发性之间差异的简要描述,请参阅this Stack Overflow question。从本质上讲,工作组中的工作项将相互独立地前进,即使它们实际上并不是并行执行。

  

OpenCL 1.2规范(第3.2节:执行模型)

     

给定工作组中的工作项同时在单个计算单元的处理元素上执行。

基于您之前关于类似主题的问题,我假设您正在使用针对CPU的AMD的OpenCL实现。大多数OpenCL CPU实现的工作方式是将工作组中的所有工作项序列化为单个线程。然后,该线程依次执行每个工作项(为了参数而忽略向量化),当它们完成或遇到障碍时在它们之间切换。这就是它们实现并发执行的方式,并为您提供所需的所有保证,以便在内核中安全地使用障碍。并行执行是通过拥有多个工作组来实现的(如第一个示例所示),这将导致多个线程在多个核心上执行(如果可用)。

如果你用屏障取代无限循环,你会清楚地看到它确实有用。