分叉和IPC机制

4
我正在编写一个单线程、内存密集型的概念验证应用程序。该应用程序本身不会操作太多的数据,主要是加载几个GB的数据,然后进行一些数据分析。
我不想通过多线程实现并发管理,也不想实现锁(例如互斥锁、自旋锁等),所以这次我决定使用老式的fork()。在Linux中,由于内存采用了CoW技术,因此可以使用简单的并行单线程逻辑来高效地分析相同的数据集,而无需显式复制它们(再次强调,这是一个概念验证)。
现在我生成了子进程,使用fork()非常容易为子任务(在这种情况下是子进程)设置输入参数,但然后我必须将结果传递回主进程。有时这些结果达到数十GB。我所知道的所有IPC机制如下:
- 管道/套接字(然后使用epoll等待以单线程方式获取结果) - 混合管道/共享内存(使用与共享内存相关的epoll等待结果,然后从共享内存中复制数据到父进程,销毁共享内存)
除了明显的“多线程”之外,我真的希望利用这个概念验证的CoW和单线程多进程架构。你有什么想法吗?
谢谢!
2个回答

2
经过一些实验,我得出的结论如下:
  1. 当子进程需要与父进程通信时,在生成这样的子进程之前,我会创建一个共享内存段(即16 MB)
  2. 如果需要协调,就在sh mem段中创建一个信号量
  3. 然后,在分叉时,我使用非阻塞套接字pipe2让子进程可以在某些数据可用时通知父进程
  4. 然后将管道fd用于epoll
  5. epoll作为Level Triggered使用,以便在子进程真正快速发送数据时可以交替请求
  6. 如果结构体是pod,则直接使用共享内存段进行数据通信,否则使用简单的template<...>二进制读/写函数。
我认为这是一个很好的解决方案。
干杯

0

你也可以使用普通文件。

父进程可以等待子进程(分析内存中的数据,然后将其结果写入文件),一旦子进程退出,您必须能够从文件中读取数据。正如您所提到的,输入参数不是问题,您只需在其中一个输入参数中指定要写入的文件名即可。这样,除了等待子进程的退出状态之外,不需要任何锁定。

我想知道如果每个子进程返回10GB的大数据,那么最好使用普通文件,因为您将有足够的时间处理每个子进程的结果。但是这10GB的数据是否在子进程之间共享?如果是这种情况,您会更喜欢使用锁定,因此我假设它不是。


我正在使用子进程和父进程之间的共享内存(以二进制形式进行序列化/反序列化),这是最快的IPC。我可以在短时间内传输大量数据,目前运行良好。我认为使用文件系统只会减慢事情的速度,并可能依赖于磁盘。而且它无法解决读取文件时阻塞父进程太长时间的问题。 - Emanuele
你是对的,共享内存最快。 文件读写很慢。 但除此之外,您可以像使用共享内存一样使用文件。 阻塞父进程并不是必要的,我不确定即使使用共享内存,您如何通知父进程数据可用性。 无论如何,我猜您已经找到了解决方案。 - achillez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接