与子进程通信的最快方式
Fastest way to communicate with subprocess
我有一个父进程,它生成多个子进程来执行一些 CPU 密集型工作。对于每批工作,父进程需要向子进程发送几个 100MB 的数据(作为一个单独的块),完成后,它必须接收大约相同数量的数据(再次作为一个单独的块)。
父进程和子进程是不同的应用程序,甚至是不同的语言(主要是 Python 和 C++),但如果我在 C/C++ 中有任何解决方案,我可以根据需要编写一个 Python 包装器.
我认为最简单的方法是使用管道。这有很多优点,例如主要是跨平台的、简单和灵活的,我什至可以在以后扩展我的代码而无需太多工作来通过网络进行通信。
但是,现在我正在分析整个应用程序,我发现通信中有一些明显的开销,我想知道是否有更快的方法。我的案例(科学研究)并不真正需要跨平台,如果它在 Ubuntu >=12 左右工作就足够了(尽管 MacOSX 也不错)。原则上,我认为将一大块数据复制到管道中并在另一端读取它应该不会比设置一些共享内存并执行 memcpy
花费更多时间。我错了吗?或者你期望性能会差多少?
分析本身很复杂,我没有真正可靠和准确的数据,只有线索(因为它是一个相当复杂的系统)。我想知道我现在应该把时间花在哪里。试图获得更准确的分析数据?尝试实施一些共享内存解决方案并查看它改进了多少?。或者是其他东西?我还考虑过在库中包装和编译子进程应用程序并将其链接到主进程,从而避免与另一个进程通信——在这种情况下,我只需要一个 memcpy
.
Whosebug 上有很多相关问题,但我还没有真正看到不同通信方法的性能比较。
好的,所以我写了一个小的基准测试工具 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),我几乎看不到总时间的差异。
第二个显着差异是在内核中花费的时间。预计管道需要更多的内核时间,因为内核必须处理所有这些读取和写入。但是我没想到会那么多。
我有一个父进程,它生成多个子进程来执行一些 CPU 密集型工作。对于每批工作,父进程需要向子进程发送几个 100MB 的数据(作为一个单独的块),完成后,它必须接收大约相同数量的数据(再次作为一个单独的块)。 父进程和子进程是不同的应用程序,甚至是不同的语言(主要是 Python 和 C++),但如果我在 C/C++ 中有任何解决方案,我可以根据需要编写一个 Python 包装器.
我认为最简单的方法是使用管道。这有很多优点,例如主要是跨平台的、简单和灵活的,我什至可以在以后扩展我的代码而无需太多工作来通过网络进行通信。
但是,现在我正在分析整个应用程序,我发现通信中有一些明显的开销,我想知道是否有更快的方法。我的案例(科学研究)并不真正需要跨平台,如果它在 Ubuntu >=12 左右工作就足够了(尽管 MacOSX 也不错)。原则上,我认为将一大块数据复制到管道中并在另一端读取它应该不会比设置一些共享内存并执行 memcpy
花费更多时间。我错了吗?或者你期望性能会差多少?
分析本身很复杂,我没有真正可靠和准确的数据,只有线索(因为它是一个相当复杂的系统)。我想知道我现在应该把时间花在哪里。试图获得更准确的分析数据?尝试实施一些共享内存解决方案并查看它改进了多少?。或者是其他东西?我还考虑过在库中包装和编译子进程应用程序并将其链接到主进程,从而避免与另一个进程通信——在这种情况下,我只需要一个 memcpy
.
Whosebug 上有很多相关问题,但我还没有真正看到不同通信方法的性能比较。
好的,所以我写了一个小的基准测试工具 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),我几乎看不到总时间的差异。
第二个显着差异是在内核中花费的时间。预计管道需要更多的内核时间,因为内核必须处理所有这些读取和写入。但是我没想到会那么多。