用 CS 做高斯模糊
先简单说一下 CPU 和 GPU 的架构不同点。
CPU 有很多的 ALU 算数运算单元,GPU 则是更多的流处理器,所以 CPU 适合复杂的运算任务,而 GPU 适合简单的多核简单运算。
一些 GPU 中的概念
streaming processor(sp): 最基本的处理单元。GPU 进行并行计算,也就是很多个 SP 同时做处理。现在 SP 的术语已经有点弱化了,而是
直接使用thread来代替。一个 SP 对应一个 thread。Warp:warp 是SM 调度和执行的基础概念,通常一个 SM 中的 SP(Thread) 会分成几个 Warp (也就是 SP 在 SM 中是进行分组的,物理上进
行的分组),一般每一个 Warp 中有32个 Thread.这个 Warp 中的32个 Thread(sp) 是一起工作的,执行相同的指令,如果没有这么多 Thread
需要工作,那么这个 Warp 中的一些 Thread(sp) 是不工作的(每一个线程都有自己的寄存器内存和 Local Memory,一个 Warp 中的线程是同时
执行的,也就是当进行并行计算时,线程数尽量为32的倍数,如果线程数不上32的倍数的话;假如是1,则 Warp 会生成一个掩码,当一个指令控制器对一个 Warp 单位的线程发送指令时,32个线程中只有一个线程在真正执行,其他31个 进程会进入静默状态。)Streaming Multiprocessor(sm):多个 SP 加上其他的一些资源组成一个 SM, 其他资源也就是存储资源,共享内存,寄储器等。可见,一个
SM 中的所有SP是先分成 Warp的,是共享同一个 Memory和 Instruction Unit(指令单元)。从硬件角度讲,一个 GPU 由多个 SM 组成(当然
还有其他部分),一个 SM 包含有多个 SP(以及还有寄存器资源,Shared Memory资源,L1cache,Scheduler,SPU,LD/ST单元等等)
关于 SIMD :
- SIMD(Single Instruction Multiple Data)即单指令流多数据流,是一种采用一个控制器来控制多个处理器,同时对一组数据(又称“数据向量”)中的每一个分别执行相同的操作从而实现空间上的并行性的技术。简单来说就是一个指令能够同时处理多个数据。
CS 的执行时机:
如下图所示,计算着色器不属于渲染管线的一部分,但是计算着色器可以读写渲染管线。
一个线程组运行于一个多处理器之上,因此对于拥有16个多处理器的 GPU 来说,我们至少应该将任务分解为 16 个线程组,以此领每个多处理器都
充分的运转起来。但是,要活的更佳的性能,我们还应当令每个多处理器至少拥有两个线程组,使它能够切换到不同的线程组进行处理,以连续不停的工作。
每个线程组中都有一块共享内存,供组内的线程访问。但是线程并不能访问其他组中的共享内存。同理,同组内的线程间能够进行同步操作,不同组
的线程间却不能实现这一点。
一个线程组含有 n 个线程。硬件实际上会将这些线程分为多个 warp,而且多处理器会以 SIMD32 的方式来处理 warp。每个 CUDA 核心都可处理一个线程。在 D3D 中能够以非 32 倍数指定线程组的大小,但是出于性能原因应该将线程组的大小设置为 32 的倍数。
CS 代码
1 |
|
unroll 的含义:
- 添加了unroll标签的for循环是可以展开的,直到循环条件终止,代价是产生更多机器码
然后是几个测试结果
小米 11 青春版 1000 个圆球每帧更新坐标:
13700K + 4090 50000物体每秒更新坐标 :
小米 11 青春版 运行高斯模糊 :
参考连接 :
- https://www.jianshu.com/p/1527ff975a1b
- https://www.ronja-tutorials.com/post/050-compute-shader/
- https://blog.csdn.net/sinat_24229853/article/details/77151102
- https://zznewclear13.github.io/posts/accelerate-gaussian-blur-using-group-shared-memory/
- https://segmentfault.com/a/1190000040825838
- https://www.cnblogs.com/biglucky/p/4223565.html
- https://zhuanlan.zhihu.com/p/53763285
- https://zhuanlan.zhihu.com/p/115871017