【问题标题】:OpenCL - Writing to the Buffer is zero?OpenCL - 写入缓冲区为零?
【发布时间】:2016-04-17 09:46:44
【问题描述】:

我已经编写了一个内核,它应该什么都不做,除了向 float3 的每个组件添加一个:

__kernel void GetCellIndex(__global Particle* particles) {

   int globalID = get_global_id(0);
   particles[globalID].position.x += 1;
   particles[globalID].position.y += 1;
   particles[globalID].position.z += 1;
};

具有以下结构(在内核中)

typedef struct _Particle
{
    cl_float3 position;
}Particle;

我的问题是,当我将粒子数组写入 GPU 时,每个组件都为零。这是必要的代码:

(Particle*) particles = new Particle[200];
for (int i = 0; i < 200; i++)
{
    particles[i].position.x = 5f;
}

cl_Particles = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(Particle)*200, NULL, &err);
if (err != 0)
{
    std::cout << "CreateBuffer does not work!" << std::endl;
    system("Pause");
}

clEnqueueWriteBuffer(queue, cl_Particles, CL_TRUE, 0, sizeof(Particle) * 200, &particles, 0, NULL, NULL);


//init of kernel etc.



err = clSetKernelArg(kernel, 0, sizeof(Particle) * 200, &cl_Particles);
if (err != 0) {
    std::cout << "Error: setKernelArg 0 does not work!" << std::endl;
    system("Pause");
}

这是我在 CPU 上的结构:

typedef struct _Particle
{
    cl_float4 position;
}Particle;

有人可以帮我解决这个问题吗? (任何线索都值得讨论......)

谢谢

【问题讨论】:

  • 1) 也许 size of 给你指针的大小,2) 也许 cl_float3 需要在设备端替换为 cl_float4 因为驱动程序或硬件

标签: c struct kernel buffer opencl


【解决方案1】:

您的代码 sn-p 包含一些典型的 C 编程错误。一开始,

(Particle*) particles = new Particle[200];

没有将新变量particle 声明为指向Particle 的指针。必须是:

Particle *particles = new Particle[200];

接下来,在您的召唤中

clEnqueueWriteBuffer(queue, cl_Particles, CL_TRUE, 0, sizeof(Particle) * 200, &particles, 0, NULL, NULL);

您将指向 particles 的指针作为第 6 个参数 (ptr) 传递。但是,在这里您必须传递一个指向主机上包含数据的区域的指针。因此,将&amp;particles 更改为particles

clEnqueueWriteBuffer(queue, cl_Particles, CL_TRUE, 0, sizeof(Particle) * 200, particles, 0, NULL, NULL);

内核参数的设置也是错误的。在这里,您必须传递使用clCreateBuffer 创建的 OpenCL 缓冲区。因此,替换

err = clSetKernelArg(kernel, 0, sizeof(Particle) * 200, &cl_Particles);

与:

err = clSetKernelArg(kernel, 0, sizeof(cl_Particle), &cl_Particles);

clCreateBuffer 返回一个cl_mem 类型的值时,表达式sizeof(cl_Particle) 的计算结果与sizeof(cl_mem) 相同。我建议始终在变量上调用sizeof(),因此您只需在一个地方更改数据类型:变量声明。

在我的平台上,cl_float3cl_float4 相同。在您/每个平台上可能并非如此,因此您应该始终在主机代码和内核代码中使用相同的类型。此外,在您的内核代码中,您应该/必须使用类型 float4 而不是 cl_float4

我希望我能正确地调用 C 语言,因为我实际上是用这个 C++ 代码对其进行了测试。此代码 sn-p 包含作为 cmets 的固定 C 调用:

Particle *particles = new Particle[200];
for (int i = 0; i < 200; i++)
{
    //particles[i].position.x = 5f;
    particles[i].position.s[0] = 0x5f; // due to VC++ compiler
}

//cl_mem cl_Particles = cl_createBuffer(context, CL_MEM_READ_WRITE, sizeof(Particle)*200, NULL, &err); // FIXED
cl::Buffer cl_Particles(context, CL_MEM_READ_WRITE, sizeof(Particle)*200, NULL, &err); 
checkErr(err, "Buffer::Buffer()");

//err = clEnqueueWriteBuffer(queue, cl_Particles, CL_TRUE, 0, sizeof(Particle) * 200, particles, 0, NULL, NULL); // FIXED
queue.enqueueWriteBuffer(cl_Particles, CL_TRUE, 0, sizeof(Particle) * 200, particles, NULL, NULL);
checkErr(err, "ComamndQueue::enqueueWriteBuffer()");

//init of kernel
cl::Kernel kernel(program, "GetCellIndex", &err);
checkErr(err, "Kernel::Kernel()");

//err = clSetKernelArg(kernel, 0, sizeof(cl_Particle), &cl_Particles); // FIXED
err = kernel.setArg(0, sizeof(cl_Particles), &cl_Particles);
checkErr(err, "Kernel::setArg()");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    • 2016-09-16
    相关资源
    最近更新 更多