具有共享库和内存持久性的Python多处理

时间:2014-03-20 10:41:48

标签: python process shared-libraries multiprocessing

我使用Python作为驱动程序来运行数千个数值模拟。由于每个模拟的初始化过程是相同的,我可以通过执行(耗时的)初始化过程来节省时间,在内存中备份向量的初始状态,并且对于每个后续模拟,只需恢复这些向量。

一个小的工作示例是:

from ctypes import cdll

try:
    lib = cdll.LoadLibrary('shared_lib.so')
    print lib.set_to_backup() # this tells the program to save the initial state
    print lib.simulate("cmd.txt") # initializes, backs up state, saves an internal variable -backed_up- to true and simulates
    print lib.simulate("cmd2.txt") # sees the internal state -backed_up- equal to true and skips initialisation, restores from memory and simulates
except:
    import traceback
    traceback.print_exc()

这非常有效,我可以在不重新初始化的情况下运行多个模拟(cmd1,cmd2,...)。

现在,我想使用多处理并行化此过程。因此,每个进程应该加载一次库并运行初始化,保存和模拟的第一个模拟。每个后续模拟都应重新加载初始状态并进行模拟。一个过程的示例:

from ctypes import cdll
from multiprocessing import Process

try:
    lib = cdll.LoadLibrary('shared_lib.so')
    print lib.set_to_backup() # this tells the program to save the initial state
    p1 = Process(target=lib.simulate, args=("cmd.txt",)) # initializes, backs up state, saves an internal variable -backed_up- to true and simulates
    p1.start()
    p1.join()
    print p1.exitcode

    p2 = Process(target=lib.simulate, args=("cmd2.txt",)) # (should) see the internal state -backed_up- equal to true and skips initialisation, restores from memory and simulates
    p2.start()
    p2.join()
    print p2.exitcode
except:
    import traceback
    traceback.print_exc()

第一个过程正确地完成了工作(我可以在跟踪中看到它)。第二个进程没有在lib中看到-backed_up-变量并重新初始化所有内容。

我试过没有声明一个新进程,但只是重新运行p1.start()来重新启动相同的进程但它失败了(断言self._popen为None,'无法启动进程两次')。

-backed_up-是lib中的全局变量,应该在调用lib.simulate之间保留在内存中(就像在第一个示例中那样)。

我运行Linux Debian 7并使用python 2.7.3。

任何人都知道如何让这项工作好吗?

1 个答案:

答案 0 :(得分:0)

我设法让它使用队列工作。答案受到了很大的启发 - > https://stackoverflow.com/a/6672593/801468

import multiprocessing
from ctypes import cdll

num_procs = 2

def worker():
    lib = cdll.LoadLibrary('shared_lib.so')
    print lib.set_to_backup()
    for DST in iter( q.get, None ):
        print 'treating: ', DST
        print lib.simulate(DST)
        q.task_done()
    q.task_done()

q = multiprocessing.JoinableQueue()
procs = []
for i in range(num_procs):
    procs.append( multiprocessing.Process(target=worker) )
    procs[-1].daemon = True
    procs[-1].start()

list_of_DST = ["cmd1.txt", "cmd2.txt"]
for DST in list_of_DST:
    q.put(DST)

q.join()

for p in procs:
    q.put( None )

q.join()

for p in procs:
    p.join()

print "Finished everything...."
print "Active children:", multiprocessing.active_children()