zoukankan      html  css  js  c++  java
  • OpenCL 学习step by step (9) 灰度图Histogram计算(3)

         在OpenCL编程中,特别是基于GPU的opencl的编程,提高程序性能最主要的方法就是想法提高memory的利用率,它主要包括两方面的优化:一方面是提高global memory的合并读写效率,另一方面就是减少local memory的bank conflict。下面我们分析一下教程7中的代码,看看它的memory利用率如何?

        首先我们用amd的opencl profiler分析一下程序性能[最新的app sdk改用CodeXL进行性能分析]。

         下面我们来分析我们的kernel代码中memory操作:

         首先是shared memory的的初始化,我们知道shared memory是local memory,被一个workgroup中的所有thread,或者说work item共享。在amd硬件系统中,local memory是LDS,它通常是为32k或更高,分为32个bank,dword字节地址,每个bank 512个item,我们可以通过函数得到自己系统中的local memory数量:

    cl_ulong DeviceLocalMemSize;
    clGetDeviceInfo(device,
        CL_DEVICE_LOCAL_MEM_SIZE,
        sizeof(cl_ulong),
        &DeviceLocalMemSize,
        NULL);

    LDS的示意图如下,对于每个bank,同时只能有一个读写请求,如果两个thread都读写bank1,那个必须串行访问,这就称作bank conflict。

    image

    kernel初始化local memory的代码如下:

    //初始化共享内存
    for(int i = 0; i < BIN_SIZE; ++i)
        sharedArray[localId * BIN_SIZE + i] = 0;

         在同一时间,thread0访问地址0(bank1),thread1,访问地址256,也在bank1,…,这样就有很多bank conflit,降低程序的性能。从profiler里面可以看到,lds bank conflit为13.98,很高的比例,所以此时同时运行的thread就比较少,只有总wave(每个wave 64个thread)的12%(我曾经默认lds内存分配是0,这样我们就省去了这些代码,但是实际上分配内存是一些随机的值…)。

    image

    image

    第二段memory操作的代码为:

        //计算thread直方图
        for(int i = 0; i < BIN_SIZE; ++i)
        {
            uint value = (uint)data[groupId * groupSize * BIN_SIZE + i * groupSize + localId];
            sharedArray[localId * BIN_SIZE + value]++;
        }

    其中有lds的操作,也有global memory的操作,对于全局memory的访问,在同一时刻,thread0访问i=0的memory

    ,thread1访问相邻的memory单元…,这是对于global memory的访问会采用合并读写的方式(coalencing),就是一个memory请求返回16个dword,也就是一个请求满足16个thread,提高memory利用率。此时对lds的写是随机的,根据value的值决定,不能控制…

    image

    最后一段memory读写的代码:

    //合并workgroup中所有线程的直方图,产生workgroup直方图
    for(int i = 0; i < BIN_SIZE / groupSize; ++i)
    {
         uint binCount = 0;
         for(int j = 0; j < groupSize; ++j)
             binCount += sharedArray[j * BIN_SIZE + i * groupSize + localId];
            
         binResult[groupId * BIN_SIZE + i * groupSize + localId] = binCount;
    }

    其中lds的读写如下图,此时每个线程访问不同的bank,因为amd lds访问就是以32为单位,所以实际上,这段代码不会有bank conflit。

    image

  • 相关阅读:
    (6)STM32使用HAL库实现modbus的简单通讯
    (4)STM32使用HAL库实现串口通讯——理论讲解
    (3)STM32使用HAL库操作外部中断——实战操作
    (2)STM32使用HAL库操作外部中断——理论讲解
    对图片进行压缩、水印、伸缩变换、透明处理、格式转换操作1
    文件压缩、解压工具类。文件压缩格式为zip
    Bean与Map的转换 和 Map与Bean的转换
    正则 身份证的验证
    金钱处理工具类 人民币转换为大写
    正则表达式工具类,验证数据是否符合规范
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/2742078.html
Copyright © 2011-2022 走看看