Сбой ядра бикубической интерполяции OpenCL с ошибкой CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST

Бикубическая интерполяция является одним из распространенных методов интерполяции, но я не могу найти ни одной работающей реализации на OpenCL. Было решено самому написать бикубическую интерполяцию на OpenCL, но...

У меня проблема с программой ядра.

Когда я запускаю выполнение ядра, программа завершается с ошибкой CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST. Никакой другой информации о причине ошибки нет. Я использую код Google для привязки javacl: http://code.google.com/p/javacl, AMD Accelerated Parallel Processing SDK 2.3 на Ubuntu linux 10.10, аппаратное обеспечение AMD Radeon 5xxxHD

У меня нет отладчика opencl на ubuntu для AMD APP SDK (

Если я раскомментирую float4 val=read_imagef(signal, sampler, (float2)(x+iX,y+iY)); и комментарий вычисления бикубической интерполяции "float4 val=..." все работает без ошибок (но с использованием билинейной интерполяции). Я думаю, что эта ошибка из-за недопустимого доступа к памяти или переполнения памяти регистра.

const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP_TO_EDGE;
const float CATMULL_ROM[16]={-0.5F,1.5F,-1.5F,0.5F,1.0F,-2.5F,2.0F,-0.5F,-0.5F,0.0F,0.5F,0.0F,0.0F,1.0F,0.0F,0.0F};
__kernel void bicubicUpscale(int scale,read_only image2d_t signal, write_only image2d_t upscale) {

int x = get_global_id(0)-2, y = get_global_id(1)-2;

float C[16];
float T[16];


for (int i = 0; i < 16; i++)
{
    C[i]=0.0F;
    T[i]=0.0F;
}

for (int i = 0; i < 4; i++)
    for (int j = 0; j < 4; j++)
        for (int k = 0; k < 4; k++)
        {
            T[4*i+j] += read_imagef(signal, sampler, (int2)(x+k,y+i)).x * CATMULL_ROM[4*j+k];
        }
for (int i = 0; i < 4; i++)
    for (int j = 0; j < 4; j++)
        for (int k = 0; k < 4; k++)
        {
            C[4*i+j] += CATMULL_ROM[4*i+k] * T[4*k+j];
        }

for (int i = 0; i < scale; i++)
{
    for (int j = 0; j < scale; j++)
    {
        float iX=(float)j/(float) scale;
        float iY=(float)i/(float) scale;
        //float4 val=read_imagef(signal, sampler, (float2)(x+iX,y+iY));
        float val= iX * (iX * (iX * (iY * (iY * (iY * C[0] + C[1]) + C[2]) + C[3])
        + (iY * (iY * (iY * C[4] + C[5]) + C[6]) + C[7]))
        + (iY * (iY * (iY * C[8] + C[9]) + C[10]) + C[11]))
        + (iY * (iY * (iY * C[12] + C[13]) + C[14]) + C[15]);
        write_imagef(upscale, (int2)(x*scale+j, y*scale+i), val);
    }
}
}

Я переписываю эту программу для использования локальной памяти, но она все еще работает неправильно

const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP_TO_EDGE;
const float CATMULL_ROM[]={-0.5F,1.5F,-1.5F,0.5F,1.0F,-2.5F,2.0F,-0.5F,-0.5F,0.0F,0.5F,0.0F,0.0F,1.0F,0.0F,0.0F};
__kernel void bicubicUpscale(local float* sharedBuffer,int scale,read_only image2d_t signal, write_only image2d_t upscale) {
int x = get_global_id(0)-2, y = get_global_id(1)-2;
//int locX=get_local_id(0);

int offsetT = (y+2)*512+(x+2)*32+16;
int offsetC = (y+2)*512+(x+2)*32;

global float* C=&sharedBuffer[offsetT];
global float* T=&sharedBuffer[offsetT];

for (int i = 0; i < 32; i++){
    sharedBuffer[offsetC+ i]=0.0F;
}

for (int i = 0; i < 4; i++)
    for (int j = 0; j < 4; j++)
        for (int k = 0; k < 4; k++){
            //T[4*i+j] = mad(read_imagef(signal, sampler, (int2)(x+k,y+i)).x,CATMULL_ROM[4*j+k],T[4*i+j]);
            T[i+j] += read_imagef(signal, sampler, (int2)(x+k,y+i)).x * CATMULL_ROM[4*j+k];
        }
for (int i = 0; i < 4; i++)
    for (int j = 0; j < 4; j++)
        for (int k = 0; k < 4; k++){
            //C[4*i+j] = mad(CATMULL_ROM[4*i+k],T[4*k+j],C[4*i+j]);
            sharedBuffer[offsetC +4*i+j] += CATMULL_ROM[4*i+k] * sharedBuffer[offsetT + 4*k+j];
        }


barrier (CLK_GLOBAL_MEM_FENCE);


for (int i = 0; i < scale; i++)
    for (int j = 0; j < scale; j++)
        {
            float iX=(float)j/(float) scale;
            float iY=(float)i/(float) scale;
            float4 val= iX * (iX * (iX * (iY * (iY * (iY * C[0] + C[1]) + C[2]) + C[3])
            + (iY * (iY * (iY * C[4] + C[5]) + C[6]) + C[7]))
            + (iY * (iY * (iY * C[8] + C[9]) + C[10]) + C[11]))
            + (iY * (iY * (iY * C[12] + C[13]) + C[14]) + C[15]);
            write_imagef(upscale, (int2)(x*scale+j, y*scale+i), val);
        }
}

Знаете ли вы какое-либо решение этой проблемы.

Исходники Java + сборка maven2. Используйте команду "mvn clean compile exec:java" для компиляции и запуска демо.

С уважением, Игорь


person Igor Suhorukov    schedule 20.02.2011    source источник
comment
Вы должны опубликовать исходный код на стороне хоста, так как именно здесь возникает ошибка. Точный вызов, который возвращает эту ошибку, также был бы полезен.   -  person Dr. Snoopy    schedule 21.02.2011
comment
Спасибо за помощь. Вы можете загрузить мой демонстрационный проект maven2 для бикубической интерполяции и выполнить его из командной строки mvn установить исполняемый файл: java   -  person Igor Suhorukov    schedule 22.02.2011


Ответы (1)


Я исправляю это! Это ядро ​​не является оптимальным с точки зрения производительности, но функционально корректно.

Пожалуйста, используйте такие параметры для enqueueNDRange:

            kernelBicubic.getKernel().setArgs(scaleFactor, inImage, imageOut);
            lastEvent=kernelBicubic.getKernel().enqueueNDRange(queue,
                    new int[]{(int) inImage.getWidth()+1,(int) inImage.getHeight()+1},lastEvent);

Код ядра:

const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP_TO_EDGE;

const float CATMULL_ROM[16]={-0.5F, 1.5F,-1.5F, 0.5F, 1.0F,-2.5F, 2.0F,-0.5F,-0.5F, 0.0F, 0.5F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F};

inlie float calcT(image2d_t signal,int x,int y,int i,int j){
      return read_imagef(signal, sampler, (int2)(x  ,y+i)).x * CATMULL_ROM[4*j]
            +read_imagef(signal, sampler, (int2)(x+1,y+i)).x * CATMULL_ROM[4*j+1]
            +read_imagef(signal, sampler, (int2)(x+2,y+i)).x * CATMULL_ROM[4*j+2]
            +read_imagef(signal, sampler, (int2)(x+3,y+i)).x * CATMULL_ROM[4*j+3];
}

inline float C(image2d_t signal,int x,int y,int i,int j){
      return CATMULL_ROM[4*i  ] * calcT(signal,x,y,0,j)
            +CATMULL_ROM[4*i+1] * calcT(signal,x,y,1,j)
            +CATMULL_ROM[4*i+2] * calcT(signal,x,y,2,j)
            +CATMULL_ROM[4*i+3] * calcT(signal,x,y,3,j);
}


__kernel void bicubicUpscale(int scale,read_only image2d_t signal, write_only image2d_t upscale) {

int x = get_global_id(0)-2, y = get_global_id(1)-2;

float C0 =C(signal,x,y,0,0);
float C1 =C(signal,x,y,0,1);
float C2 =C(signal,x,y,0,2);
float C3 =C(signal,x,y,0,3);
float C4 =C(signal,x,y,1,0);
float C5 =C(signal,x,y,1,1);
float C6 =C(signal,x,y,1,2);
float C7 =C(signal,x,y,1,3);
float C8 =C(signal,x,y,2,0);
float C9 =C(signal,x,y,2,1);
float C10=C(signal,x,y,2,2);
float C11=C(signal,x,y,2,3);
float C12=C(signal,x,y,3,0);
float C13=C(signal,x,y,3,1);
float C14=C(signal,x,y,3,2);
float C15=C(signal,x,y,3,3);

float xOff=scale*1.5F + x*scale;
float yOff=scale*1.5F + y*scale;

 for (int i = 0; i < scale; i++)
 {
    for (int j = 0; j < scale; j++)
    {
        float iY=(float)j/(float) scale;
        float iX=(float)i/(float) scale;
        float val= iX * (iX * (iX * (iY * (iY * (iY * C0 + C1) + C2) + C3)
        + (iY * (iY * (iY * C4 + C5) + C6) + C7))
        + (iY * (iY * (iY * C8 + C9) + C10) + C11))
        + (iY * (iY * (iY * C12 + C13) + C14) + C15);
        write_imagef(upscale, (int2)(xOff+j, yOff+i), val);
    }
 }
}
person Igor Suhorukov    schedule 31.03.2011