为了加快 C# 中物理对象的处理速度,我决定将线性更新算法更改为并行算法。我认为最好的方法是使用 ThreadPool,因为它是为完成作业队列而构建的。
当我第一次实现并行算法时,我为每个物理对象排队了一个作业。请记住,单个作业完成得相当快(更新力、速度、位置,检查与任何周围对象的旧状态的碰撞以使其线程安全等)。然后,我将使用单个等待句柄等待所有作业完成,每次物理对象完成时我都会递减一个互锁整数(在达到零时,我然后设置等待句柄)。需要等待,因为我需要做的下一个任务涉及更新所有对象。
我注意到的第一件事是表演很疯狂。平均下来,线程池的速度似乎快了一点,但性能却出现了巨大的峰值(每次更新大约 10 毫秒,随机跳转到 40-60 毫秒)。我尝试使用 ANTS 对此进行分析,但是我无法深入了解为什么会出现尖峰。
我的下一个方法是仍然使用 ThreadPool,但是我将所有对象分成组。我最初只使用 8 个组,因为这就是我的计算机所具有的任何内核。表演很棒。它远远优于单线程方法,并且没有峰值(每次更新大约 6 毫秒)。
我唯一想到的是,如果一个工作在其他工作之前完成,就会有一个空闲的核心。因此,我将作业数量增加到 20 个左右,甚至增加到 500 个。正如我所料,它下降到 5ms。
所以我的问题如下:
- 当我快速/大量地调整作业大小时,为什么会出现尖峰?
- 是否有任何关于如何实现 ThreadPool 的见解可以帮助我了解如何最好地使用它?