在循环中创建子进程时如何与父进程进行 IPC (Ruby)
How to IPC with the parent process when creating child processes in a loop (Ruby)
我有以下代码片段(我正在尝试做的事情的简化表示 - 训练轮)。 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
- 预计总计 ~2s(sleep() 的异步处理)
所以一个很好的评论澄清事情,解释理论会有很大帮助。谢谢
在您的循环中,您等待每个子进程在开始下一次迭代之前将其结果写入管道。
最简单的解决方法是将管道的读取端保存在一个数组中,并且在循环完成并且您已启动所有子进程之前不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
如果不同子进程变量的 wait/network 次可能是查看 select
的更复杂的解决方案,因此您可以从首先准备好的管道中读取。
我有以下代码片段(我正在尝试做的事情的简化表示 - 训练轮)。 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
- 预计总计 ~2s(sleep() 的异步处理)
所以一个很好的评论澄清事情,解释理论会有很大帮助。谢谢
在您的循环中,您等待每个子进程在开始下一次迭代之前将其结果写入管道。
最简单的解决方法是将管道的读取端保存在一个数组中,并且在循环完成并且您已启动所有子进程之前不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
如果不同子进程变量的 wait/network 次可能是查看 select
的更复杂的解决方案,因此您可以从首先准备好的管道中读取。