about opencl

Platform:LG G3,Adreno 330


1. 8M3264x2448) memmap方式读入时间24ms,读出时间12ms,时间与内存大小基本成线性关系。使用memmap memcopy(clEnqueueWriteBuffer)方式并无时间差异。

2.使用pingpong的方式,使memory读写与kernel执行同时执行。在clFinish(commandQueue)等待kernel执行时可以进行memory操作.

    cl_context mem_context = 0;
    cl_command_queue mem_commandQueue = 0;
    ...
     cl_mem  memoryObjects2 = clCreateBuffer(mem_context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR , bufferSize, NULL, &errorNumber);
    ...
    t0 = now_ms();
    {
    cl_uchar* luminance = (cl_uchar*)clEnqueueMapBuffer(mem_commandQueue, memoryObjects2, CL_TRUE, CL_MAP_WRITE, 0, bufferSize, 0, NULL, NULL, &errorNumber);

     memcpy(luminance,in,bufferSize);
   
     if (!checkSuccess(clEnqueueUnmapMemObject(mem_commandQueue, memoryObjects2, luminance, 0, NULL, NULL)))
     {
     }
    //     clEnqueueWriteBuffer(mem_commandQueue, memoryObjects2, CL_TRUE, 0, bufferSize,in, 0, NULL, NULL);  //使用 clEnqueueWriteBuffer也是24ms

     LOGI("memory unmap:%f ms",now_ms() - t0 );
    }

    t0 = now_ms();
    /* Wait for completion */
    if (!checkSuccess(clFinish(commandQueue)))
    {
    }
    LOGI("Wait for completion  time:%f ms",now_ms() - t0 );

结果:

12-02 09:39:54.734: I/GAUSS(8133): memory unmap:26.099365 ms
12-02 09:39:54.738: I/GAUSS(8133): Wait for completion time:4.448486 ms
12-02 09:39:54.752: I/GAUSS(8133): memory out time:12.929443 ms


kernel 执行需要29ms,26+4.4接近,说明memmapkernel是同时在运行的。

但是 memoryObjects2 需要单独的 contextcommand_queue .

只有单独的 command_queue,kernel共用context的情况下:

12-02 09:32:13.712: I/GAUSS(5169): memory unmap:57.429443 ms
12-02 09:32:13.713: I/GAUSS(5169): Wait for completion time:0.022217 ms
12-02 09:32:13.726: I/GAUSS(5169): memory out time:11.878174 ms

memmap的实际时间57 = 24+29,等于memmap的时间加上kernel需要的时间,说明是串行执行的。


3.关于第一点memmap memcopy(clEnqueueWriteBuffer)方式的时间更正.看到AMDopencl-optimization-guide中提到opecl为了避免为不会被使用memory object分配device memory,使用了deferred allocation策略,即space在第一次使用时才会分配,所以第一次使用memory object的时间会比较长。

循环多次memmap方式读入8Mimage的结果:

12-04 15:31:52.894: I/GAUSS(30530): memory in time:22.367188 ms
12-04 15:31:52.900: I/GAUSS(30530): queue time:6.125732 ms
12-04 15:31:52.929: I/GAUSS(30530): run time:29.329102 ms
12-04 15:31:52.932: I/GAUSS(30530): memory in time:2.342773 ms
12-04 15:31:52.932: I/GAUSS(30530): queue time:0.333252 ms
12-04 15:31:52.962: I/GAUSS(30530): run time:29.895020 ms
12-04 15:31:52.967: I/GAUSS(30530): memory in time:5.199463 ms
12-04 15:31:52.968: I/GAUSS(30530): queue time:0.180176 ms
12-04 15:31:52.997: I/GAUSS(30530): run time:29.568359 ms
12-04 15:31:52.999: I/GAUSS(30530): memory in time:1.941162 ms
12-04 15:31:52.999: I/GAUSS(30530): queue time:0.183594 ms
12-04 15:31:53.029: I/GAUSS(30530): run time:29.852295 ms


循环多次memcopy(clEnqueueWriteBuffer)的方式:

12-04 15:37:34.747: I/GAUSS(32217): memory in time:22.356689 ms
12-04 15:37:34.752: I/GAUSS(32217): queue time:4.679199 ms
12-04 15:37:34.782: I/GAUSS(32217): run time:30.098877 ms
12-04 15:37:34.784: I/GAUSS(32217): memory in time:1.853516 ms
12-04 15:37:34.784: I/GAUSS(32217): queue time:0.326172 ms
12-04 15:37:34.814: I/GAUSS(32217): run time:29.864990 ms
12-04 15:37:34.816: I/GAUSS(32217): memory in time:1.709473 ms
12-04 15:37:34.816: I/GAUSS(32217): queue time:0.188965 ms
12-04 15:37:34.846: I/GAUSS(32217): run time:29.705322 ms

可以看出memmap clEnqueueWriteBuffer 方式还是无差别,因为deferred allocation的策略,memory access,提交任务队列和kernel 执行需要一到两个周期达到最佳性能.


4.相关术语,wavefront,work-group

一个device有若干个compute uint,一个compute unit有若干个流核心(stream core,AMD上叫SIMD,NvidaStream Processor),每个流核心含有若干个Processing Element.

一个work-item在一个PE上执行,一个计算单元上的一组工作项以锁步(lock-step,相同的指令不同的数据)的方式执行,称为wavefrontwavefront是硬件调度的基本单元。

一个工作组由一个或多个wavefront组成,在一个工作组内的wavefront切换就可以隐藏访存延迟。例如:访问global memory400 cycles,距离下一次memory access20 cycles的计算指令,那么就需要20wavefront来隐藏400 cycles的延迟。


 

posted @ 2015-12-11 15:53  mlj318  阅读(418)  评论(0编辑  收藏  举报