2016-01-12 63 views
1

我写了一个内核,它应该做的什么都没有,除了从添加一个到FLOAT3的每个组件:OpenCL - 写入缓冲区为零?

__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时,每个分量都是零。这里是neccassary代码:

(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; 

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

感谢

+0

1)的可能尺寸为您提供了指针的大小,2)也许cl_float3需要由cl_float4被替换,因为驱动程序或硬件 –

回答

1

你的代码段包含了一些典型的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)。但是,在这里,您必须将指针传递到包含数据的主机上的区域。因此,改变&particlesparticles

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_float3与​​相同。这可能不适用于您的/每个平台,因此您应始终在主机代码和内核代码中使用相同的类型。另外,在您的内核代码中,您应该/必须使用类型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()"); 
+0

的设备侧谢谢为了这个真棒帮助!它现在有效! – 3DExtended