用OpenCL實現HEVC中ME模塊的測試數據分析

 

 

使用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 內存的話, 會慢一半!

下面貼出部分代碼供參考:

 

#define SearchRange 16
#define Edge_SIZE_T 48
//32x32 version of kernel
__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)
{
	int searchrange = SearchRange;
	int edeg = Edge_SIZE_T;
	int width = get_global_size(0);
	int height = get_global_size(1);
	int block_w = get_local_size(0);
	int block_h = get_local_size(1);
	int local_x = get_local_id(0);
	int local_y = get_local_id(1);
	int lcu_x = get_group_id(0);
	int lcu_y = get_group_id(1);
	int stride = width + 2 * edeg;
	int lcu_adr_offset = edeg * stride + edeg;
	int local_refBuf_stride = block_w + 2 * searchrange;
			
	//LCU blcok adr
	lcu_adr_offset += lcu_y * stride * block_h + lcu_x * block_w;
	int ref_lcu_adr_offset = lcu_adr_offset - searchrange - searchrange * stride;
	//thread adr
	int global_thread_adr_offset = local_y * stride + local_x;
	int thread_adr_offset  = local_y * local_refBuf_stride + local_x;

	local_curBuf[local_y * block_w + local_x]										= p_cur[lcu_adr_offset + global_thread_adr_offset];

	local_refBuf[thread_adr_offset]												= p_ref[ref_lcu_adr_offset + global_thread_adr_offset ];
	local_refBuf[thread_adr_offset + block_w]									= p_ref[ref_lcu_adr_offset + global_thread_adr_offset + block_w];
	local_refBuf[thread_adr_offset + local_refBuf_stride * block_h]				= p_ref[ref_lcu_adr_offset + global_thread_adr_offset + stride * block_h];
	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];
 barrier(CLK_LOCAL_MEM_FENCE);
  {
   int i;
  int uiSum = 0;
  for( int i = 0; i < block_h; i++ )
  {
計算sad
}
{
  比較最小SAD 保存bestcost
}
 if((local_y ==0) && (local_x == 0))
 {
  int best_sad  = mv_cost[local_y*2*SearchRange*3 + local_x*3 + 2];
  int best_mvx  = mv_cost[local_y*2*SearchRange*3 + local_x*3 + 0];
  int best_mvy  = mv_cost[local_y*2*SearchRange*3 + local_x*3 + 1];
  outputBuf[(lcu_y * get_num_groups(0) + lcu_x)*3 + 0] = best_mvx;
  outputBuf[(lcu_y * get_num_groups(0) + lcu_x)*3 + 1] = best_mvy;
  outputBuf[(lcu_y * get_num_groups(0) + lcu_x)*3 + 2] = best_sad; 
  //printf("\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = %d, y = %d, sad = %d",best_mvx, best_mvy, best_sad);
 }
 


 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章