与子进程通信的最快方式
Posted
技术标签:
【中文标题】与子进程通信的最快方式【英文标题】:Fastest way to communicate with subprocess 【发布时间】:2016-07-15 08:26:34 【问题描述】:我有一个父进程,它产生几个子进程来执行一些 CPU 密集型工作。对于每一批工作,父进程需要向子进程发送几个 100MB 的数据(作为一个块),完成后,它必须接收大约相同数量的数据(再次作为一个块)。 父进程和子进程是不同的应用程序,甚至是不同的语言(主要是 Python 和 C++),但如果我有任何 C/C++ 解决方案,我可以根据需要编写 Python 包装器。
我认为最简单的方法是使用管道。这有很多优点,例如主要是跨平台的、简单且灵活,而且我甚至可以在以后扩展我的代码而无需太多工作来通过网络进行通信。
但是,现在我正在分析整个应用程序,我发现通信中有一些明显的开销,我想知道是否有更快的方法。我的案例(科学研究)并不真正需要跨平台,如果它可以在 Ubuntu >=12 左右运行就足够了(尽管 MacOSX 也很好)。原则上,我认为将一大块数据复制到管道中并在另一端读取它不应该比设置一些共享内存并执行memcpy
花费更多的时间。我错了吗?或者您预计性能会差多少?
分析本身很复杂,我并没有真正可靠和准确的数据,只有线索(因为这都是一个相当复杂的系统)。我想知道我现在应该把时间花在哪里。试图获得更准确的分析数据?尝试实现一些共享内存解决方案,看看它改进了多少?或者是其他东西?我还考虑过在库中包装和编译子进程应用程序并将其链接到主进程,从而避免与另一个进程通信——在这种情况下,我只需要一个memcpy
。
*** 上有很多相关的问题,但我还没有真正看到不同通信方法的性能比较。
【问题讨论】:
可能是共享内存。如果可能,不要 memcpy 进入共享内存 - 将数据放在共享内存中开始。 @immibis:考虑到我仍然需要 memcpy,在两端。它比通过管道复制二进制数据快多少? 理论上即时,没有复制,数据在两个进程中同时存在。那么什么都不做的速度有多快呢? 我不知道管道有多快。 您是否正在从接收端的管道中积极阅读?我知道管道对可以输入多少数据有一些限制,但现在不记得了。 【参考方案1】:好的,所以我编写了一个小型基准测试工具here,它通过共享内存或管道复制一些数据(~200MB)10 次。
MacOSX 在我的 MacBook 上的结果:
Shared memory:
24.34 real 18.49 user 5.96 sys
Pipe:
36.16 real 20.45 user 17.79 sys
所以,首先我们看到共享内存明显更快。请注意,如果我复制较小的数据块(~10MB),我几乎看不到总时间的差异。
第二个明显的区别是在内核中花费的时间。预计管道需要更多的内核时间,因为内核必须处理所有这些读取和写入。但我没想到会这么多。
【讨论】:
以上是关于与子进程通信的最快方式的主要内容,如果未能解决你的问题,请参考以下文章