【发布时间】:2020-06-24 01:04:21
【问题描述】:
我正在使用一个我无法控制的外部程序,它有时会调用我可以指定的子进程,传递一些参数并在完成后检查其退出状态。
我希望这个程序调用的子进程是一个执行一些计算的 python 3 脚本 使用一个构建起来非常昂贵且非常大的对象。因为对象的构造非常昂贵,所以我不想每次外部程序调用脚本时都构造它,而且因为它需要相当多的空间,所以每次都将它腌制到磁盘并加载它很慢。
我目前对此的解决方案是有两个进程,一个进程构造对象并在请求时执行计算,另一个进程由外部程序调用,其唯一真正目标是通过以下方式与第一个进程通信一个套接字并要求它执行其任务。
第一个进程的代码大致如下:
# process1.py, performs calculations
import socket
import pickle
def do_expensive_calculations(large_object, data):
# some expensive calculations
return value
class LargeAndSlow:
def __init__(self):
# some code
if __name__ == '__main__':
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.bind('ADDRESS')
s.listen(1)
large_object = LargeAndSlow()
while True:
(conn, address) = s.accept()
data = pickle.loads(conn.recv(4096))
value = do_expensive_calculations(large_object, data)
conn.send(pickle.dumps(value))
第二个(外部程序调用的那个)就像这样:
# process2.py
import sys
import socket
import pickle
def value_is_correct(value):
# check if value is correct
return is_correct
if __name__ == '__main__':
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect('ADDRESS')
s.send(pickle.dumps(sys.argv))
value = pickle.loads(s.recv(4096))
if value_is_correct(value):
s.close()
sys.exit(0)
else:
s.close()
sys.exit(1)
然而,这个解决方案实际上比每次都构造对象要慢,我怀疑这是由于多个 python 进程同时运行并通过 UNIX 套接字进行通信的开销(但是,我可能是错的,也许我只是以一种非常低效的方式编码)。
是否有更快、更有效的解决方案来解决这个问题?
【问题讨论】:
-
如果对象是可序列化的,您可以将其转储到一个文件中,并在外部程序调用的过程中
mmap()它。这样,您的 IPC 就更少了。如果该文件被频繁访问并且有空闲内存,一个不错的操作系统会将文件保存在内存中。
标签: python python-3.x multiprocessing pthreads ram