为什么有CL_DEVICE_MAX_WORK_GROUP_SIZE?

时间:2012-01-29 17:36:50

标签: opencl

我正在尝试理解诸如GPU之类的OpenCL设备的架构,我不明白为什么本地工作组中的工作项数量存在明确限制,即常量CL_DEVICE_MAX_WORK_GROUP_SIZE。

在我看来,这应该由编译器来处理,即如果一个(简单的一维)内核用本地工作组大小500执行而其物理最大值是100,并且内核看起来像例如这样:

__kernel void test(float* input) {
    i = get_global_id(0);
    someCode(i);
    barrier();
    moreCode(i);
    barrier();
    finalCode(i);
}

然后它可以自动转换为此内核上工作组大小为100的执行:

__kernel void test(float* input) {
    i = get_global_id(0);
    someCode(5*i);
    someCode(5*i+1);
    someCode(5*i+2);
    someCode(5*i+3);
    someCode(5*i+4);
    barrier();
    moreCode(5*i);
    moreCode(5*i+1);
    moreCode(5*i+2);
    moreCode(5*i+3);
    moreCode(5*i+4);
    barrier();
    finalCode(5*i);
    finalCode(5*i+1);
    finalCode(5*i+2);
    finalCode(5*i+3);
    finalCode(5*i+4);
}

但是,似乎默认情况下不会这样做。为什么不?有没有办法让这个过程自动化(除了自己编写预编译器)?或者是否存在一个内在的问题,可以使我的方法在某些例子上失败(你能给我一个)吗?

2 个答案:

答案 0 :(得分:4)

我认为CL_DEVICE_MAX_WORK_GROUP_SIZE的起源在于底层硬件实现。

多个线程同时在计算单元上运行,并且每个线程都需要保持状态(对于call,jmp等)。大多数实现都使用堆栈,如果你看看AMD Evergreen系列,它们是可用堆栈条目数量的硬件限制(每个堆栈条目都有子条目)。这实质上限制了每个计算单元可以同时处理的线程数。

至于编译器可以做到这一点使它成为可能。它可以工作但是理解它意味着重新编译内核。这并不总是可行的。我可以想象开发人员以二进制格式为每个平台转储编译内核的情况,并将其与其软件一起发送,仅仅是因为“不那么开源”的原因。

答案 1 :(得分:0)

编译器从设备中查询这些常量,以便在编译时确定合适的工作组大小(编译时当然是指编译内核)。我可能会误解你的意思,但似乎你正在考虑自己设定这些值,但实际情况并非如此。

责任在您的代码中,用于查询系统功能,以便为将运行的任何硬件做好准备。