cuda+opencv多线程加速笔记

CUDA学习
https://www.cnblogs.com/1024incn/tag/CUDA/

CUDA快速傅里叶变换(cuFFT)

原文:https://blog.csdn.net/csgxy123/article/details/10525693

线程网络的分配
https://blog.csdn.net/s_sunnyy/article/details/60580541

利用cufft进行的图像傅里叶变换的注意事项
http://blog.sina.com.cn/s/blog_471e6c930102wldk.html

  1. 简介
    cuFFT是的全称是CUDA Fast Fourier Transform,顾名思义,它提供了一系列的函数帮助开发者进行快速傅里叶变换的运算。cuFFT库由两个子库构成,它们分别是CUFFT和CUFFTW。CUFFTW库是一个移植工具(porting tool),它为用户提供了一些接口,以使得用户使用FFTW库(一个非常流行的CPU快速傅里叶变换库)编写的程序能够运行在CUDA GPU上。而CUFFT则是纯CUDA接口的快速傅里叶变换库。

在CUDA toolkit 5.5版本中,cuFFT库支持的特性有:

1、对于可以表示为的输入规模,CUFFT会自动采用一些优化算法来达到最佳的运算性能

2、对于所有的输入规模,CUFFT的算法复杂性均为O(nlogn)

3、不同输入输出类型的指定:其中C2C代表输入输出均为复数,R2C代表输入为实数而输出为复数,C2R代表输入为复数而输出为实数。

4、可以进行1维、2维和3维变换

5、多个不同的1D、2D、3D变换可以并行进行

6、同时支持单精度浮点和双精度浮点运算

7、支持就地转换(输出直接覆盖输入)和外部转换(输出和输入不重叠)

8、与FFTW库兼容的数据布局

9、支持跨步输入数据读取

10、支持流执行(Streamed execution),这样就同时支持了计算与数据传输的异步并行执行。

11、对于单精度浮点数,一次最多传输128百万元素,双精度则一次最多传输64百万元素。

12、CUFFT库提供的API是线程安全的。

2. 使用CUFFT API
在关注具体的API之前,我们先来回顾一下快速傅里叶变换的背景知识。
快速傅里叶变换(FFT)是离散傅里叶变换(DFT)的快速算法,在数字信号处理、大整数乘法和求解偏微分方程等领域都有着广泛的应用,DFT的作用是将时域(time domain)上的一组离散复数与到频域(frequency domain)上的一组值相互映射,以对输入数据进行进一步处理。离散傅里叶公式可以表示为:

其中,Xk是与输入数据xk大小相同的数组,这一公式也被称作正向(forward)DFT。把上式中e的指数符号修改为正(positive),我们就得到了逆向(inverse)DFT。CUFFT API根据N的不同,将使用不同的优化算法,以达到最佳的性能。
CUFFT API的原型是FFTW库,FFTW则是一个基于CPU的高效FFT库。CUFFT提供了一个简单的被称为plan的配置方法,使用plan的好处是可以根据输入数据的大小预先配置好内存和计算资源,使得真正运算时处理器能达到最佳的性能。设置好plan后,运行execution函数,真正的傅里叶变换便开始执行了。一旦配置完成,配置信息便被保存起来,这对于多次调用来说非常省时。
下面来看一个代码片段,计算BATCH块大小为NX的一维DFT的CUDA代码通常如下所示:
#define NX 256
#define BATCH 10
… {
cufftHandle plan;
cufftComplex data;

cudaMalloc((void
*)&data, sizeof(cufftComplex)NXBATCH);
cufftPlan1d(&plan, NX, CUFFT_C2C, BATCH);

cufftExecC2C(plan, data, data, CUFFT_FORWARD);
cudaThreadSynchronize();

cufftDestroy(plan);
cudaFree(data);
}

2.1. 访问CUFFT(Accessing CUFFT)
CUFFT和CUFFTW均被实现为共享库,可以使用编译器和链接器把它们集成到普通的程序当中。这些库文件和头文件在不同系统上的默认位置如下图所示:

最常见的使用这些库函数的方法是修改一个已经存在的CUDA文件,以filename.cu为例,在filename.cu中将头文件cufft.h包含进来,然后在程序中调用CUFFT库函数,为了使得程序可以运行,一个单一文件的编译和链接命令的形式可以如下:

2.2. 傅里叶变换配置(Fourier Transform Setup)
在CUDA上进行傅里叶变换一般需要做以下几步工作:
1. 创建一个plan。调用函数cufftPlan1D/cufftPlan2D/cufftPlan3D可以分别创建一个简单的1维/2维/3维的傅里叶变换。调用函数cufftPlanMany则可以创建支持更多配置操作的变换计划。
2. 执行plan。这一步可以使用cufftExecC2C()、cufftExecR2C()或cufftExecC2R()等函数完成plan的计算任务。
3. 执行完成以后若不再需要该plan,则调用cufftDestroy()函数销毁该plan及为其分配的计算资源。

2.3 傅里叶变换类型(Fourier Transform Types)
CUFFT库实现了三种不同类型的傅里叶变换:C2C(复数到复数)、C2R(复数到实数)、R2C(实数到复数)。本质上,这三种转换都可以被看做是复数域到复数域的变换,之所以这样划分,其最主要的考量是性能因素。例如,在一般的数字信号处理中,输入数据是一些离散的实数域上的采样点,这时候对它们做傅里叶变换实际上就是R2C,根据埃尔米特对称性(Hermitian symmetry),变换后,*代表共轭复数。CUFFT的傅里叶变换类型则利用了这些冗余,将计算量降到最低。

    变换执行函数的单精度和双精度版本分别定义如下:

    1. cufftExecC2C() / cufftExecZ2Z() - 单精度/双精度浮点数复数域到复数域的傅里叶变换

    2. cufftExecR2C() / cufftExecD2Z() - 单精度/双精度浮点数实数域到复数域的傅里叶变换(正向傅里叶变换)

    3. cufftExecC2R() / cufftExecZ2D() - 单精度/双精度浮点数复数域到实数域的傅里叶变换(逆向傅里叶变换)

2.4 数据布局(Data Layout)
CUFFT库包含有若干种数据类型,对于复数有cufftComplex / cufftDoubleComplex两种数据类型,对于实数则分别有cufftReal / cufftDouble两种数据类型。
根据转换结果的存储位置不同,FFT变换可分为就地变换(in-place)和外部变换(out-of-place),前者直接在输入数据上进行变换,而后者则会将变换后的结果存入新的存储器地址。
就地转换(in-place)支持两种数据布局:native和padded,前者用于获得最佳性能,而后者则用于与FFTW库兼容。
在padded布局中输出信号的开始地址与输入信号一样,换句话说,实数域到复数域变换的输入数据和复数域到实数域的输出数据必须被填充。在native布局中则没有填充要求。
输入数据和输出数据的尺寸总结如下:

2.5 流化CUFFT变换(Streamed CUFFT Transform)
CUFFT的每一个plan都可以和某个流(stream)结合起来运行,一旦结合,那么该plan就会在特定的流上面运行。CUFFT执行的流化使得快速傅里叶变换可以和其它流中的数据拷贝任务并行运行,从而提高了设备利用率和程序性能。

2.6 线程安全(Thread Safety)
CUFFT库从版本4.1开始拥有线程安全特性,也就是说,主机端的多个线程同时调用CUFFT中的函数时,CUDA可以保证任务执行的正确

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV中,可以使用多进程来加速图像处理。多进程是一种并行计算的方法,可以将任务分解成多个子任务,每个子任务在不同的进程中执行,从而提高整体的处理速度。 要在OpenCV中实现多进程加速,可以使用Python的multiprocessing库。这个库能够创建并管理多个进程,并允许它们之间进行通信和共享数据。 以下是一个示例代码,展示了如何使用多进程在OpenCV中进行图像处理的加速: ```python import cv2 import multiprocessing as mp def process_image(img): # 图像处理的逻辑 # 这里可以使用OpenCV的函数对图像进行处理 return processed_img if __name__ == '__main__': # 加载图像 img = cv2.imread('image.jpg') # 创建进程池 pool = mp.Pool() # 将图像分成多个块,并在多个进程中处理 results = [pool.apply_async(process_image, (block,)) for block in img_blocks] # 获取处理后的图像块 processed_blocks = [result.get() for result in results] # 合并处理后的图像块 processed_img = merge_blocks(processed_blocks) # 显示处理后的图像 cv2.imshow('Processed Image', processed_img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个示例中,我们使用了multiprocessing.Pool来创建进程池。然后,将图像划分成多个块,并在多个进程中并行处理这些块。最后,将处理后的图像块合并起来,得到最终的处理结果。 需要注意的是,在多进程编程中,数据共享和通信是非常重要的。在上述示例中,我们使用了apply_async方法来异步执行图像处理任务,并在主进程中通过get方法获取处理后的结果。 总之,使用多进程可以加速OpenCV中的图像处理任务。通过将任务分解成多个子任务,并在多个进程中并行执行,可以提高整体的处理速度。123 #### 引用[.reference_title] - *1* *2* *3* [cuda+opencv多线程加速笔记](https://blog.csdn.net/weixin_41284599/article/details/90758256)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值