现在的位置: 首页 > 综合 > 正文

用OpenCL实现HEVC中ME模块的测试数据分析

2013年06月29日 ⁄ 综合 ⁄ 共 3131字 ⁄ 字号 评论关闭

使用opencl来实现编码算法中运动搜索模块!

下面测试数据时在GTX570上的测试结果:

LCU为32x32, 100帧720P, CPU上纯C算法使用搜索时间是67s, GPU上是0.915s

LCU为16x16, CPU 是76.8s,   GPU上是1.6s

LCU为8x8, CPU 是82.5s,   GPU上是4.2s

 

 

同样的程序, CPU改为SSE实现, GPU做一个小的改动, 使用缩减算法! 结果如下:

 

 

 

从上面数据可以看出, sse 比C语言快5倍左右, 新的GPU kenel快了20%左右, 其中LCU为8x8的快了好几倍!

 

综合看来

OPENCL实现 比C语言实现接近100倍的级别, 比SSE快了接近20倍左右!

另外提一句, 如果OPENCL不适用__local 内存的话, 会慢一半!

下面贴出部分代码供参考:

 

  1. #define SearchRange 16  
  2. #define Edge_SIZE_T 48  
  3. //32x32 version of kernel  
  4. __kernel void opencl_me_32x32(const __global short* p_ref, __global short* p_cur, __global int* outputBuf, __local int* local_refBuf, __local int* local_curBuf, __local int* mv_cost)  
  5. {  
  6.     int searchrange = SearchRange;  
  7.     int edeg = Edge_SIZE_T;  
  8.     int width = get_global_size(0);  
  9.     int height = get_global_size(1);  
  10.     int block_w = get_local_size(0);  
  11.     int block_h = get_local_size(1);  
  12.     int local_x = get_local_id(0);  
  13.     int local_y = get_local_id(1);  
  14.     int lcu_x = get_group_id(0);  
  15.     int lcu_y = get_group_id(1);  
  16.     int stride = width + 2 * edeg;  
  17.     int lcu_adr_offset = edeg * stride + edeg;  
  18.     int local_refBuf_stride = block_w + 2 * searchrange;  
  19.               
  20.     //LCU blcok adr  
  21.     lcu_adr_offset += lcu_y * stride * block_h + lcu_x * block_w;  
  22.     int ref_lcu_adr_offset = lcu_adr_offset - searchrange - searchrange * stride;  
  23.     //thread adr  
  24.     int global_thread_adr_offset = local_y * stride + local_x;  
  25.     int thread_adr_offset  = local_y * local_refBuf_stride + local_x;  
  26.   
  27.     local_curBuf[local_y * block_w + local_x]                                       = p_cur[lcu_adr_offset + global_thread_adr_offset];  
  28.   
  29.     local_refBuf[thread_adr_offset]                                             = p_ref[ref_lcu_adr_offset + global_thread_adr_offset ];  
  30.     local_refBuf[thread_adr_offset + block_w]                                   = p_ref[ref_lcu_adr_offset + global_thread_adr_offset + block_w];  
  31.     local_refBuf[thread_adr_offset + local_refBuf_stride * block_h]             = p_ref[ref_lcu_adr_offset + global_thread_adr_offset + stride * block_h];  
  32.     local_refBuf[thread_adr_offset + local_refBuf_stride * block_h + block_w]   = p_ref[ref_lcu_adr_offset + global_thread_adr_offset + stride * block_h + block_w];  
  1.  barrier(CLK_LOCAL_MEM_FENCE);  
  2.   {  
  3.    int i;  
  4.   int uiSum = 0;  
  5.   for( int i = 0; i < block_h; i++ )  
  6.   {  
  1. 计算sad  
  1. }  
  1. {  
  1. 比较最小SAD 保存bestcost  
  1. }  
  1.  if((local_y ==0) && (local_x == 0))  
  2.  {  
  3.   int best_sad  = mv_cost[local_y*2*SearchRange*3 + local_x*3 + 2];  
  4.   int best_mvx  = mv_cost[local_y*2*SearchRange*3 + local_x*3 + 0];  
  5.   int best_mvy  = mv_cost[local_y*2*SearchRange*3 + local_x*3 + 1];  
  6.   outputBuf[(lcu_y * get_num_groups(0) + lcu_x)*3 + 0] = best_mvx;  
  7.   outputBuf[(lcu_y * get_num_groups(0) + lcu_x)*3 + 1] = best_mvy;  
  8.   outputBuf[(lcu_y * get_num_groups(0) + lcu_x)*3 + 2] = best_sad;   
  9.   //printf("\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = %d, y = %d, sad = %d",best_mvx, best_mvy, best_sad);  
  10.  }  
  1.    

抱歉!评论已关闭.