Python中的多进程可以用于模拟随时间演化的图吗?
我在使用Julia进行多线程编程时,成功模拟了一个值不断变化的图,现在我想在Python中实现类似的功能。
因为在某个时刻t
,一个节点的值可能会依赖于在t-1
时刻其他节点的值,所以每个时间步结束时,所有线程的结果必须一致。不过,在每个时间步内,线程可以根据上一个时间步共享的信息独立更新各自的内容。我不太清楚Julia内部是怎么处理的,但多线程在这个场景下效果很好。我在Python中实现了一个比较粗糙的方法(见下文),但每次在每个时间步创建和销毁线程的速度显然很慢,而且似乎不允许重复使用线程。在我深入学习Python中的多线程细节之前,或许有人能给我一些建议,看看这种做法是否可行。用Python的多进程(或者其他库)来并行更新图形是否合理呢?
import multiprocessing
T = 1000
for t in range(T):
thrds = []
for n,node in enumerate(net.nodes):
thrds.append(
multiprocessing.Process(
target=update_node,
args=(n,node,t)
)
)
for thrd in thrds:
thrd.start()
for thrd in thrds:
thrd.join()
del(thrds)
1 个回答
0
因为在某个时刻的节点值可能会依赖于前一个时刻其他节点的值,所以在每个时间步骤结束时,所有线程必须保持一致。
实现这个目标最简单的方法是使用一个叫做 multiprocessing.Barrier
的对象,这样可以让所有线程同步进行。
当你创建一个 Barrier
对象时,需要指定线程的数量 N
,然后这些线程就可以调用 barrier.wait()
。前面 N-1
个调用者会被阻塞,直到第 N
个线程调用 wait()
。然后,所有的 wait()
调用都会返回,屏障会自动重置,准备好再次使用。
你可以试着运行这个代码,看看我说的是什么意思:
#!/usr/bin/env python3
import multiprocessing as mp
import time
NWORKERS=3
NTHREADS=NWORKERS+1 # main thread + worker threads
NGENERATIONS=3
def work_fun(barrier, tag):
for generation in range(NGENERATIONS):
barrier.wait()
print(f"I am worker{tag}, generation={generation}", flush=True)
if __name__ == "__main__":
ctx = mp.get_context('spawn')
barrier = ctx.Barrier(NTHREADS)
procs = []
for i in range(NWORKERS):
proc = ctx.Process(target=work_fun, args=(barrier, i))
proc.start()
procs.append(proc)
for i in range(NGENERATIONS):
time.sleep(1)
barrier.wait()
for i in range(NWORKERS):
procs[i].join()
print("Nighty Night!")
它在使用 ctx=mp.get_context('fork')
时也同样有效,所以你应该可以在几乎任何操作系统上使用它。