图像处理的并行模式选择问题?

图像处理的并行模式选择问题?

问题约束:a.输入的2D图像大小不是预先设定的
b.运行CUDA程序的显卡不是固定的
c.算法只涉及点模式或者周围小区域内的 也就是可以看作是数据并行模式

大多数网上的CUDA例子(包括SDK里面的例子)通常都是以下这种模式:

    //一个简单地2维int数组的填充例子 
   //设备上的实现 
   __global__ static void fill2D_CUDA(int* pDst,int pitch,int width,int height,int fillValue){ 
const int x = blockIdx.x*blockDim.x + threadIdx.x; 
   const int y = blockIdx.y*blockDim.y + threadIdx.y; 
   if ((x <width)&&(y <height)){ 
   int* pdata=(unsigned int*)((char*)pDst+pitch*y+sizeof(int)*x); 
   *pdata=fillValue; 
   }        
   } 


   //从CPU端调用 
   const int THREAD_NUM_X=16; //这里也可以改为32 
   const int THREAD_NUM_Y=16; 
   const int BLOCK_NUM_X=(width+THREAD_NUM_X-1)/THREAD_NUM_X; 
   const int BLOCK_NUM_Y=(height+THREAD_NUM_Y-1)/THREAD_NUM_Y; 
   fill2D_CUDA < < < dim3(BLOCK_NUM_X,BLOCK_NUM_Y,1), dim3(THREAD_NUM_X,THREAD_NUM_Y,1), 0 >>>(pDst,pitch,width,height,fillValue); 


这种并行模式代码实现很简单,但潜藏的缺陷很多

a.由于每个点都启动了一个线程 所以每个线程做的事情可能都很少 线程本身的开销很可能大于其处理任务的开销
b.由于能够启动的线程数目有限制 所以能够一次处理的图像大小也就受限制
理论线程数 (2^16-1)512,开平方为5792 不到60006000 这个限制不算太大
但很可能实际上能够启动的线程将远远低于理论值,线程消耗比一个int值可大多了
也就是能够获得不错并行性能收益的图片大小将远小于理论值,显卡硬件性能越差,这个值越小
c.从内存访问模式来看 将一个block中的多个thread拆成了x,y两个方向 图像大小稍大就可能会产生严重地内存访问性能;
y方向的跨度增大了将同时访问的内存路数(增大缓冲区压力), x方向的跨度小使内存延时(上百个周期)得不到有效屏蔽;

通过以上分析 这种并行方案并不是万能的通用模式
大家有没有更好地并行模式 一起来讨论讨论