我试图在CUDA中为一维数组实现HAAR小波变换。
算法
我在输入数组中有8个索引
在这种情况下,我将有4个线程分别为0、2、4、6,并且我打算使用每个线程处理输入中的两个索引。
我计算avg.EG:如果我的线程ID为'0'-那么avg为(input [0] + input [1])/ 2,然后同时获得要输入的差值-[0]-其余线程的平均数等等。
现在重要的是输出的放置。我为输出创建了一个单独的thread_id,因为使用索引0、2、4、6在将输出放置在正确的索引中时遇到了困难。
我的平均值应该放在前4个索引中,即输出的0、1、2、3,而o_thread_id应该是0、1、2、3。
类似地,为了将差值放在4,5,6,7,我将0、1、2、3递增为'4',如代码所示
问题
我的输出全为零!不管我改变什么,我都会明白的。
码
__global__ void cal_haar(int input[],float output [],int i_widthstep,int o_widthstep,int o_width,int o_height)
{
int x_index=blockIdx.x*blockDim.x+threadIdx.x;
int y_index=blockIdx.y*blockDim.y+threadIdx.y;
if(x_index>=o_width/2 || y_index>=o_height/2) return;
int i_thread_id=y_index*i_widthstep+(2*x_index);
int o_thread_id=y_index*o_widthstep+x_index;
float avg=(input[i_thread_id]+input[i_thread_id+1])/2;
float diff=input[i_thread_id]-avg;
output[o_thread_id]=avg;
output[o_thread_id+4]=diff;
}
void haar(int input[],float output [],int i_widthstep,int o_widthstep,int o_width,int o_height)
{
int * d_input;
float * d_output;
cudaMalloc(&d_input,i_widthstep*o_height);
cudaMalloc(&d_output,o_widthstep*o_height);
cudaMemcpy(d_input,input,i_widthstep*o_height,cudaMemcpyHostToDevice);
dim3 blocksize(16,16);
dim3 gridsize;
gridsize.x=(o_width+blocksize.x-1)/blocksize.x;
gridsize.y=(o_height+blocksize.y-1)/blocksize.y;
cal_haar<<<gridsize,blocksize>>>(d_input,d_output,i_widthstep,o_widthstep,o_width,o_height);
cudaMemcpy(output,d_output,o_widthstep*o_height,cudaMemcpyDeviceToHost);
cudaFree(d_input);
cudaFree(d_output);
}
以下是我的主要功能:
void main()
{
int in_arr[8]={1,2,3,4,5,6,7,8};
float out_arr[8];
int i_widthstep=8*sizeof(int);
int o_widthstep=8*sizeof(float);
haar(in_arr,out_arr,i_widthstep,o_widthstep,8,1);
for(int c=0;c<=7;c++)
{cout<<out_arr[c]<<endl;}
cvWaitKey();
}
您能告诉我哪里出问题了吗?它的输出为零?
谢谢。
最佳答案
您的代码存在以下问题:
if(x_index>=o_width/2 || y_index>=o_height/2) return;
给定
o_height = 1
,我们有o_height/2 = 0
(o_height
是int
,因此这里我们有整数取整并向下取整),因此没有线程执行任何操作。要实现所需的功能,您可以在此处执行浮点运算,也可以使用(o_height+1)/2
和(o_width+1)/2
:它将使用“算术”舍入进行除法(您将具有( x_index >= (8+1)/2 /*= 4*/ && y_index >= (1+1)/2 /*= 1*/ )
)此外,当您在Y维度上有多个线程时,寻址会出现问题,因为这样
i_thread_id
和o_thread_id
计算将是错误的(_withstep
是字节大小,但您将其用作数组索引) 。