双三次插值是一种常见的插值方法,但我在 OpenCL 上找不到任何可行的实现。我决定自己在 OpenCL 上编写双三次插值,但是......
我对内核程序有一些问题。
当我运行内核执行时,程序失败并出现错误 CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST。没有关于错误原因的任何其他信息。我正在使用 google 代码的 javacl 绑定形式:http ://code.google.com/p/javacl,Ubuntu linux 10.10 上的 AMD Accelerated Parallel Processing SDK 2.3,硬件 AMD Radeon 5xxxHD
我还没有在 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”编译并运行demo。
问候,伊戈尔