使用进程和线程的mpi4py

2 投票
1 回答
3946 浏览
提问于 2025-04-16 15:19

你好,这个问题比较具体,希望StackOverflow能涵盖所有编程语言,而不仅仅是JavaScript或HTML。

我正在用MPICH2(一个流行的消息传递接口)写一个多程序。我的程序是用Python写的,所以我使用了MPI4Py这个Python库。MPI最适合没有共享内存的情况,因此不太适合多核编程。为了充分利用我5个节点集群中的4个核心,我还使用了线程。不过,我发现使用线程反而让我的模拟变得更慢。我的程序有几万行代码,不能全部贴出来,但这里有一段导致问题的代码。

from threading import Thread
...
threadIndeces=[[0,10],[11,20],[21,30],[31,40]] #subset for each thread
for indeces in treadIndeces:
  t=Thread(target=foo,args=(indeces,))
  t.start()

另外,我确保在后面会把线程合并。如果我不使用线程,直接用所有的索引调用foo,速度大约快10到15倍。当我记录多线程版本的时间时,创建线程的那一行t=Thread(target=foo,args=(indeces,))大约花了0.05秒,合并线程也差不多是0.05秒,但t.start()的调用竟然要花0.2秒。

那么,start()是一个耗时的调用吗?我应该改变我的方法吗?我考虑过保持一个线程池,而不是每次迭代都创建新的线程,但似乎t=Thread(target=foo,args=(indeces,))并不是导致变慢的原因。

另外,如果有人想知道foo的复杂性,这里有一个函数,它在每次迭代中会被调用i次,针对indeces(非离散时间):

def HD_training_firing_rate(HD_cell):
    """During training, the firing rate is governed by the difference between the 
       current heading direction and the preferred heading direction. This is made
       to resemble a Gaussian distribution
    """
    global fabs
    global exp
    global direction

    #loop over twice due to concurrent CW and CCW HD training
    for c in [0,1]:
        d=direction[c]
        dp=HD_cell.dp  #directional preferance
        s_d=20.0  #standard deviation
        s_i=min(fabs(dp-d),360-fabs(dp-d)) #circular deviation from preferred dir.

        HD_cell.r[c]=exp(-s_i*s_i/(2*s_d*s_d))  #normal distribution

1 个回答

5

如果你需要使用线程,Python可能不是最好的选择,因为它有一个叫做全局解释器锁的东西,这个锁会阻止真正的并发执行。你可以看看Dave Beazly的一个让人不安的演讲

你可能更适合直接运行20个进程,这样可以让你的4个核心和5个节点都忙起来,然后用MPI来处理所有的通信。

在大型计算机上,Python的开销比较大——如果你真的想要使用线程和消息传递的方式,可能需要考虑用C或C++(或者我敢说Fortran?)来实现。

撰写回答