文件: | 在 GitHub* 上下载: |
许可: | 英特尔示例源代码许可协议 |
面向……优化 | |
---|---|
操作系统: | Windows® 10(64 位) |
硬件: | 需要 GPU |
软件: (编程语言、工具、IDE、框架) | Microsoft Visual Studio* 2017、Unity* 5.6、C# |
前提条件: | 熟悉 Microsoft Visual Studio、Unity* API、3D 图形、并行处理。 |
教程: | 使用 Unity* 进行并行处理的一种方法 |
简介
该项目的理念是展示如何使用 Unity* 在游戏中进行并行处理,以及如何使用游戏引擎执行与游戏相关的物理。在这个领域内,现实感是成功的一个重要标志。为了模拟真实世界,许多动作需要同时发生,这需要并行处理。创建两个不同的应用,然后将它们与在单个内核上运行的单线程应用进行比较。代码和随附的文章(参见下面的参考文献)介绍了群集算法的开发,并通过两个应用以鱼群的形式展示该算法。第一个应用在多线程 CPU 上运行,第二个应用在 GPU 上执行物理计算。
- 群集算法的实施
- 编码差异:CPU 对比 GPU
入门教程
群集算法的实施
在本示例中,一个群集被定义为一群鱼。算法需要考虑每个成员的聚集、队列和分离。如果每条鱼都与鱼群中的其他鱼保持一定的距离,经过计算得出,该鱼在一个鱼群里“游动”。鱼群的成员只能以群集成员的身份行动,不得单独行动,它们拥有相同的参数,如速度和方向。
该群集算法的复杂度为 O(n2),其中,n 为鱼的数量。为了更新单条鱼的移动,算法需要查看环境中的所有其他 n 条鱼,以确定鱼是否可以 1) 留在鱼群;2) 离开鱼群;或者 3) 加入新鱼群。单条鱼可能单独“游”一段时间,并有机会加入新鱼群。这需要针对每条鱼执行 n 次。
算法可以被简化为:
对于每条鱼 (n)
查看所有其他的鱼 (n)
如果鱼之间的距离足够近
应用规则:聚集、队列和分离
数据被存储于两个缓冲区内,以表示每条鱼的状态。交替使用这两个缓冲区进行读写。需要这两个缓冲区在内存中维持每条鱼之前的状态。然后,使用该信息计算每条鱼的下一个状态。在每一帧前,读取当前读取缓冲,以更新场景。
该应用的基本流程为:
- 初始化场景。
- 针对每一帧更新场景
- 读取当前的读取缓冲
- 计算场景
- 渲染场景
- 写入当前的写入缓冲
- 交换缓冲
编码差异:CPU 对比 GPU
单线程和多线程应用的主要编码区别体现在如何调用群集计算上。请记住,每一帧都会调用 n 次该计算。单线程应用使用常规的 for 循环,而多线程应用使用 Parallel.For 类。
为了得到最佳性能,将物理计算的任务转移至 GPU。为此,在 GPU上使用并执行“着色器”。使用着色器为场景添加图形效果。本项目使用了“计算着色器”。通过 HLSL(高级着色器语言)编写计算着色器。计算着色器复制 Calc 函数的行为(如速度、位置、方向等),但是无需计算旋转。
使用 Parallel.For 函数的 CPU 调用面向每条鱼的 UpdateStates 函数,以便在绘制每条鱼前,计算其旋转并创建 TRS 矩阵。使用“四元数”类的 Unity 函数 Slerp 计算鱼的旋转。
请注意,随附的文章指出了使用 GPU 时需要考虑的其他方面:
- GPU 上的随机数生成
- 在 GPU 和 CPU 之间交换与共享数据
- CPU 优于 GPU 的案例
参考资料
Jeremy Servoz,Integrated Computing Solutions 公司,《使用 Unity 进行并行处理的一种方法》,https://software.intel.com/zh-cn/articles/an-approach-to-parallel-processing-with-unity,2018
更新日志
创建于 2018 年 3 月 20 日