三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Shader学习22:ComputeShader

Shader学习22:ComputeShader

概念理解

  1. cpu-逻辑处理;gpu-渲染计算

  2. 当一个脚本上挂有一个m次的for循环,当场景中有n个该脚本时,就需要nm次,当这个值很大时,就容易遇到性能瓶颈。为了解决该问题,unity提供了ComputeShader这个解决方案。

  3. cpu-一个教授,难易都能解决,但当数量大时也要花时间去算;computeShader-很多小学生,每个只负责简单计算,并行处理。在这种情况下,一群小学生 > 教授

BUT - SO

  1. 问题:cpu和gpu之间无法直接进行数据交互,所以如果要把数据给到gpu,就要通过显存上的Buffer(缓冲区),作为中转站。

  2. 所以,在cpu上new并绑定buffer,然后将需要进行循环计算的初始数据给到buffer,gpu就能从buffer中获取到数据 进行并行计算,算完后再将数据传回buffer,cpu再从buffer中拿结果后,会继续干自己主线程的事。

    1. ⚠️注:因为buffer只能存入值类型的数据,所以数据复杂时,需要构造struct

    💡 显存介绍:
    cpu的工作台是内存,gpu的工作台是显存,但他们只能读写自己的数据,所以cpu想让gpu帮忙计算东西的时候,需要把数据搬到显存上,gpu算完再搬回来

    显卡由 gpu芯片(负责计算) + 显存VRAM(存数据)组成,显存紧挨着芯片能让它读写非常快。

实战演习

基础实现

  1. c#文件:

    1. 持有computeShader文件引用,准备输入数据

    2. 创建输入、输出buffer,传入数据,并将该buffer绑定到computeShader

      输入输出buffer分开放,能避免同时读写的数据竞争。

      创建buffer时的构造参数:(count, stride) —— (这块 Buffer 里有多少个元素,每个元素占多大)

    3. 启动computeShader,gpu执行计算

    4. 从buffer中拿到结果,释放buffer,继续自己的主线程

    kernel【核心、内核】—— 核心函数解释:gpu上要执行的一个函数。用#pragma kernel标记函数,再用FindKernel("CSMain")找到具体函数,然后用Dispatch让gpu执行

  2. computeShader文件:

    1. 创建输入、输出缓冲区

    2. 划分线程组。

      线程组解释:
      GPU 并不是一个线程一个线程地跑,而是把线程打包成固定大小的组一起执行。
      同一个线程组内的线程可以共享一块很快的组共享内存,不同线程组间则是完全独立的

      [numthreads(8, 8, 1)] 先定义一个线程组里有多少个线程,再用Dispatch(groupX, groupY, groupZ)决定要启动多少个线程组,所以为了能够让所有数据都进行计算,线程组数的分配要向上取整。

      线程组本身是个三维结构,选择几维的写法取决于本身自己的数据是几维的,目的是让代码更简洁。像是处理贴图这种二维数据,线程组就要构造成二维的分组(eg. 8,8,1),像是处理流体模拟这种三维的数据,就要构造成三维的分组

    三维相乘 = 一个组内的线程数


❓ 分线程组的时候,一维是 64 1 1,二维 8 8 1,三维4 4 4,为什么乘起来都是64?

💡 和硬件有关。

小一点呢?可以看到这些gpu的厂商,每次执行的最小单位是32、64,如果给一个线程组里分48个线程,就一定会浪费25%的算力。

大一点呢?线程组越大,每个线程能分到的寄存器和共享内存就越少(它们是共享的资源池)。如果你的 shader 逻辑复杂、用的变量多,线程组太大反而会变慢(因为寄存器不够用,会溢出到慢速内存)。

——》64大概是一个比较平衡的选择,闭眼选不会出错。


数值能差多少

——借鱼群算法看性能优势

顺便调研一下:下次遇到批量计算,多少量级使用什么方法

flock.mp4

  1. 多少量级开始,使用compute shader优于cpu?

  2. 如果算上job,多少量级开始 使用compute shader优于job?

结论:

(1)单纯的话,大概100只开始,gpu优于cpu;

(2)但是如果加上job:
16以内的量级时,直接用最普通的cpu最合算;1000或者1500以内,用Job;再大就可以考虑使用compute shader了。

← 返回列表