ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Shader学习22:ComputeShader

Shader学习22:ComputeShader 概念理解cpu-逻辑处理gpu-渲染计算当一个脚本上挂有一个m次的for循环当场景中有n个该脚本时就需要nm次当这个值很大时就容易遇到性能瓶颈。为了解决该问题unity提供了ComputeShader这个解决方案。cpu-一个教授难易都能解决但当数量大时也要花时间去算computeShader-很多小学生每个只负责简单计算并行处理。在这种情况下一群小学生 教授BUT - SO问题cpu和gpu之间无法直接进行数据交互所以如果要把数据给到gpu就要通过显存上的Buffer缓冲区作为中转站。所以在cpu上new并绑定buffer然后将需要进行循环计算的初始数据给到buffergpu就能从buffer中获取到数据 进行并行计算算完后再将数据传回buffercpu再从buffer中拿结果后会继续干自己主线程的事。⚠️注因为buffer只能存入值类型的数据所以数据复杂时需要构造struct 显存介绍cpu的工作台是内存gpu的工作台是显存但他们只能读写自己的数据所以cpu想让gpu帮忙计算东西的时候需要把数据搬到显存上gpu算完再搬回来显卡由 gpu芯片负责计算 显存VRAM存数据组成显存紧挨着芯片能让它读写非常快。实战演习基础实现c#文件持有computeShader文件引用准备输入数据创建输入、输出buffer传入数据并将该buffer绑定到computeShader输入输出buffer分开放能避免同时读写的数据竞争。创建buffer时的构造参数(count, stride) —— (这块 Buffer 里有多少个元素每个元素占多大)启动computeShadergpu执行计算从buffer中拿到结果释放buffer继续自己的主线程kernel【核心、内核】—— 核心函数解释gpu上要执行的一个函数。用#pragma kernel标记函数再用FindKernel(CSMain)找到具体函数然后用Dispatch让gpu执行computeShader文件创建输入、输出缓冲区划分线程组。线程组解释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多少量级开始使用compute shader优于cpu如果算上job多少量级开始 使用compute shader优于job结论1单纯的话大概100只开始gpu优于cpu2但是如果加上job16以内的量级时直接用最普通的cpu最合算1000或者1500以内用Job再大就可以考虑使用compute shader了。
返回列表