【问题标题】:How to IPC with the parent process when creating child processes in a loop (Ruby)在循环中创建子进程时如何与父进程进行IPC(Ruby)
【发布时间】:2015-12-06 15:42:10
【问题描述】:

我有以下代码 sn-p(我正在尝试做的事情的简化表示 - 训练轮)。 sleep(2) 将代表我真实代码中的一些网络操作:

arr = []

5.times do |i|
     rd, wr = IO.pipe
     fork do
         sleep(2) # I'm still waiting for the sleep to happen on each process ... not good, there is no parallelism here
         rd.close
         arr[i] = i
         Marshal.dump(arr, wr)
     end
     wr.close
     result = rd.read
     arr = Marshal.load(result)
end

# Process.waitall
p arr

问:是否有可能以某种方式在循环中创建新进程,将结果传回但不等待每次迭代。我很生疏,对 IPC 不太了解/记得很多……尤其是在 Ruby 中。

  • 实际结果是等待时间2s*5 = 10s
  • 预计总共约 2 秒(sleep() 的异步处理)

所以,一个很好的评论可以澄清事情,解释理论会有很大帮助。谢谢。

【问题讨论】:

    标签: ruby pipe ipc


    【解决方案1】:

    在您的循环中,您等待每个子进程将其结果写入管道,然后再开始下一次迭代。

    最简单的解决方法是将管道的读取端保存在一个数组中,并且在循环完成并且您已经启动所有子进程之前不要read其中任何一个:

    arr = []
    # array to store the IOs
    pipes = []
    
    5.times do |i|
      rd, wr = IO.pipe
      fork do
        sleep(2)
        rd.close
        # Note only returning the value of i here, not the whole array
        Marshal.dump(i, wr)
      end
    
      wr.close
      #store the IO for later
      pipes[i] = rd
    end
    
    # Now all child processes are started, we can read the results in turn
    # Remember each child is returng i, not the whole array
    pipes.each_with_index do |rd, i|
        arr[i] = Marshal.load(rd.read)
    end
    

    如果不同子进程的等待/网络时间变量的更复杂的解决方案可能是查看select,这样您就可以从首先准备好的管道中读取。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-02
      • 1970-01-01
      相关资源
      最近更新 更多