3

我目前有一些数据想传递给我的 GPU 并将其乘以 2。

我创建了一个结构,可以在这里看到:

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

这个结构应该包含一个浮点数组。浮点数数组直到运行时我才会知道,因为它是由用户指定的。

主机代码:

typedef struct GPUPatternDataContatiner
{

    int nodeInput,nodeOutput,patternCount, offest;
    float* patterns;
} GPUPatternData; 
__kernel void patternDataAddition(__global GPUPatternData* gpd,__global GPUPatternData* output)
{
    int index = get_global_id(0);
    if(index < gpd->patternCount)
    {
        output.patterns[index] = gpd.patterns[index]*2;
    }
}

这是主机代码:

GPUPattern::GPUPatternData gpd;    
gpd.nodeInput = ptSet->getInputCount();
gpd.nodeOutput = ptSet->getOutputCount();
gpd.offest = gpd.nodeInput+gpd.nodeOutput;
gpd.patternCount = ptSet->getCount();
gpd.patterns = new cl_float [gpd.patternCount*gpd.offest];

GPUPattern::GPUPatternData gridC;
gridC.nodeInput = ptSet->getInputCount();
gridC.nodeOutput = ptSet->getOutputCount();
gridC.offest = gpd.nodeInput+gpd.nodeOutput;
gridC.patternCount = ptSet->getCount();
gridC.patterns = new cl_float [gpd.patternCount*gpd.offest];

所有数据都被初始化,然后用值初始化,然后传递给GPU

int elements = gpd.patternCount;
size_t ofsdf = sizeof(gridC);
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);

//This buffer is being written to only
cl_mem bufferC = clCreateBuffer(gpu.context,CL_MEM_WRITE_ONLY,dataSize,NULL,&err);
openCLErrorCheck(&err);
err = clEnqueueWriteBuffer(queue,bufferC,CL_TRUE,0,dataSize,(void*)&gridC,0,NULL,NULL);

一切都已构建,我只检查保持为 0 的错误

cl_program program = clCreateProgramWithSource(gpu.context,1, (const char**) &kernelSource,NULL,&err);

////Build program
err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);

char build[2048];
clGetProgramBuildInfo(program, gpu.device, CL_PROGRAM_BUILD_LOG, 2048, build, NULL);

////Create kernal
cl_kernel kernal = clCreateKernel(program, "patternDataAddition",&err);

////Set kernal arguments
err  = clSetKernelArg(kernal,  0, sizeof(cl_mem), &bufferA);
err |= clSetKernelArg(kernal,  1, sizeof(cl_mem), &bufferC);

然后被踢掉

size_t globalWorkSize = 1024;
size_t localWorkSize = 512;

err = clEnqueueNDRangeKernel(queue, kernal, 1, NULL, &globalWorkSize, &localWorkSize, 0, NULL, NULL); 

clFinish(queue);

在这一点上,一切都出错了

err = clEnqueueReadBuffer(queue, bufferC, CL_TRUE, 0, dataSize, &gridC, 0, NULL, NULL);
clFinish(queue);

这种情况下的错误是 -5 (CL_OUT_OF_RESOURCES)。

另外,如果我换行:

err = clEnqueueReadBuffer(queue, bufferC, CL_TRUE, 0, dataSize, &gridC, 0, NULL, 

至:

err = clEnqueueReadBuffer(queue, bufferC, CL_TRUE, 0, dataSize*1000, &gridC, 0, NULL, NULL);

我收到错误 -30 (CL_INVALID_VALUE)。

所以我的问题是为什么我在读回缓冲区时会遇到错误。另外我不确定我是否无法使用指向我的浮点数组的指针,因为这可能会给我错误的sizeof()使用方法,datasize从而给我错误的缓冲区大小。

4

3 回答 3

5

您不能将包含指针的结构传递给 OpenCL

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

您可以按照 Eric Bainville 指出的那样进行纠正,或者如果您对内存的限制不是很严格,您可以执行类似的操作

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

编辑:好的,如果内存是一个问题。由于您只使用patternsandpatternCount您可以从结构中复制模式并将它们分别传递给内核。

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

从 GPU复制patterns到 GPU并在GPU 上gpd分配空间。然后patternsgridC

您可以单独传递缓冲区

__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;
    }
}

当您从内核回来时,gridC.patterns直接将数据复制回


多一个 :

您不必更改 CPU 结构。它保持不变。然而这部分

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

应该改为类似

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

同样的事情也适用于gridC

当您复制回来时,将其复制到gridC_dataPointerAKAgridC.dataPointer

然后继续使用该结构,就好像什么都没发生一样。

于 2013-03-26T17:30:14.273 回答
1

问题可能出在结构内的指针上。

在这种情况下,我建议将 nInput,nOutput,patternCount,offset 作为内核参数传递,将模式作为浮点缓冲区传递:

__kernel void patternDataAddition(int nInput,int nOutput,
    int patternCount,int offset,
    __global const float * inPatterns,
    __global float * outPatterns)
于 2013-03-26T16:13:55.250 回答
-1

我知道它现在不是实际的,但我以其他方式传递了这个问题:您的代码为结构分配内存的数据保持不变,但结构应该改为

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

使用这个“功能”,我为 OpenCL 创建了向量

于 2014-12-24T07:07:26.050 回答