[Python] mpi4py deadlock with scipy.minimize

Discussão em 'Python' iniciado por Stack, Junho 2, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to do something similar as described in Parallelize a function call with mpi4py

    But there are some things there that make me skeptical of the provided answer. Additionally, I have a class implementation that makes things a little different. Here is some "reduced" code to demonstrate the main logic:

    from scipy.optimize import minimize
    from mpi4py import MPI
    import numpy as np

    class Solver():
    def __init__(self, SampleTimes, InitialArray):
    self.comm = MPI.COMM_WORLD
    self.rank = self.comm.Get_rank()
    self.size = self.comm.Get_size()

    self.SampleTimes = SampleTimes
    self.InitialArray = InitialArray

    self.Finished = False


    def f(x_):
    return <some scalar result>

    def Objective(self, x):

    self.x = self.comm.bcast(x if self.rank == 0 else None, root=0)

    tstep_select = np.array_split(self.SampleTimes, self.size)[self.rank]

    local_results = []
    for t in tstep_select:
    result = self.f(self.x) # Some function of x
    local_results.append( (t, result) )

    all_results = self.comm.gather(local_results, root=0)

    if self.rank==0:
    all_results = [item for sublist in all_results for item in sublist]
    all_results = np.array(all_results)
    all_results = all_results[all_results[:,0].argsort()]

    scalar = np.trapz(all_results[:,1], all_results[:,0])

    return -scalar

    def Maximize(self,):

    if self.rank == 0:
    self.Max = minimize(self.Objective, self.InitialArray)
    self.Finished = self.comm.bcast(True, root=0)
    return self.Max

    else:
    while not self.Finished:
    self.Objective(None)


    if __name__=='__main__':
    t_eval = np.linspace(0, 100, 100)
    Instance = Solver(SampleTimes=t_eval)
    print(Instance.Maximize())


    So I understand that I need to only call the minimizer on rank 0. Additionally, I need to engage the rank!=0 workers to evaluate Objective. This is the intent of the if/else in the Maximize method.

    As I understand, I can pass None to Objective for rank!=0 because self.x will be set based on the broadcast from rank 0. I am wondering if the issue has something to do with the fact that scipy's minimize will expect a single value from each evaluation of Objective but, as-written, Objective will be returning None on all rank!=0 (on the other hand, the minimizer is only executed on rank 0 so I feel like this is potentially a non-issue).

    Continue reading...

Compartilhe esta Página