调用任何enqueue命令时,OpenCL CL_INVALID_COMMAND_QUEUE

时间:2015-11-10 10:16:45

标签: c++ c++11 opencl gpgpu

每当我在命令队列上调用enqueue命令返回值{{ product.description|nl2br }} 时,我就会得到。

锅炉板的东西(放在ctor中)运行得很好,但是当我调用处理内核执行的函数时,它会在排队的第一个位置发生故障。

我认为我的内核非常正确,因为任何OpenCL C编译器都没有抛出任何错误(AMD用于vga卡,INTEL用于处理器)。空内核也出现了同样的错误。

也许只是一个小碎屑导致了这个问题,但我没有看到它。

以下显示了我的构造函数应该可以正常工作:

CL_INVALID_COMMAND_QUEUE

这是应该处理内核执行的函数的第一部分。如果我注释掉内存缓冲区的入队,那么在将内核排入队列时会失败:

std::vector<cl_platform_id>             this->OCLPlatformList;
std::vector<std::vector<cl_device_id>>  this->OCLDevicesList;
std::vector<cl_context>                 this->OCLContext;

className::ctor()
{
    this->FFT_SIZE_3 = this->configuration->getFFTSize(FFT_MULT::FFT_3);

    cl_int err;

    this->samplesInBuffer = new std::complex<float>[this->FFT_SIZE_3]();

    // query OCL Platforms
    cl_uint platformCount;
    err = clGetPlatformIDs(0,NULL,&platformCount);
    OCLCheckErr(err);

    cl_platform_id* plBuffer = new cl_platform_id[platformCount];
    err = clGetPlatformIDs(platformCount,plBuffer,NULL);
    OCLCheckErr(err);

    this->OCLPlatformList.resize((unsigned int)platformCount);
    this->OCLDevicesList.resize((unsigned int)platformCount);
    this->OCLContext.resize((unsigned int)platformCount);
    for(cl_uint i = 0; i < platformCount; i++)
    {
        this->OCLPlatformList[i] = plBuffer[i];
    }
    delete[] plBuffer;


    // query OCL Devices
    cl_uint devCount;
    for(unsigned int i = 0; i < this->OCLPlatformList.size() - 1; i++)
    {
        err = clGetDeviceIDs(this->OCLPlatformList[i],CL_DEVICE_TYPE_ALL,0,NULL,&devCount);
        OCLCheckErr(err);

        cl_device_id* devBuffer = new cl_device_id[devCount];
        err = clGetDeviceIDs(this->OCLPlatformList[i],CL_DEVICE_TYPE_ALL,devCount,devBuffer,NULL);
        OCLCheckErr(err);

        this->OCLDevicesList[i].resize((unsigned int)devCount);

        std::cout << std::endl << "Platform #" << i << ": " <<    OCLGetPlatformName(this->OCLPlatformList[i]) << std::endl;
        for(cl_uint j = 0; j < devCount; j++)
        {
            this->OCLDevicesList[i][j] = devBuffer[j];
            std::cout << "|-- Device #" << j << ": " << OCLGetDeviceName(this->OCLDevicesList[i][j]) << std::endl;
        }
        std::cout << std::endl;
        delete[] devBuffer;


    }


    // create OCL Context
    cl_context_properties* cprops = new cl_context_properties[3];
    cprops[0] = ;
    cprops[2] = 0;
    for(unsigned int i = 0; i < this->OCLPlatformList.size() - 1; i++)
    {
        cl_device_id* devBuffer = new cl_device_id[this->OCLDevicesList[i].size()];
        unsigned int j = 0;
        for(std::vector<cl_device_id>::iterator it = this->OCLDevicesList[i].begin(); it != this->OCLDevicesList[i].end(); ++it)
        devBuffer[j++] = *it;

        cprops[1] = (cl_context_properties)this->OCLPlatformList[i];
        this->OCLContext[i] = clCreateContext(cprops,(cl_uint)this->OCLDevicesList[i].size(),devBuffer,NULL,NULL,&err);
    OCLCheckErr(err);

    }
    delete[] cprops;


    // create OCL Command Queue
    cl_queue_properties qprops[] =
    {
        CL_QUEUE_PROPERTIES,CL_QUEUE_ON_DEVICE_DEFAULT,0
    };
    this->OCLComQueue = clCreateCommandQueueWithProperties(this->OCLContext[0],this->OCLDevicesList[0][0],qprops,&err);
    OCLCheckErr(err);

    cl_int commSize;
    err = clGetCommandQueueInfo(this->OCLComQueue,CL_QUEUE_SIZE,sizeof(cl_int),&commSize,NULL);
    std::cout << this->OCLComQueue << " " << (long)commSize << std::endl;

    OCLCheckErr(OCLCompileKernelFromSource(this->OCLProgram,"Kkernel.cl",this->OCLContext[0],this->OCLDevicesList[0][0],true));

    this->kernel = clCreateKernel(this->OCLProgram,"Kkernel",&err);
    OCLCheckErr(err);


    // create OCL Buffer
    //std::complex<float> this->BufferA[this->sizeA];
    this->BufferACL = clCreateBuffer(this->OCLContext[0],(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR),
                                            (this->sizeA * sizeof(std::complex<float>)),this->BufferA,&err);
    OCLCheckErr(err);

    //std::complex<float> this->BufferB[this->sizeB * this->k];
    this->BufferBCL = clCreateBuffer(this->OCLContext[0],(CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR),
                                            (this->sizeB * this->k * sizeof(std::complex<float>)),BufferB,&err);
    OCLCheckErr(err);

    //std::complex<float> this->BufferB[this->l * this->k];
    this->BufferCCL = clCreateBuffer(this->OCLContext[0],(CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR),
                                            (this->l * this->k * sizeof(std::complex<float>)),this->BufferC,&err);
    OCLCheckErr(err);

    err = clSetKernelArg(this->kernel,0,sizeof(this->BufferACL),(void*)&this->BufferACL);
    OCLCheckErr(err);
    err = clSetKernelArg(this->kernel,1,sizeof(this->BufferBCL),(void*)&this->BufferBCL);
    OCLCheckErr(err);
    err = clSetKernelArg(this->kernel,2,sizeof(this->BufferCCL),(void*)&this->BufferCCL);
    OCLCheckErr(err);
    err = clSetKernelArg(this->kernel,3,sizeof(unsigned int),(void*)&this->k);
    OCLCheckErr(err);
}

最后但并非最不重要的是,这是内核的来源。它对l个工作组的k个工作项进行乘法运算:

void className::func1()
{
    long c = this->k - 1;

    for(std::list<std::complex<float>>::iterator it = this->sampleHistBuffer.begin(); it != this->sampleHistBuffer.end(); ++it)
    {
        cl_int err;
        cl_event event;
        clFinish(this->OCLComQueue);
        OCLCheckErr(err);

        err = clEnqueueWriteBuffer(this->OCLComQueue,this->BufferACL,CL_TRUE,0,(this->k * sizeof(std::complex<float>)),this->BufferA,0,NULL,&event);
        OCLCheckErr(err);
        cl_int state;
        do
        {
            clGetEventInfo(event,CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof(state),&state,NULL);
            if(state < 0)
                throw 11;
        }
        while(state >= CL_COMPLETE);

        size_t global_item_size = this->k * this->l;
        size_t local_item_size = this->k;
        err = clEnqueueNDRangeKernel(this->OCLComQueue,this->kernel,1,NULL,&global_item_size,&local_item_size,0,NULL,&event);
        OCLCheckErr(err);
        do
        {
            clGetEventInfo(event,CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof(state),&state,NULL);
            if(state < 0)
                throw 11;
        }
        while(state >= CL_COMPLETE);
     /*...*/
}

如果有一些未描述的功能(如float2 cmult(float2 A, float2 B) { float2 ret; ret.x = A.x * B.x; ret.y = A.y * B.y; return ret; } #pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable __kernel void Kkernel(__global float2* BufferA, __global float2* BufferB, __global float2* BufferC, unsigned int k) { size_t sampleWrkGp = get_group_id(0); size_t sampleWrkId = get_local_id(0); BufferC[(sampleWrkId * k) + sampleWrkId] = cmult(BufferA[sampleWrkId],BufferB[(sampleWrkId * k) + sampleWrkId]); } ),您可以确定它们是安全的而不是问题。

1 个答案:

答案 0 :(得分:0)

看起来您正在创建设备上命令队列(CL_QUEUE_ON_DEVICE_DEFAULT),然后尝试使用它来排队来自主机的命令。您只能从设备端使用设备端命令队列。使用常规命令队列(clCreateCommandQueue)进行主机端队列。