Passing struct to GPU with OpenCL that contains an array of floats

落花浮王杯 提交于 2019-11-30 16:16:57

You cannot pass a struct that contains pointers into OpenCL

http://www.khronos.org/registry/cl/specs/opencl-1.2.pdf (Section 6.9)

You can either correct as Eric Bainville pointed out or if you are not very restrict on memory you can do something like

struct GPUPatternData
{
    cl_int nInput,nOutput,patternCount, offest;
    cl_float patterns[MAX_SIZE];
};

EDIT: OK if memory is an issue. Since you only use the patterns and patternCount you can copy the patterns from the struct and pass them to the kernel separately.

struct GPUPatternData
    {
        cl_int nInput,nOutput,patternCount, offest;
        cl_float patterns*;
    };

copy patterns to GPU from gpd and allocate space for patterns in gridC on GPU. then

You can pass the buffers separately

__kernel void patternDataAddition(int gpd_patternCount,
    __global const float * gpd_Patterns,
    __global float * gridC_Patterns) {

    int index = get_global_id(0);
    if(index < gpd_patternCount)
    {
        gridC_Patterns[index] = gpd_Patterns[index]*2;
    }
}

when you come back from the kernel copy the data back to gridC.patterns directly


One more :

You don't have to change your CPU struct. It stays the same. However this part

size_t dataSize = sizeof(GPUPattern::GPUPatternData)+ (sizeof(cl_float)*elements);

cl_mem bufferA = clCreateBuffer(gpu.context,CL_MEM_READ_ONLY,dataSize,NULL,&err);
openCLErrorCheck(&err);
//Copy the buffer to the device
err = clEnqueueWriteBuffer(queue,bufferA,CL_TRUE,0,dataSize,(void*)&gpd,0,NULL,NULL);

should be changed to something like

size_t dataSize = (sizeof(cl_float)*elements);  // HERE
float* gpd_dataPointer = gpd.patterns;    // HERE

cl_mem bufferA = clCreateBuffer(gpu.context,CL_MEM_READ_ONLY,dataSize,NULL,&err);
openCLErrorCheck(&err);

// Now use the gpd_dataPointer
err = clEnqueueWriteBuffer(queue,bufferA,CL_TRUE,0,dataSize,(void*)&(gpd_dataPointer),0,NULL,NULL);

Same thing goes for the gridC

And when you copy back, copy it to gridC_dataPointer AKA gridC.dataPointer

And then continue using the struct as if nothing happened.

The problem is probably with the pointer inside your struct.

In this case, I would suggest to pass nInput,nOutput,patternCount,offset as kernel args, and the patterns as a buffer of float:

__kernel void patternDataAddition(int nInput,int nOutput,
    int patternCount,int offset,
    __global const float * inPatterns,
    __global float * outPatterns)

I know that it is not actual now, but i passed this problem in other way: Your code for allocation memory for struct with data stay same, but struct should bu changed to

typedef struct GPUPatternDataContatiner
{
    int nodeInput, nodeOutput, patternCount, offest;
    float patterns[0];
} GPUPatternData;

Using this "feature" i have created vectors for OpenCL

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!