0

我正在模拟具有大量节点的网状网络。节点在整个网络的不同主节点之间传递数据。

每个主节点每秒上线一次接收信息,但是从节点不知道主节点何时启动,因此当它们有信息要发送时,它们会尝试每5毫秒发送一次,持续1秒以确保他们可以找到主人。

在具有 1600 个节点的普通计算机上运行此程序会产生 1600 个线程,并且性能极差。

什么是处理线程的好方法,以便每个节点都像在自己的线程上运行一样?

万一这很重要,我将在 python 2.7 中构建模拟,但如果有意义的话,我愿意更改为其他东西。

4

4 回答 4

1

对我来说,1600 个线程听起来很多但并不过分,因为它是一个模拟。如果这是一个生产应用程序,它可能不具备生产价值。

标准机器处理 1600 个线程应该没有问题。至于操作系统,本文可以为您提供一些见解。

当涉及到您的代码时,Python 脚本不是本机应用程序,而是解释脚本,因此需要更多的 CPU 资源来执行。

我建议您尝试用 C 或 C++ 来实现模拟,这将产生一个应该更有效地执行的本机应用程序。

于 2013-09-30T09:47:45.677 回答
1

一方面,您是否真的使用默认 Python 2.7 解释器 (CPython) 中可用的常规默认 Python 线程,并且您的所有代码都是 Python 中的?如果是这样,您可能实际上并没有使用多个 CPU 内核,因为 CPython 具有全局解释器锁(请参阅https://wiki.python.org/moin/GlobalInterpreterLock)。您也许可以尝试在 Jython 下运行您的代码,以检查性能是否会更好。

您可能应该重新考虑您的应用程序架构并切换到手动调度事件而不是使用线程,或者尝试使用类似 greenlets ( https://stackoverflow.com/a/15596277/1488821 ) 的东西,但这可能意味着不太精确的时间安排,因为缺乏并行性。

于 2013-09-30T10:00:34.470 回答
1

不要为此使用线程。如果坚持 Python,让节点一个一个地执行它们的动作。如果这样做的性能还可以,则不必使用 C/C++。如果每个节点执行的操作都很简单,那可能会奏效。无论如何,根本没有理由在 Python 中使用线程。Python 线程主要用于使阻塞 I/O 不会阻塞您的程序,而不是用于多个 CPU 内核的利用。

如果您想真正使用并行处理并编写您的节点,就好像它们真的是分开的并且只使用消息交换,您可以使用 Erlang ( http://www.erlang.org/ )。它是一种非常适合执行并行进程并让它们交换消息的函数式语言。Erlang 进程不映射到操作系统线程,您可能会创建数以千计的线程。但是,Erlang 是一种纯粹的函数式语言,如果您从未使用过此类语言,您可能会觉得非常奇怪。而且它也不是很快,所以,像 Python 一样,不可能每 5 毫秒处理 1600 个动作,除非动作相当简单。

最后,如果您使用 Python 或 Erlang 无法获得所需的性能,您可能会转向 C 或 C++。但是,仍然不要使用 1600 线程。事实上,只有在线程数不显着超过 CPU 内核数的情况下,使用线程来获得性能才是合理的。在这种情况下,您可能需要一个反应器模式(具有多个反应器线程)(http://en.wikipedia.org/wiki/Reactor_pattern)。boost.asio 库中有一个很好的反应器​​模式实现。这里解释:http ://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio/

于 2013-09-30T10:44:25.307 回答
0

这里有一些随机的想法:

我在 Java 中有数百个像这样工作的线程做得相当好;它可以用正确的语言来完成。(但我没有在 Python 中尝试过。)

在任何语言中,您都可以在一个线程中运行主节点代码;让它连续循环,在每个循环中运行每个主控的代码。但是,您将失去多核的好处。另一方面,你也会失去多线程的问题。(比如说,你可以有 4 个这样的线程,利用内核,但让多线程头痛又回来了。它也会降低线程开销,但是会出现阻塞......)

我遇到的一个大问题是线程相互阻塞。让 100 个线程同时在同一个对象上调用同一个方法,而无需相互等待,这需要一些思考甚至研究。我发现我的多线程程序一开始经常只使用 25% 的 4 核 CPU,即使在运行时也是如此。这可能是您运行缓慢的原因之一。

不要让您的从节点重复发送数据。主节点应该响应数据进来而活跃起来,或者有某种方式存储它直到它们活跃起来,或者某种组合。

拥有比内核更多的线程确实是值得的。一旦你有两个线程,它们就可以互相阻塞(如果它们共享任何数据,它们也会阻塞)。如果您要运行不会阻塞的代码,则希望在其自己的线程中运行它,这样它就不会等待确实阻塞的代码解除阻塞并完成。我发现一旦我有了几个线程,它们就开始疯狂地增加——因此我的数百个线程程序。尽管我的才华横溢,即使有 100 个线程在一个地方阻塞,还有很多其他线程可以让内核保持忙碌!

于 2013-09-30T19:46:42.250 回答