OpenCL - 写入缓冲区为零?
OpenCL - Writing to the Buffer is zero?
我写了一个内核,它应该什么都不做,除了给 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;
有人可以帮我解决这个问题吗?
(任何线索都值得讨论...)
谢谢
您的代码片段包含一些典型的 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
)。但是,在这里您必须传递一个指向主机上包含数据的区域的指针。因此,将 &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
returns 类型 cl_mem
的值,表达式 sizeof(cl_Particle)
的计算结果与 sizeof(cl_mem)
相同。我建议始终在变量上调用 sizeof()
,因此您只需在一处更改 data-type:变量声明。
在我的平台上,cl_float3
与 cl_float4
相同。这在 your/every 平台上可能并非如此,因此您应该始终在主机代码和内核代码中使用相同的类型。此外,在您的内核代码中,您 should/must 使用类型 float4
而不是 cl_float4
.
我希望,我的 C 调用是正确的,因为我实际使用此 C++ 代码对其进行了测试。此代码片段包含固定的 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()");
我写了一个内核,它应该什么都不做,除了给 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;
有人可以帮我解决这个问题吗? (任何线索都值得讨论...)
谢谢
您的代码片段包含一些典型的 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
)。但是,在这里您必须传递一个指向主机上包含数据的区域的指针。因此,将 &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
returns 类型 cl_mem
的值,表达式 sizeof(cl_Particle)
的计算结果与 sizeof(cl_mem)
相同。我建议始终在变量上调用 sizeof()
,因此您只需在一处更改 data-type:变量声明。
在我的平台上,cl_float3
与 cl_float4
相同。这在 your/every 平台上可能并非如此,因此您应该始终在主机代码和内核代码中使用相同的类型。此外,在您的内核代码中,您 should/must 使用类型 float4
而不是 cl_float4
.
我希望,我的 C 调用是正确的,因为我实际使用此 C++ 代码对其进行了测试。此代码片段包含固定的 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()");