游戏消息传递系统的选项

发布于 2024-07-23 17:12:37 字数 1025 浏览 7 评论 0原文

我正在用 C++ 开发一款针对手持硬件(Pandora)的 RTS 游戏。 作为参考,Pandora 有一个约 600Mhz 的 ARM 处理器,并运行 Linux。 我们正在尝试建立一个良好的消息传递系统(内部和外部),这对我来说是一个新领域。

举一个我们想要传递的消息的例子可能会有所帮助。 一个单元可以进行此调用以将其模型加载到内存中:

sendMessage("model-loader", "load-model", my_model.path, model_id );

作为回报,该单元可能期望某种类型包含特定 model_id 的模型对象的消息,然后可以将其传递到图形系统。 请注意,这个 sendMessage 函数绝不是最终的。 它只是反映了我目前对消息传递系统的理解,这可能不正确:)

据我所知,有两种截然不同的选择。 一种是在内存中传递消息,只有在需要与外部机器对话时才通过网络传递。 我喜欢这个想法,因为开销似乎很低,但这里的大问题是,您似乎需要在消息队列上广泛使用互斥锁。 如果可能的话,我真的很想避免过度锁定。 我已经阅读了几种无需锁定即可实现简单队列的方法(通过依赖原子 int 操作),但这些方法假设队列只有一个读取器和一个写入器。 这对于我们的特定情况似乎没有用,因为一个对象的队列将有许多写入者和一个读取者。

另一种选择是完全越过网络层。 这有一些有趣的优点,比如几乎免费获得异步消息传递。 此外,我们还能够使用与本地传递完全相同的调用将消息传递到其他机器。 然而,这个解决方案让我感到不舒服,可能是因为我不完全理解它:)我们是否需要为每个要发送/接收消息的对象提供一个套接字? 如果是这样,这似乎有些过分了。 一个给定的游戏将有数千个对象。 对于像潘多拉这样动力不足的设备,我担心像这样滥用网络可能最终会成为我们的瓶颈。 但是,我还没有进行任何测试,所以这只是猜测。

MPI 似乎在消息传递方面很受欢迎,但对于我们想要的东西来说,它确实感觉有些过头了。 这段代码永远不会接触集群或需要进行大量计算。

非常感谢您了解我们有什么选择来实现这一目标。

I'm working on an RTS game in C++ targeted at handheld hardware (Pandora). For reference, the Pandora has a single ARM processor at ~600Mhz and runs Linux. We're trying to settle on a good message passing system (both internal and external), and this is new territory for me.

It may help to give an example of a message we'd like to pass. A unit may make this call to load its models into memory:

sendMessage("model-loader", "load-model", my_model.path, model_id );

In return, the unit could expect some kind of message containing a model object for the particular model_id, which can then be passed to the graphics system. Please note that this sendMessage function is in no way final. It just reflects my current understanding of message passing systems, which is probably not correct :)

From what I can tell there are two pretty distinct choices. One is to pass messages in memory, and only pass through the network when you need to talk to an external machine. I like this idea because the overhead seems low, but the big problem here is it seems like you need to make extensive use of mutex locking on your message queues. I'd really like to avoid excess locking if possible. I've read a few ways to implement simple queues without locking (by relying on atomic int operations) but these assume there is only one reader and one writer for a queue. This doesn't seem useful to our particular case, as an object's queue will have many writers and one reader.

The other choice is to go completely over the network layer. This has some fun advantages like getting asynchronous message passing pretty much for free. Also, we gain the ability to pass messages to other machines using the exact same calls as passing locally. However, this solution rubs me the wrong way, probably because I don't fully understand it :) Would we need a socket for every object that is going to be sending/receiving messages? If so, this seems excessive. A given game will have thousands of objects. For a somewhat underpowered device like the Pandora, I fear that abusing the network like that may end up being our bottleneck. But, I haven't run any tests yet, so this is just speculation.

MPI seems to be popular for message passing but it sure feels like overkill for what we want. This code is never going to touch a cluster or need to do heavy calculation.

Any insight into what options we have for accomplishing this is much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

月朦胧 2024-07-30 17:12:37

网络也将使用锁定。 它只是在操作系统内核中你看不到的地方。

我要做的是创建您自己的消息队列对象,您可以根据需要重写该对象。 从简单开始,然后根据需要使其变得更好。 这样您就可以让它在幕后使用您喜欢的任何实现,而无需更改其余代码。

查看您将来可能想要执行的几种可能的实现,并设计您的 API,以便在您决定按照这些条款实现时可以有效地处理所有这些实现。

如果您想要真正高效的消息传递,请查看一些开源 L4 微内核。 这些人在快速消息传递上投入了大量时间。

The network will be using locking as well. It will just be where you cannot see it, in the OS kernel.

What I would do is create your own message queue object that you can rewrite as you need to. Start simple and make it better as needed. That way you can make it use any implementation you like behind the scenes without changing the rest of your code.

Look at several possible implementations that you might like to do in the future and design your API so that you can handle them all efficiently if you decide to implement in those terms.

If you want really efficient message passing look at some of the open source L4 microkernels. Those guys put a lot of time into fast message passing.

痴者 2024-07-30 17:12:37

由于这是一个小型平台,因此可能值得对这两种方法进行计时。

然而,除非出现某种大的速度问题,我总是会选择编码更简单的方法。 这可能会使用网络堆栈,因为无论接收者在哪里,它都是相同的代码,并且您不必手动编码和调试互斥、消息缓冲、分配等。

如果您发现它太慢了,您可以稍后使用内存重新编码本地内容。 但是,如果不必要的话,为什么要浪费时间预先做这些呢?

Since this is a small platform, it might be worth timing both approaches.

However, barring some kind of big speed issue, I'd always go for the approach that is simpler to code. That is probably going to be using the network stack, as it will be the same code no matter where the recipient is, and you won't have to manually code and degug your mutual exclusions, message buffering, allocations, etc.

If you find out it is too slow, you can always recode the local stuff using memory later. But why waste the time doing that up front if you might not have to?

装迷糊 2024-07-30 17:12:37

我同意 Zan 的建议,即尽可能在内存中传递消息。

原因之一是您可以传递复杂的对象 C++,而无需对它们进行编组和反编组(序列化和反序列化)。

使用信号量保护消息队列的成本很可能低于进行网络代码调用的成本。

如果您使用某种无锁算法(使用您自己提到的原子操作)保护消息队列,您可以避免大量上下文切换进出内核。

I agree with Zan's recommendation to pass messages in memory whenever possible.

One reason is that you can pass complex objects C++ without needing to marshal and unmarshal (serialize and de-serialize) them.

The cost of protecting your message queue with a semaphore is most likely going to be less than the cost of making networking code calls.

If you protect your message queue with some lock-free algorithm (using atomic operations as you alluded to yourself) you can avoid a lot a context switches into and out of the kernel.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文