OpenCL max_work_item_sizes

OpenCL max_work_item_sizes

我无法理解工作项约束的含义。我正在使用 pyopencl 并查看 max_work_item_sizes 它给出了我假设的每个维度的最大全局工作线程数。

import pyopencl as cl
import numpy as np

ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)

queue.device.max_work_item_sizes # [1024, 1024, 64]

我可以通过以下方式模拟 np.arange 函数:

prg = cl.Program(ctx, """
__kernel void arange(__global int *res_g)
{
  int gid = get_global_id(0);
  res_g[gid] = gid;
}
""").build()

res_g = cl.Buffer(ctx, cl.mem_flags.READ_WRITE, 4 * 4096)
prg.arange(queue, [4096], None, res_g)

# transfer back to cpu
res_np = np.empty(4096).astype(np.int32)
cl.enqueue_copy(queue, res_np, res_g)

assert (res_np == np.arange(4096)).all() # this is true

如何为第一个维度指定超过 1024 个工作项? max_work_item_sizes 是什么意思?

与此相关的另一个问题是,使用尽可能多的工作维度是否有益?据我了解,最多可以使用 3 个维度。可以通过以下方式使用 2 个工作项维度来模拟 np.arange

prg = cl.Program(ctx, """
__kernel void arange(__global int *res_g)
{
  int gid = get_global_id(0) * get_global_id(1);
  barrier(CLK_GLOBAL_MEM_FENCE);
  res_g[gid] = gid;
}
""").build()

res_g = cl.Buffer(ctx, cl.mem_flags.READ_WRITE, 4 * 4096)
prg.arange(queue, [64, 64], [1,1], res_g)

# transfer back to cpu
res_np = np.empty(4096).astype(np.int32)
cl.enqueue_copy(queue, res_np, res_g)

assert (res_np == np.arange(4096)).all()

由于某些原因,断言并不总是正确的

但我的问题是,在处理大数组时,是不是全部使用 3 个 work_item_dimensions 更好?还是将数组视为一维连续数组并仅使用 get_global_id(0)?

更好?

How is it possible to specify more than 1024 work items for the first dimension? What does the max_work_item_sizes mean?

max_work_item_sizes returns 每个工作组在每个维度中的最大工作项数。

通过将 None 作为第三个参数传递:

prg.arange(queue, [4096], None, res_g)
                          ^^^^

正在要求实现 select 最佳工作组规模。可以通过这种方式检查工作组大小,例如:

res_g[gid] = get_local_size(0);

在我的系统中 max_work_item_sizes=[4096, 4096, 4096] 并且 get_local_size(0) 返回的值为 1024,这意味着实施决定工作组大小为 1024 个项目,而 4096 / 1024 为我们安排了 4 个工作组。

指定工作组大小,例如 256 个工作项:

prg.arange(queue, [4096], [256], res_g)

将安排 4 倍以上的工作组。

Another question related to this is if it is beneficial to use as many work dimensions as possible? As I understand it possible to use 3 dimensions at most.

But my question is, when processing a large array, is it better to make use of all 3 work_item_dimensions? Or is it better to treat the array as a 1d contiguous array and only use get_global_id(0)?

根据我的经验,使用一维还是多维没有区别。所以你做对你来说更方便。

For some reason the assertion is not always true

那是因为您的代码中存在错误。计算索引应为:

int gid = get_global_id(0) * get_global_size(0) + get_global_id(1);