【问题标题】:Opencl kernel runs on Intel platform but not on NvidiaOpencl 内核在 Intel 平台上运行,但不在 Nvidia 上
【发布时间】:2015-06-02 12:48:30
【问题描述】:

我正在使用 openCL 实现光线追踪器。我已经安装了 NVidia 的 CUDA sdk,一切似乎都设置得很好,我的两个平台都被检测到(英特尔和英伟达),并且每个平台都能看到它的设备(英特尔有 HD Graphics 4000,英伟达有我的 GPU:GeForce GT 630M)。

我的问题是我可以使用 Intel 平台运行我的应用程序,但不能使用 Nvidia 的平台。我不认为问题出在我的代码中,但这是我的设备代码:

#include "constants.h" //only a couple of #define

typedef struct Sphere {
    float x, y, z;
    float radius;
    float  r, g, b;
}Sphere;


float hit(Sphere s, float ox, float oy, float *n) {
    float radius = s.radius;
    float dx = ox - s.x;
    float dy = oy - s.y;
    if (dx*dx + dy*dy < radius*radius) {
        float dz = sqrt(radius*radius - dx*dx - dy*dy);
        *n = dz / sqrt(radius * radius);
        return dz + s.z;
    }
    return -INF;
}

__kernel void rayTracer(__global Sphere* spheres, write_only image2d_t res) {

    // Get the index of the current element to be processed
    int x = get_global_id(0);
    int y = get_global_id(1);

    int ox = x - WIDTH / 2;
    int oy = y - HEIGHT / 2;

    float   r = 0, g = 0, b = 0;
    float   maxz = (float) -INF;

    for (int i = 0; i<NUM_SPHERES; i++) 
    {
        float   n;
        float   t = hit(spheres[i], ox, oy, &n);
        if (t > maxz) 
        { 
            float fscale = 1;
            r = spheres[i].r * fscale;
            g = spheres[i].g * fscale;
            b = spheres[i].b * fscale;
        }
    }
    write_imagei(res, (int2)(x, y), (int4)(r, g, b, 0));
}

我的主机应用程序也很简单。我只是初始化 openCL 结构,设置数据,然后将其读回。

同样,当使用英特尔平台时,我的应用程序运行良好,我可以看到光线追踪图像。在使用英伟达的时候,虽然API错误码总是0,但是没有结果。

有没有人有任何想法可能是什么问题?

提前致谢

---编辑---

这是一些主机代码

设置 OpenCL 结构:

//Setup OpenCL
cl_platform_id platform = getPlatforms();
cl_device_id device = getDevices(platform, CL_DEVICE_TYPE_GPU);

cl_context_properties ctxProps[] =
{
    CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
    0, 0
};
cl_context ctx = clCreateContext(ctxProps, 1, &device, NULL, NULL, &err);
cl_command_queue queue1 = clCreateCommandQueue(ctx, device, NULL, &err);

GetPlatforms 和 GetDevices 是要求用户选择平台和设备的函数

创建程序并构建它:

cl_program prog = clCreateProgramWithSource(ctx, 1, srcs, &srcSize, &err);
err = clBuildProgram(prog, 1, &device, NULL, NULL, NULL);
if (err < 0)
{
    //PRINT BUILD ERROR
    size_t log_size;
    clGetProgramBuildInfo(prog, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size);
    char* log = (char*)calloc(log_size + 1, sizeof(char));
    clGetProgramBuildInfo(prog, device, CL_PROGRAM_BUILD_LOG, log_size + 1, log, NULL);
    printf("%s/n", log);
    free(log);
    std::cin >> err;
    return 1;
}
cl_kernel krn = clCreateKernel(prog, "rayTracer", &err);

//....CREATE SOME SPHERES...

//Setup device data
cl_image_format fmt;
fmt.image_channel_order = CL_RGBA;
fmt.image_channel_data_type = CL_UNSIGNED_INT8;

cl_mem spheresBuff = clCreateBuffer(ctx, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, spheres.size() * sizeof(Sphere), spheres.data(), &err);
cl_mem resBuff = clCreateImage2D(ctx, CL_MEM_WRITE_ONLY, &fmt, WIDTH, HEIGHT, 0, NULL, &err);

//Setup kernel arguments
err = clSetKernelArg(krn, 0, sizeof(cl_mem), (void*)&spheresBuff);
err = clSetKernelArg(krn, 1, sizeof(cl_mem), (void*)&resBuff);

//Run kernel
size_t gSize[] = { WIDTH, HEIGHT };
err = clEnqueueNDRangeKernel(queue1, krn, 2, NULL, gSize, NULL, 0, NULL, NULL);

//Read result
Image img = createRGBAImage(WIDTH, HEIGHT);

size_t origin[] = { 0, 0, 0 };
size_t region[] = { WIDTH , HEIGHT , 1 };
err = clEnqueueReadImage(queue1, resBuff, CL_TRUE, origin, region, 0, 0, img.pixel.data(), 0, NULL, NULL);

【问题讨论】:

  • 当你说'不显示结果'时,你的意思是结果图像是空白的吗?您能否向我们展示一些相关的主机代码(OpenCL 缓冲区/图像的创建、内核排队、主机设备传输)?
  • 呼应@jprice 在别处所说的:您是否在每个 API 调用中检查状态错误返回值?
  • 我已经放了一些主机代码。虽然其中没有错误检查代码,但我已经调试了应用程序并且错误变量始终为 0
  • 是的,我的意思是生成的图像是空白的
  • alpha值不应该是1,而不是0吗?此外,您应该使用write_imageui 而不是write_imagei,因为您的图像是CL_UNSIGNED_INT8,尽管我不确定这在实践中会有多大影响。

标签: c++ opencl gpu nvidia


【解决方案1】:

尝试在内核执行之前将clEnqueueMapBuffer 与CL_MAP_READ 一起使用,在内核执行之后为您的spheresBuff 使用clEnqueueUnmapMemObject

【讨论】:

    猜你喜欢
    • 2014-07-02
    • 2023-02-19
    • 2019-02-19
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-07
    相关资源
    最近更新 更多