课 程 设 计
题目: CUDA加速和优化直方图均衡化
姓 名: nch
学 号: SA19219093
学 院: 微电子学院
学校:中国科学技术大学
专 业: 集成电路
指导教师: 谭立湘
2019 年 12 月 15 日
CUDA加速和优化直方图均衡化
项目简介
直方图均衡化(Histogram Equalization) 又称直方图平坦化,实质上是对图像进行非线性拉伸,重新分配图像象元值,使一定灰度范围内象元值的数量大致相等。直方图均衡化的只要目的是为了图像的增强。在现实的拍摄过程中,比如说视频监控领域,由于其图像的灰度分布集中在较窄的范围内,这就导致了图像的细节不够清晰。为什么不清晰呢,因为灰度分布较窄时,在计算对比度的时候,对比度就很小,所以就不清晰。为了使得图像变得清晰,那么就需要使得灰度值的差别变大,为了使得灰度值的差别变大,就意味着灰度分布就变的较宽,使得灰度值分布变得均匀,在某个灰度级区间内,像素的个数分布大致相同,这样才能使得图像的对比度增强,细节变得清晰可见。直方图均衡化就是对图像进行非线性拉伸,使得变换后的图像直方图分布均匀。
基于 GPU 课程学习的基础上,采用 CUDA 编程对直方图均衡化加速和优化,利用 GPU 的高度并发性能,提高对图片处理的速度。设计中实现了直方图灰度的统计,灰度占比的计算,直方图概率累积,灰度映射,并且在 GPU 实现和 CPU 实现进行了对比实验。
关键词:CUDA,直方图均衡化,共享内存,原子操作
2
目录
1.CUDA简介… 4
1.1 CUDA编程................................................................................................................. 4
1.1.1 CUDA的执行模型… 4
1.2.1 常用函数及用法........................................................................................... 4
1.2 软件配置.................................................................................................................... 5
1.3 硬件配置.................................................................................................................... 5
-
基础知识… 6
2.1 共享内存… 6
2.2 原子操作---------------------------------------------------------------------------------------------- 6
2.3 规约操作… 6
-
CPU源程序… 8
3.1 直方图灰度的统计… 8
3.2 灰度图占比的计算… 8
3.3 直方图概率的累积… 9
3.4 灰度的映射… 9
3.5 实验结果测试… 10
-
GPU加速优化… 11
4.1 直方图灰度统计的优化… 11
4.2 灰度占比的优化… 11
4.3 直方图概率累积的优化… 12
4.4 灰度映射的优化… 13
-
对比分析… 14
-
总结… 15
3
1.CUDA简介
1.1CUDA 编程
1.1.1 CUDA 的执行模型
在 CUDA
的架构下,一个程序分为两个部份:host
端和
device 端。Host 端是指在 CPU 上执行的部份,而 device 端则是在显示芯片上执行的部份。Device
端的程序又称为 kernel。通常 host 端程序会将数据准备好后,复制到显卡的内
存中,再由显示芯片执行 device 端程序,完成后再由 host 端程序将结果从显卡
的内存中取回。一个完整的 CUDA 程序是由一系列的设备端 kernel 核函数并行
步骤和主机端串行处理步骤共同组成的。在这个模型中,CPU 与 GPU 协同工作,
CPU
负责进行逻辑性强的事物处理和串行计算,GPU
则专注于执行高度线程化
的并形处理任务。
Kernel
不是一个完整的程序,而只是其中的一个关键并行计算步骤。Kernel
以一个网格(Grid)的形式,每个网格由若干个线程块(block)组成,每一个线
程块又由若干个线程(thread)组成。
1.1.2 常用函数及用法
(1)核函数的声明与执行
要写在显示芯片上执行的程序。在 CUDA 中,在函数前面加上__global__表
示这个函式是要在显示芯片上执行的。在显示芯片上执行的程序有一些限制,首
先最明显的一个限制,不能有传回值,一般把计算结构返回值写在函数的指针类
型参数中。
在 CUDA 中,要执行一个核函数,可以使用语法:
函数名称<<<block
数目,
thread 数目, shared memory 大小>>>(参数…);
(2)全局内存的使用
GPU 的全局内存之所以是全局内存,主要是因为 GPU 与 CPU 都可以对它进
行写操作,任何设备都可以通过 PCI-E 总线对其进行访问。在多 GPU 系统GPU 之间可以不通过 CPU 直接将数据从一块 GPU 卡传输到另一块 GPU 卡上。使用 cudaMalloc 函数开辟一块全局内存空间。使用 cudaMemcpy
函数可以把 CPU 上的数据传输到 GPU 的全局内存上或者相反方向。
4
1.2软件配置
在win10
系统上完成 CUDA8.0 的安装:
在win10
系统上安装opencv3.4.0
在win10
系统上安装 Visual Studio 2015。
1.3 硬件配置
处理器:Intel®
Core™ i5-8500U CPU @ 3.00GHz 3.00GHz,RAM: 8.00GB
显卡:Intel® HD
Graphics Family
NVIDIA
GeForce GT 730
5
2.基础知识
2.1 共享内存
ShareMemory(共享内存) 是一个 block 中所有thread 都能使用的共享内存,存取的速度相当快,存取
shared memory 的速度和存取寄存器相同,不需要担心 latency
的问题。原理上来说,共享内存是GPU上可受用户控制的一级缓存。在一个SM中,存在着若干cuda core + DP(双精度计算单元) + SFU(特殊函数计算单元)+共享内存+常量内存+纹理内存。因而共享内存的使用时性能提高的一个重要的因素。但是注意到,将数据拷贝到共享内存中也消耗了部分时间。因而,共享内存仅仅适合存在着数据的重复利用,全局的内存合并或者是线程之间有共享数据的时候,否则直接使用全局内存会更好一些。
2.2原子操作
原子操作 是指对全局和共享内存中的32位或者64位数据进行 “读取-修改-覆写”这一操作。原子操作可以看作是一种最小单位的执行过程。
在其执行过程中,不允许其他并行线程对该变量进行读取和写入的操作。 如果发生竞争,则其他线程必须等待。原子操作只支持某些运算(加、减、最小值、异或运算等,不支持求余和求幂等)和数据类型(整型),但是需要注意的是,原子操作的运行顺序不定,如果安排不当的话,会使速度变慢。
2.3规约操作
规约是一类并行算法,对传入的N个数据,使用一个二元的符合结合律的操作符⊕,生成1个结果。这类操作包括取最小、取最大、求和、平方和、逻辑与/或、向量点积。规约也是其他高级算法中重要的基础算法。除非操作符⊕的求解代价极高,否则规约倾向于带宽受限型任务(bandwidthbound)。本文将介绍几种规约算法的实现,从两遍规约、block的线程数必须为2的幂,一步一步优化到单遍规约、任意线程数的规约实现,还将讨论讨论基于C++模板的优化。
6
7
3.CPU源程序
3.1 直方图灰度的统计
我们要处理的图像是灰度图像,如果是彩色的,需要先转化成灰度图像,然
后确定图像的灰度级有多大,一般就是8位的图像,灰度级为0-255。利用opencv
加载图像并且转换成灰度图。
对灰度图进行直方图的统计。
3.2 灰度图占比的计算
8
3.3 直方图概率的累积
3.4 灰度的映射
9
3.5 实验结果测试
输入原图:
直方图均衡化的图:
10
4.GPU 加速优化
4.1 直方图灰度的统计的优化
开辟一段共享内存,数据在共享内存的读写速度大于在全局内存的读写速度。同时,保证输出结果的正确性,使用原子操作。开辟的线程数为16×16.
4.2 灰度图占比的计算的优化
在一个block中,开辟256个线程,并行计算得到概率。。
11
4.3 直方图概率累积的优化
对概率进行累加,可以采用并行规约算法,提高累加的速度。
12
4.4 灰度的映射优化
13
5.对比分析
GPU 与 CPU 运行时间的对比
输入十张不同大小的图片进行结果对比,并且每个图片运行十遍。
输入的图像大小:800×534
输入的图像大小:500×413
输入的图像大小:576×324
输入的图像大小:3584×2016
输入的图像大小:720×480
输入的图像大小:1920×1080
输入的图像大小:2560×1600
输入的图像大小:1920×1200
输入的图像大小:3840×2160
14
图片的大小
CPU运行时间
GPU运行时间
加速比
800×534
34.4907ms
1.1950ms
28.86
500×413
30.8715ms
2.96653ms
10.40
576×324
10.9619ms
1.377280ms
7.96
3584×2016
116.913ms
4.320256
27.06
720×480
64.2778ms
1.045504ms
61.480
1920×1080
109.867ms
1.959936ms
56.056
2560×1600
121.166ms
2.969600ms
40.8021
1920×1200
110.219ms
1.956864ms
56.3243
3840×2160
117.654ms
5.150720ms
22.8422
通过上述简单的实验,可以得出随着图片变大,CPU上运行的时间越长,加速比越来越大。由于时间有限,我自己认为应该比较使用全局内存和共享内存下实验结果的区别,同时利用不同的Block和Thread进行对比,在写报告的时,发现新的优化方法,来不及进行实验。但是,上述实验说明对串行程序起到了一定程度上的加速优化作用。
6.总结
通过测试对比,可以发现在GPU上使用共享内存,原子操作和规约加法的优化加速方法,可以较为显著的提高性能。由于时间有限,在实验的对比上做法有些粗糙。为了提高实验的准确性,应该考虑在全局内存下和共享内存的实验对比,也可以实验不用规约和用规约的区别,开辟不同数量的Block和Thread进行测试。同时,从学习的过程中,我发现可以有更好的优化方法,例如使用纹理内存或者常量内存。虽然这次报告写的较为粗糙,但是实验结果还是在一定程度上具有可靠性。
通过这次课程设计,我学到了很多,不仅仅是对上课知识的系统回顾和总结,从同学报告中有了新的知识,得到新的启发。更为重要的是,燃起了我对GPU开发的浓厚兴趣,对以前的编写的开发代码和编程知识有了新的思考,冥冥之中发现新天地,并且希望更加深入学习GPU的开发。在此,衷心感谢老师默默付出,和上课同学对我潜移默化的影响和帮助。
15
课 程 设 计
题目: CUDA加速和优化直方图均衡化
姓 名: 倪长好
学 号: SA19219093
学 院: 微电子学院
专 业: 集成电路
指导教师: 谭立湘
2019 年 12 月 15 日
1
CUDA加速和优化直方图均衡化
项目简介
直方图均衡化(Histogram Equalization) 又称直方图平坦化,实质上是对图像进行非线性拉伸,重新分配图像象元值,使一定灰度范围内象元值的数量大致相等。直方图均衡化的只要目的是为了图像的增强。在现实的拍摄过程中,比如说视频监控领域,由于其图像的灰度分布集中在较窄的范围内,这就导致了图像的细节不够清晰。为什么不清晰呢,因为灰度分布较窄时,在计算对比度的时候,对比度就很小,所以就不清晰。为了使得图像变得清晰,那么就需要使得灰度值的差别变大,为了使得灰度值的差别变大,就意味着灰度分布就变的较宽,使得灰度值分布变得均匀,在某个灰度级区间内,像素的个数分布大致相同,这样才能使得图像的对比度增强,细节变得清晰可见。直方图均衡化就是对图像进行非线性拉伸,使得变换后的图像直方图分布均匀。
基于 GPU 课程学习的基础上,采用 CUDA 编程对直方图均衡化加速和优化,利用 GPU 的高度并发性能,提高对图片处理的速度。设计中实现了直方图灰度的统计,灰度占比的计算,直方图概率累积,灰度映射,并且在 GPU 实现和 CPU 实现进行了对比实验。
关键词:CUDA,直方图均衡化,共享内存,原子操作
2
目录
1.CUDA简介… 4
1.1 CUDA编程................................................................................................................. 4
1.1.1 CUDA的执行模型… 4
1.2.1 常用函数及用法........................................................................................... 4
1.2 软件配置.................................................................................................................... 5
1.3 硬件配置.................................................................................................................... 5
-
基础知识… 6
2.1 共享内存… 6
2.2 原子操作---------------------------------------------------------------------------------------------- 6
2.3 规约操作… 6
-
CPU源程序… 8
3.1 直方图灰度的统计… 8
3.2 灰度图占比的计算… 8
3.3 直方图概率的累积… 9
3.4 灰度的映射… 9
3.5 实验结果测试… 10
-
GPU加速优化… 11
4.1 直方图灰度统计的优化… 11
4.2 灰度占比的优化… 11
4.3 直方图概率累积的优化… 12
4.4 灰度映射的优化… 13
-
对比分析… 14
-
总结… 15
3
1.CUDA简介
1.1CUDA 编程
1.1.1 CUDA 的执行模型
在 CUDA
的架构下,一个程序分为两个部份:host
端和
device 端。Host 端是指在 CPU 上执行的部份,而 device 端则是在显示芯片上执行的部份。Device
端的程序又称为 kernel。通常 host 端程序会将数据准备好后,复制到显卡的内
存中,再由显示芯片执行 device 端程序,完成后再由 host 端程序将结果从显卡
的内存中取回。一个完整的 CUDA 程序是由一系列的设备端 kernel 核函数并行
步骤和主机端串行处理步骤共同组成的。在这个模型中,CPU 与 GPU 协同工作,
CPU
负责进行逻辑性强的事物处理和串行计算,GPU
则专注于执行高度线程化
的并形处理任务。
Kernel
不是一个完整的程序,而只是其中的一个关键并行计算步骤。Kernel
以一个网格(Grid)的形式,每个网格由若干个线程块(block)组成,每一个线
程块又由若干个线程(thread)组成。
1.1.2 常用函数及用法
(1)核函数的声明与执行
要写在显示芯片上执行的程序。在 CUDA 中,在函数前面加上__global__表
示这个函式是要在显示芯片上执行的。在显示芯片上执行的程序有一些限制,首
先最明显的一个限制,不能有传回值,一般把计算结构返回值写在函数的指针类
型参数中。
在 CUDA 中,要执行一个核函数,可以使用语法:
函数名称<<<block
数目,
thread 数目, shared memory 大小>>>(参数…);
(2)全局内存的使用
GPU 的全局内存之所以是全局内存,主要是因为 GPU 与 CPU 都可以对它进
行写操作,任何设备都可以通过 PCI-E 总线对其进行访问。在多 GPU 系统GPU 之间可以不通过 CPU 直接将数据从一块 GPU 卡传输到另一块 GPU 卡上。使用 cudaMalloc 函数开辟一块全局内存空间。使用 cudaMemcpy
函数可以把 CPU 上的数据传输到 GPU 的全局内存上或者相反方向。
4
1.2软件配置
在win10
系统上完成 CUDA8.0 的安装:
在win10
系统上安装opencv3.4.0
在win10
系统上安装 Visual Studio 2015。
1.3 硬件配置
处理器:Intel®
Core™ i5-8500U CPU @ 3.00GHz 3.00GHz,RAM: 8.00GB
显卡:Intel® HD
Graphics Family
NVIDIA
GeForce GT 730
5
2.基础知识
2.1 共享内存
ShareMemory(共享内存) 是一个 block 中所有thread 都能使用的共享内存,存取的速度相当快,存取
shared memory 的速度和存取寄存器相同,不需要担心 latency
的问题。原理上来说,共享内存是GPU上可受用户控制的一级缓存。在一个SM中,存在着若干cuda core + DP(双精度计算单元) + SFU(特殊函数计算单元)+共享内存+常量内存+纹理内存。因而共享内存的使用时性能提高的一个重要的因素。但是注意到,将数据拷贝到共享内存中也消耗了部分时间。因而,共享内存仅仅适合存在着数据的重复利用,全局的内存合并或者是线程之间有共享数据的时候,否则直接使用全局内存会更好一些。
2.2原子操作
原子操作 是指对全局和共享内存中的32位或者64位数据进行 “读取-修改-覆写”这一操作。原子操作可以看作是一种最小单位的执行过程。
在其执行过程中,不允许其他并行线程对该变量进行读取和写入的操作。 如果发生竞争,则其他线程必须等待。原子操作只支持某些运算(加、减、最小值、异或运算等,不支持求余和求幂等)和数据类型(整型),但是需要注意的是,原子操作的运行顺序不定,如果安排不当的话,会使速度变慢。
2.3规约操作
规约是一类并行算法,对传入的N个数据,使用一个二元的符合结合律的操作符⊕,生成1个结果。这类操作包括取最小、取最大、求和、平方和、逻辑与/或、向量点积。规约也是其他高级算法中重要的基础算法。除非操作符⊕的求解代价极高,否则规约倾向于带宽受限型任务(bandwidthbound)。本文将介绍几种规约算法的实现,从两遍规约、block的线程数必须为2的幂,一步一步优化到单遍规约、任意线程数的规约实现,还将讨论讨论基于C++模板的优化。
6
7
3.CPU源程序
3.1 直方图灰度的统计
我们要处理的图像是灰度图像,如果是彩色的,需要先转化成灰度图像,然
后确定图像的灰度级有多大,一般就是8位的图像,灰度级为0-255。利用opencv
加载图像并且转换成灰度图。
对灰度图进行直方图的统计。
3.2 灰度图占比的计算
8
3.3 直方图概率的累积
3.4 灰度的映射
9
3.5 实验结果测试
输入原图:
直方图均衡化的图:
10
4.GPU 加速优化
4.1 直方图灰度的统计的优化
开辟一段共享内存,数据在共享内存的读写速度大于在全局内存的读写速度。同时,保证输出结果的正确性,使用原子操作。开辟的线程数为16×16.
4.2 灰度图占比的计算的优化
在一个block中,开辟256个线程,并行计算得到概率。。
11
4.3 直方图概率累积的优化
对概率进行累加,可以采用并行规约算法,提高累加的速度。
12
4.4 灰度的映射优化
13
5.对比分析
GPU 与 CPU 运行时间的对比
输入十张不同大小的图片进行结果对比,并且每个图片运行十遍。
输入的图像大小:800×534
输入的图像大小:500×413
输入的图像大小:576×324
输入的图像大小:3584×2016
输入的图像大小:720×480
输入的图像大小:1920×1080
输入的图像大小:2560×1600
输入的图像大小:1920×1200
输入的图像大小:3840×2160
14
图片的大小
CPU运行时间
GPU运行时间
加速比
800×534
34.4907ms
1.1950ms
28.86
500×413
30.8715ms
2.96653ms
10.40
576×324
10.9619ms
1.377280ms
7.96
3584×2016
116.913ms
4.320256
27.06
720×480
64.2778ms
1.045504ms
61.480
1920×1080
109.867ms
1.959936ms
56.056
2560×1600
121.166ms
2.969600ms
40.8021
1920×1200
110.219ms
1.956864ms
56.3243
3840×2160
117.654ms
5.150720ms
22.8422
通过上述简单的实验,可以得出随着图片变大,CPU上运行的时间越长,加速比越来越大。由于时间有限,我自己认为应该比较使用全局内存和共享内存下实验结果的区别,同时利用不同的Block和Thread进行对比,在写报告的时,发现新的优化方法,来不及进行实验。但是,上述实验说明对串行程序起到了一定程度上的加速优化作用。
6.总结
通过测试对比,可以发现在GPU上使用共享内存,原子操作和规约加法的优化加速方法,可以较为显著的提高性能。由于时间有限,在实验的对比上做法有些粗糙。为了提高实验的准确性,应该考虑在全局内存下和共享内存的实验对比,也可以实验不用规约和用规约的区别,开辟不同数量的Block和Thread进行测试。同时,从学习的过程中,我发现可以有更好的优化方法,例如使用纹理内存或者常量内存。虽然这次报告写的较为粗糙,但是实验结果还是在一定程度上具有可靠性。
通过这次课程设计,我学到了很多,不仅仅是对上课知识的系统回顾和总结,从同学报告中有了新的知识,得到新的启发。更为重要的是,燃起了我对GPU开发的浓厚兴趣,对以前的编写的开发代码和编程知识有了新的思考,冥冥之中发现新天地,并且希望更加深入学习GPU的开发。在此,衷心感谢老师默默付出,和上课同学对我潜移默化的影响和帮助。
15