Python中的多进程可以用于模拟随时间演化的图吗?

3 投票
1 回答
47 浏览
提问于 2025-04-14 16:15

我在使用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') 时也同样有效,所以你应该可以在几乎任何操作系统上使用它。

撰写回答