OpenCL global_work_size 不反映返回的实际 ID

OpenCL global_work_size does not reflect actual ids returned

我是 OpenCL 的新手,我似乎对我在 OpenCL C++ 中使用 enqueueNDRangeKernel 设置的 global_work_size 的含义感到困惑。

我的问题如下:

我必须使用内核文件中的以下代码来初始化矩阵:

kernel void init(global const int *n, global const int *m, global float *matrix, global int *all_positions)
{
    size_t position = get_global_id(0);
    all_positions[position] = position;
    int i = position / m[position];
    int j = position % m[position];
    matrix[position] = i * (n[position] - i - 1) * (2.f*i / n[position]) * j * (m[position] - j - 1) * (1.f*j / m[position]);
}

以及来自我的主机的这段代码

cl::Kernel init(program, "init");

// Prepare input data.
std::vector<int> all_positions(n*m, 0);
std::vector<int> input_n(n*m, n);
std::vector<int> input_m(n*m, m);

cl::Buffer N(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, input_n.size(), input_n.data());
cl::Buffer M(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, input_m.size(), input_m.data());

cl::Buffer MATRIX(context, CL_MEM_READ_WRITE, matrix.size(), matrix.data());

cl::Buffer ALLPOSITIONS(context, CL_MEM_WRITE_ONLY, all_positions.size(), all_positions.data());
// Set kernel parameters.
init.setArg(0, N);
init.setArg(1, M);
init.setArg(2, MATRIX);
init.setArg(3, ALLPOSITIONS);

// Launch kernel on the compute device.
queue.enqueueNDRangeKernel(init, cl::NullRange, N_SIZE);

// Get result back to host.
queue.enqueueReadBuffer(MATRIX, CL_TRUE, 0, matrix.size(), matrix.data());
queue.enqueueReadBuffer(ALLPOSITIONS, CL_TRUE, 0, all_positions.size(), all_positions.data());

在此代码示例中,nm 是确定矩阵大小的命令行参数。 matrix 是一维浮点向量,大小为 n * m.

据我所知,当我调用 queue.enqueueNDRangeKernel(init, cl::NullRange, N_SIZE) 时,N_SIZE 也等于 n * m,我将 global_work_size 设置为相同的数量(n * m).

问题是,当我启动我的程序时,我打印了结果 all_positions 向量的 int,我相信它的值应该从 0 开始到 n*m-1,但它结束了像这样:

0 1 2 3 4 5 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

(使用 n=5m=5

矩阵值也只计算到 matrix[6]

您在 GPU 上创建的缓冲区的大小太小。 例如 all_positions.size() returns 25。这是向量中元素的数量。 以字节为单位的实际大小为 25 * sizeof(int)。 所以写:

cl::Buffer ALLPOSITIONS(context, CL_MEM_WRITE_ONLY, all_positions.size()*sizeof(int), all_positions.data());

NMMATRIX 缓冲区创建进行相同的更改。 queue.enqueueReadBuffer 也必须这样做。 例如:

queue.enqueueReadBuffer(MATRIX, CL_TRUE, 0, matrix.size()*sizeof(float), matrix.data());

大部分sizeof(int)是4字节,你创建的Buffer是25字节长。所以只有 6 个元素而不是 25 个元素。