假设我有一个域模型,我试图与多线程兼容。 原型域是一个由Space,SpaceObject和Location对象组成的游戏域。 SpaceObject具有Move方法,Asteroid和Ship使用对象的特定属性扩展此对象(Ship具有名称,Asteroid具有颜色)
假设我想让每个对象的Move方法在一个单独的线程中运行。这将是愚蠢的,因为有10000个对象,我会有10000个线程。什么是在核心/线程之间分离工作负载的最佳方法?
我正在尝试学习并发的基础知识,并构建一个小型游戏来构建大量概念。
我已经完成的工作是构建一个域,以及一个带有计时器的线程模型,该计时器根据间隔启动事件。如果事件发生,我想用任何SpaceObject的新位置更新我的整个模型。 但是我不知道在事件发生时如何以及何时启动带有工作负载的新线程。
有些工作人员告诉我,你无法更新你的核心域多线程,因为你必须同步一切。但在这种情况下,我无法在双四核服务器上运行我的游戏,因为它只能使用1个CPU来完成最艰巨的任务。
任何人都知道该怎么做?
对Deltreme的反应规范:
你是绝对正确的,你的方法在大多数情况下都适用。但, 线程必须更新Space类中的spaceobject的位置。
假设我在彼此旁边有2个SpaceObjects,它们正朝向彼此移动。 1对象在线程A中,另一个在线程B中。 一旦我更新了对象,线程就必须一起写入Space以在Tile(Space的一个单独部分)中写入新值。那个单独的调用不能同时在不同的线程中完成,因为Space对象会爆发......
可能发生的是碰撞,我可以写一个事件,如果他们是2艘船@ 1瓦片就会发生。那不是问题。
我认为在10000次发货的情况下,CPU主要是在线程之间切换而不是全部运行它们。 因此,为了表现,我希望能够同时“一切”
答案 0 :(得分:1)
您可以使用System.Threading.ThreadPool
或即将推出的任务并行库根据可用内核数自动管理线程数。
并发问题的一种可能方法是仅锁定当前SpaceObject可以与之交互的其他SpaceObject。在大多数情况下,这将提供足够的性能,但在最坏的情况下,处理大的交互将由单个线程完成。您需要锁定多少取决于您的模拟参数。如果对象在计时器的单个刻度内无法完全相互通过,则只需检查重叠对象即可。对于快速移动的物体,您需要检测相交的运动矢量。
答案 1 :(得分:0)
我假设您创建了快照:在情境A中,每个SpaceObject都位于某个位置,并且在每个SpaceObject移动到另一个位置后,您将进入情境B.
对于10000个对象,情境A和B之间的转换是10000个移动呼叫。 Move()听起来像一个相当快速的方法,即。使用当前位置和方向创建新位置。
在这种情况下,您可以创建10个线程(或使用ThreadPool)并为其分配50个SpaceObjects,然后它将为此计算新的Locations。如果线程已完成,并且仍有SpaceObject需要移动,则为该线程分配另外50个。
答案 2 :(得分:0)
正如Hirvox所说,ThreadPool是一个不错的选择。我会避免考虑每个SpaceObject的一个线程,而是把它想象成一个SpaceObjects的大队列,它们都需要在一个区间内更新它们的位置,然后在你出列队列时使用线程来做移动计算对象;这非常适合ThreadPool。它可能不是一个实际的队列,但可能是一个排序的字典,但你明白了。
完成Move计算后,使用类似的方法处理任何碰撞。处理快速移动器的一种方法是在非常短的时间间隔内工作,每隔一个间隔更新快速移动器,每隔一个间隔更新一次移动器,每十个间隔移动一次。
只是为了好玩,请考虑使用视频卡进行计算 - 高端GPU经过优化,可以同时进行计算。