首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenCL内核导致应用程序无限期运行,只有在我关闭IDE之后才停止运行。

OpenCL内核导致应用程序无限期运行,只有在我关闭IDE之后才停止运行。
EN

Stack Overflow用户
提问于 2017-07-26 06:29:02
回答 1查看 240关注 0票数 1

我试图使用在GPU上运行部分OpenCL代码。我现在正在尝试运行处理YCbCr到RGB转换的函数。

请注意,到目前为止,我没有试图优化GPU代码。我只想要一个与CPU上的输出相同的输出。

函数最初是这样编写的:

代码语言:javascript
复制
void YCbCr_to_ARGB(uint8_t *YCbCr_MCU[3], uint32_t *RGB_MCU, uint32_t nb_MCU_H, uint32_t nb_MCU_V)
{

    uint8_t *MCU_Y, *MCU_Cb, *MCU_Cr;
    int R, G, B;
    uint32_t ARGB;
    uint8_t index, i, j;

    MCU_Y = YCbCr_MCU[0];
    MCU_Cb = YCbCr_MCU[1];
    MCU_Cr = YCbCr_MCU[2];
    for (i = 0; i < 8 * nb_MCU_V; i++) {
        for (j = 0; j < 8 * nb_MCU_H; j++) {
            index = i * (8 * nb_MCU_H)  + j;
            R = (MCU_Cr[index] - 128) * 1.402f + MCU_Y[index];
            B = (MCU_Cb[index] - 128) * 1.7772f + MCU_Y[index];
            G = MCU_Y[index] - (MCU_Cb[index] - 128) * 0.34414f -
                (MCU_Cr[index] - 128) * 0.71414f;
            /* Saturate */
            if (R > 255)
                R = 255;
            if (R < 0)
                R = 0;
            if (G > 255)
                G = 255;
            if (G < 0)
                G = 0;
            if (B > 255)
                B = 255;
            if (B < 0)
                B = 0;
            ARGB = ((R & 0xFF) << 16) | ((G & 0xFF) << 8) | (B & 0xFF);
            // ARGB = 0xFF << 8;
            RGB_MCU[(i * (8 * nb_MCU_H) + j)] = ARGB;
        }
    }
}

此函数的变量以下列方式在main.c中声明:

代码语言:javascript
复制
cl_uchar* YCbCr_MCU[3] = { NULL, NULL, NULL};
cl_uint* RGB_MCU = NULL;

这些变量的内存是以这种方式分配的:

代码语言:javascript
复制
if (screen_init_needed == 1) 
{
                    screen_init_needed = 0;

.....
.....
//Some code

for (index = 0 ; index < SOF_section.n ; index++) {
YCbCr_MCU[index] = malloc(MCU_sx * MCU_sy * max_ss_h * max_ss_v);

YCbCr_MCU_ds[index] = malloc(MCU_sx * MCU_sy * max_ss_h * max_ss_v);

}

RGB_MCU = malloc (MCU_sx * MCU_sy * max_ss_h * max_ss_v * sizeof(cl_int));
}

break;
}

我将其直接复制并粘贴到我的.cl文件中,并做了一些小的修改,使其符合OpenCL标准。修改后的OpenCL代码如下所示:

代码语言:javascript
复制
__kernel void YCbCr_to_ARGB(__global uchar* YCbCr_MCU[3], __global uint* RGB_MCU, uint nb_MCU_H, uint nb_MCU_V)
    {        
        __global uchar *MCU_Y, *MCU_Cb, *MCU_Cr;
        int R, G, B;
        uint ARGB;
        uchar index, i, j;

        MCU_Y = YCbCr_MCU[0];
        MCU_Cb = YCbCr_MCU[1];
        MCU_Cr = YCbCr_MCU[2];

//Same code as the first code snippet
        ......
        ......
        ......

    }

当我在.cl文件中使用上面的内核代码构建和运行我的应用程序时,我得到了错误。其中一个错误声明OpenCL不允许指针参数指针。

为了避免这些错误,我再次修改了代码,如下所示:

代码语言:javascript
复制
__kernel void YCbCr_to_ARGB(__global uchar YCbCr_MCU[3], __global uint* RGB_MCU, uint nb_MCU_H, uint nb_MCU_V)
{         
            __global uchar *MCU_Y, *MCU_Cb, *MCU_Cr;
            int R, G, B;
            uint ARGB;
            uchar index, i, j;

            MCU_Y = &YCbCr_MCU[0];
            MCU_Cb = &YCbCr_MCU[1];
            MCU_Cr = &YCbCr_MCU[2];

    //Same code as the first code snippet
            ......
            ......
            ......   
}

当我再次构建和运行应用程序时,我没有收到任何错误。这促使我为这个内核编写主机代码。

看起来是这样的:

代码语言:javascript
复制
 color_kernel= clCreateKernel(program, "YCbCr_to_ARGB", &ret);

//YCbCr_MCU for YCbCrtoARGB
cl_mem colorMCU_GPU= clCreateBuffer(context, CL_MEM_READ_WRITE, 3 * sizeof(cl_uchar), NULL, &ret);


//rgb_MCU for YCbCrtoARGB
cl_mem RGB_GPU= clCreateBuffer(context, CL_MEM_READ_WRITE,  sizeof(cl_uint), NULL, &ret);

我在main.c中调用原始函数的地方调用了内核参数。我以以下方式为这个内核执行了其余的步骤:

代码语言:javascript
复制
if(color&&(SOF_section.n>1)
{
ret = clEnqueueWriteBuffer(command_queue, colorMCU_GPU, CL_TRUE, 0, 3 * sizeof(cl_uchar), YCbCr_MCU, 0, NULL, NULL);

ret = clEnqueueWriteBuffer(command_queue, RGB_GPU, CL_TRUE, 0,  sizeof(cl_uint), RGB_MCU, 0, NULL, NULL);

ret = clSetKernelArg(color_kernel, 0, sizeof(cl_mem), (void *)&colorMCU_GPU);
ret |= clSetKernelArg(color_kernel, 1, sizeof(cl_mem), (void *)&RGB_GPU);
ret = clSetKernelArg(color_kernel, 2, sizeof(cl_uint), (void *)&max_ss_h);
ret |= clSetKernelArg(color_kernel, 3, sizeof(cl_uint), (void *)&max_ss_v);

ret = clEnqueueTask(command_queue, color_kernel, 0, NULL, NULL);

ret = clEnqueueReadBuffer(command_queue, RGB_GPU, CL_TRUE, 0, sizeof(cl_uint), RGB_MCU, 0, NULL, NULL);

//YCbCr_to_ARGB(YCbCr_MCU, RGB_MCU, max_ss_h, max_ss_v);

在我使用这些参数运行和构建代码之后,代码将无限期地运行(它的输出应该是在屏幕上运行的电影剪辑)。使用这段代码,我只能得到一个黑色屏幕)。之后,我必须关闭Eclipse并重新打开它,以便对代码进行额外的更改。

是什么导致程序的行为是这样的?是否可以在GPU上安全地运行这个函数?

更新:

我遵循Anders Cedronius的建议,并以以下方式更改了我的内核代码:

代码语言:javascript
复制
__kernel void YCbCr_to_ARGB(__global uchar YCbCr_MCU[3], __global uint* RGB_MCU, uint nb_MCU_H, uint nb_MCU_V)
{
   printf("Doing color conversion\n");  

    __global uchar *MCU_Y, *MCU_Cb, *MCU_Cr;
    int R, G, B;
    uint ARGB;
    uchar index, i, j;

    i= get_global_id(0);
    j= get_global_id(1);

    MCU_Y = &YCbCr_MCU[0];
    MCU_Cb = &YCbCr_MCU[1];
    MCU_Cr = &YCbCr_MCU[2];

    if (i < 8 * nb_MCU_V && j < 8 * nb_MCU_H)
    {
            index = i * (8 * nb_MCU_H)  + j;
            R = (MCU_Cr[index] - 128) * 1.402f + MCU_Y[index];
            B = (MCU_Cb[index] - 128) * 1.7772f + MCU_Y[index];
            G = MCU_Y[index] - (MCU_Cb[index] - 128) * 0.34414f -
                (MCU_Cr[index] - 128) * 0.71414f;


            /* Saturate */
            if (R > 255)
                R = 255;
            if (R < 0)
                R = 0;
            if (G > 255)
                G = 255;
            if (G < 0)
                G = 0;
            if (B > 255)
                B = 255;
            if (B < 0)
                B = 0;
            ARGB = ((R & 0xFF) << 16) | ((G & 0xFF) << 8) | (B & 0xFF);
            // ARGB = 0xFF << 8;
        RGB_MCU[(i * (8 * nb_MCU_H) + j)] = ARGB;


}

printf("Finished color conversion\n");
}

我调用内核的主机代码现在如下所示:

代码语言:javascript
复制
color_kernel= clCreateKernel(program, "YCbCr_to_ARGB", &ret);

我以以下方式设置工作大小和内核参数:

代码语言:javascript
复制
ret = clEnqueueWriteBuffer(command_queue, colorMCU_GPU, CL_TRUE, 0, 3*sizeof(cl_uchar), YCbCr_MCU, 0, NULL, NULL);
chk(ret, "clEnqueueWriteBuffer");

ret = clEnqueueWriteBuffer(command_queue, RGB_GPU, CL_TRUE, 0,  sizeof(cl_uint), RGB_MCU, 0, NULL, NULL);
chk(ret, "clEnqueueWriteBuffer");


ret = clSetKernelArg(color_kernel, 0, sizeof(cl_mem), (void *)&colorMCU_GPU);
ret |= clSetKernelArg(color_kernel, 1, sizeof(cl_mem), (void *)&RGB_GPU);
ret = clSetKernelArg(color_kernel, 2, sizeof(cl_uint), (void *)&max_ss_h);
ret |= clSetKernelArg(color_kernel, 3, sizeof(cl_uint), (void *)&max_ss_v);


size_t itemColor[2] = {1, 1};

ret = clEnqueueNDRangeKernel(command_queue, kernel, 2, NULL, itemColor, NULL, 0, NULL, NULL);
chk(ret, "clEnqueueNDRange");

ret = clEnqueueReadBuffer(command_queue, RGB_GPU, CL_TRUE, 0, sizeof(cl_uint), RGB_MCU, 0, NULL, NULL);


clFinish(command_queue);

我运行了这段代码,我再也没有黑屏幕了。但是,"YCbCr到RGB“的内核现在还没有被识别出来。甚至我的printf注释都没有显示在输出控制台上。就像我的代码没有颜色转换功能一样。

更新:

我没有在命令EnqueueNDRangeKernel中更改内核的名称。我更改了名称,现在printf语句出现在控制台上。然而,我仍然没有得到正确的输出。

代码语言:javascript
复制
size_t itemColor[2] = {1, 1};

ret = clEnqueueNDRangeKernel(command_queue, color_kernel, 2, NULL, itemColor, NULL, 0, NULL, NULL);

chk(ret, "clEnqueueNDRange");

clFinish(command_queue);

更新:

我遵循pmdj的建议,对内核代码进行了更改。现在看起来是这样:

代码语言:javascript
复制
__kernel void YCbCr_to_ARGB(__global uchar* Y_GPU, __global uchar* Cb_GPU, __global uchar* Cr_GPU, __global uint* RGB_MCU, uint nb_MCU_H, uint nb_MCU_V)
{  
    __global uchar *MCU_Y, *MCU_Cb, *MCU_Cr;
    int R, G, B;
    uint ARGB;
    uchar index, i, j;

unsigned char   iid= get_global_id(0);
unsigned char   jid= get_global_id(1);

    // MCU_Y = &YCbCr_MCU[0];
      // MCU_Cb = &YCbCr_MCU[1];
      // MCU_Cr = &YCbCr_MCU[2];

      MCU_Y= Y_GPU;
      MCU_Cb= Cb_GPU;
      MCU_Cr= Cr_GPU;

    if (iid <= (8 * nb_MCU_V) && jid <= (8 * nb_MCU_H))
    {

            index = iid * (8 * nb_MCU_H)  + jid;
            R = (MCU_Cr[index] - 128) * 1.402f + MCU_Y[index];
            B = (MCU_Cb[index] - 128) * 1.7772f + MCU_Y[index];
            G = MCU_Y[index] - (MCU_Cb[index] - 128) * 0.34414f -
                (MCU_Cr[index] - 128) * 0.71414f;


            /* Saturate */
            if (R > 255)
                R = 255;
            if (R < 0)
                R = 0;
            if (G > 255)
                G = 255;
            if (G < 0)
                G = 0;
            if (B > 255)
                B = 255;
            if (B < 0)
                B = 0;
            ARGB = ((R & 0xFF) << 16) | ((G & 0xFF) << 8) | (B & 0xFF);

        RGB_MCU[(iid * (8 * nb_MCU_H) + jid)] = ARGB;

        }
}

在主机代码中,我为4个新变量创建并分配了内存:

代码语言:javascript
复制
Y_ForGPU= (cl_uchar *)malloc(MCU_sx * MCU_sy * max_ss_h * max_ss_v);

Cb_ForGPU= (cl_uchar *)malloc(MCU_sx * MCU_sy * max_ss_h * max_ss_v);

Cr_ForGPU= (cl_uchar *)malloc(MCU_sx * MCU_sy * max_ss_h * max_ss_v);

//Now will do it for RGB
RGB_testing= (cl_uint *)malloc (MCU_sx * MCU_sy * max_ss_h * max_ss_v * sizeof(cl_int));

我创建缓冲区的方式如下:

代码语言:javascript
复制
cl_mem for_Y= clCreateBuffer(context, CL_MEM_READ_WRITE| CL_MEM_COPY_HOST_PTR, (MCU_sx * MCU_sy * max_ss_h * max_ss_v), Y_ForGPU, &ret);


cl_mem for_Cb= clCreateBuffer(context, CL_MEM_READ_WRITE| CL_MEM_COPY_HOST_PTR, (MCU_sx * MCU_sy * max_ss_h * max_ss_v), Cb_ForGPU , &ret);

cl_mem for_Cr= clCreateBuffer(context, CL_MEM_READ_WRITE| CL_MEM_COPY_HOST_PTR, (MCU_sx * MCU_sy * max_ss_h * max_ss_v), Cr_ForGPU, &ret);

//rgb_MCU for YCbCrtoARGB
cl_mem RGB_GPU= clCreateBuffer(context, CL_MEM_READ_WRITE, (MCU_sx * MCU_sy * max_ss_h * max_ss_v * sizeof(cl_int)), NULL, &ret);

然后设置内核参数,执行内核,并将计算出来的数据发回主机:

代码语言:javascript
复制
ret = clSetKernelArg(color_kernel, 0, sizeof(cl_mem), &for_Y);
ret |= clSetKernelArg(color_kernel, 1, sizeof(cl_mem), &for_Cb);
ret |= clSetKernelArg(color_kernel, 2, sizeof(cl_mem), &for_Cr);
ret |= clSetKernelArg(color_kernel, 3, sizeof(cl_mem), &RGB_GPU);
ret |= clSetKernelArg(color_kernel, 4, sizeof(cl_uint), &max_ss_h);
ret |= clSetKernelArg(color_kernel, 5, sizeof(cl_uint), &max_ss_v);


const size_t itemColor[2] = {100, 100};

ret = clEnqueueNDRangeKernel(command_queue, color_kernel, 2, NULL, itemColor, NULL, 0, NULL, NULL);
clFinish(command_queue);

//Copy result to the host
ret = clEnqueueReadBuffer(command_queue, RGB_GPU, CL_TRUE, 0, (MCU_sx * MCU_sy * max_ss_h * max_ss_v * sizeof(cl_int)), RGB_testing, 0, NULL, NULL);

然而,现在我的代码只是突然终止。为什么会发生这种事?

更新:

我的代码现在起作用了。这些问题可能是由于指针的不同而产生的。我将Y、Cb、Cr和RGB变量(我创建的)设置为主机代码中的原始变量。

代码语言:javascript
复制
//---Setting color variables equal to array elements----//

Y_ForGPU= YCbCr_MCU[0];
Cb_ForGPU= YCbCr_MCU[1];
Cr_ForGPU= YCbCr_MCU[2];

//----RGB is being assigned value-----//

RGB_testing= RGB_MCU;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-27 10:42:27

我不知道这是否是造成您的问题的唯一原因(可能还有更多的原因我还没有发现),但是您的YCbCr_MCU内核参数中存在类型错配。你不能有指针对指针的参数,这是真的。不过,简单地删除*并不能修复它。

特别是,线

代码语言:javascript
复制
MCU_Cb = &YCbCr_MCU[1];

在内核中,无论YCbCr_MCU指向什么,都要经过1字节,这实际上是指针数组的开始,而不是像素数组的开始。

代码语言:javascript
复制
ret = clSetKernelArg(color_kernel, 0, sizeof(cl_mem), (void *)&colorMCU_GPU);

看起来,YCbCr_MCU应该是一个指向Y、Cb、Cr平面的3个指针的数组,其中包含了源像素。您需要将它们作为3个直接指针传递给您的内核,而不是3个指针的指针。换句话说,将其转换为Y、Cb和Cr参数,并通过主机上的colorMCU_GPU[0]将它们设置为colorMCU_GPU[2]

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45319076

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档