【问题标题】:openCL wrong resultopenCL 错误结果
【发布时间】:2019-12-20 00:06:47
【问题描述】:

有人能解释一下为什么会这样吗? 我认为它会增加我的数组的值。

#include <iostream>
#pragma comment(lib, "OpenCL.lib")
#include <CL/cl.h>

const std::string source_str = R"(
__kernel void add(__global int* c) {

    int i = get_global_id(0);

    c[i]=c[i]+1;
})";

size_t source_size = source_str.length();
cl_platform_id platform_id = NULL;
cl_device_id device_id = NULL;
cl_uint ret_num_devices;
cl_uint ret_num_platforms;
cl_int ret;
cl_context context;
cl_command_queue command_queue;
cl_mem a_mem_obj;
cl_program program;
cl_kernel kernel;
int* a;
#define SIZE 100

// ## You may add your own initialization routines here ##
void init() {
    ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
    if (ret != CL_SUCCESS)
        std::cout << ret << 1;
    ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1,
        &device_id, &ret_num_devices);

    if (ret != CL_SUCCESS)
        std::cout << ret << 2;

    // Create an OpenCL context
    context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);
    if (ret != CL_SUCCESS)
        std::cout << ret << 3;

    // Create a command queue
    command_queue = clCreateCommandQueue(context, device_id, 0, &ret);
    if (ret != CL_SUCCESS)
        std::cout << ret << 4;

    a_mem_obj = clCreateBuffer(context, CL_MEM_READ_WRITE,
        SIZE * sizeof(int), NULL, &ret);
    if (ret != CL_SUCCESS)
        std::cout << ret << 6;

    // Create a program from the kernel source
    program = clCreateProgramWithSource(context, 1,
        (const char**)&source_str, (const size_t*)&source_size, &ret);
    if (ret != CL_SUCCESS)
        std::cout << ret << 9;

    // Build the program
    ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
    if (ret != CL_SUCCESS)
        std::cout << ret << 10;

    // Create the OpenCL kernel
    kernel = clCreateKernel(program, "add", &ret);
    if (ret != CL_SUCCESS)
        std::cout << ret << 11;

    // Set the arguments of the kernel
    ret = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void*)&a_mem_obj);
    if (ret != CL_SUCCESS)
        std::cout << ret << 13;
}

void KernelStart() {

    // Copy to the memory buffers
    ret = clEnqueueWriteBuffer(command_queue, a_mem_obj, CL_TRUE, 0,
        SIZE * sizeof(int), a, 0, NULL, NULL);
    if (ret != CL_SUCCESS)
        std::cout << ret << 7;

    // Execute the OpenCL kernel on the list
    size_t static global_item_size = SIZE; // Process the entire lists
    size_t static local_item_size = 64; // Divide work items into groups of 64
    ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL,
        &global_item_size, &local_item_size, 0, NULL, NULL);
    if (ret != CL_SUCCESS)
        std::cout << ret << 14;

    ret = clEnqueueReadBuffer(command_queue, a_mem_obj, CL_TRUE, 0,
        SIZE * sizeof(int), a, 0, NULL, NULL);
    if (ret != CL_SUCCESS)
        std::cout << ret << 15;
}

int main() {
    a = new int[SIZE];
    for (size_t i = 0; i < SIZE; i++)
    {
        a[i] = 1;
    }
    for (size_t i = 0; i < SIZE; i++)
    {
        std::cout << a[i];
    }
    std::cout << std::endl;
    init();
    KernelStart();
    for (size_t i = 0; i < SIZE; i++)
    {
        std::cout << a[i];
    }
}

结果:

111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

-4913-541411111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

【问题讨论】:

  • 在init()和KernelStart()这两个函数前后添加一些打印;所以你可以隔离两个函数的输出。

标签: opencl


【解决方案1】:

您的日志记录已经向您展示了正在发生的事情,尽管不是特别可读。

第一个问题

你的程序的输出:

-4913

对应代码:

    // Set the arguments of the kernel
    ret = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void*)&a_mem_obj);
    if (ret != CL_SUCCESS)
        std::cout << ret << 13;

-49CL_INVALID_ARG_INDEX。内核参数从 0 开始编号,您的内核有 1 个参数,因此唯一有效的索引是 0。

第二个问题

你的程序的输出:

-5414

代码:

#define SIZE 100

…

    // Execute the OpenCL kernel on the list
    size_t static global_item_size = SIZE; // Process the entire lists
    size_t static local_item_size = 64; // Divide work items into groups of 64
    ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL,
        &global_item_size, &local_item_size, 0, NULL, NULL);
    if (ret != CL_SUCCESS)
        std::cout << ret << 14;

-54 对应于CL_INVALID_WORK_GROUP_SIZE

3 possible reasons specified:

  • CL_INVALID_WORK_GROUP_SIZE 如果指定了 local_work_size 并且 global_work_size 指定的工作项数量不能被 local_work_size 给定的工作组大小整除,或者与程序源中使用 __attribute__((reqd_work_group_size(X, Y, Z))) 限定符为内核指定的工作组大小不匹配.
  • CL_INVALID_WORK_GROUP_SIZE 如果指定了 local_work_size 并且计算为local_work_size[0] *... local_work_size[work_dim - 1] 的工作组中的工作项总数大于clGetDeviceInfo 的 OpenCL 设备查询表中CL_DEVICE_MAX_WORK_GROUP_SIZE 指定的值。
  • CL_INVALID_WORK_GROUP_SIZE 如果local_work_sizeNULL 并且__attribute__((reqd_work_group_size(X, Y, Z))) 限定符用于在程序源中声明内核的工作组大小。

你的本地大小是 64,你的全局大小是 100。这意味着你遇到了第一个条件:你需要确保你的全局大小是本地大小的整数倍。

【讨论】:

    猜你喜欢
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 2020-02-12
    • 1970-01-01
    • 2018-08-25
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    相关资源
    最近更新 更多