dme65 / pySOT

Surrogate Optimization Toolbox for Python

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MPI example gets stuck

SanPen opened this issue · comments

Hi, I am trying the examples provided and the MPI example gets stuck, not error, just not advancing nor calling the objective function. I have tried the same code under windows 10 (after installing MPI from microsoft) and under Ubuntu 18.

I wonder is this is a bug, of if I am missing something.

The code is this:

"""
.. module:: mpiexample_simple_mpi
  :synopsis: Simple MPI example
.. moduleauthor:: David Eriksson <dme65@cornell.edu>
"""

from pySOT.experimental_design import SymmetricLatinHypercube
from pySOT.strategy import SRBFStrategy
from pySOT.surrogate import RBFInterpolant, CubicKernel, LinearTail
from pySOT.optimization_problems import OptimizationProblem

from poap.mpiserve import MPIController, MPISimpleWorker
import numpy as np
import os.path
import logging

# Try to import mpi4py
try:
    from mpi4py import MPI
except Exception as err:
    print("ERROR: You need mpi4py to use the POAP MPI controller.")
    exit()


class Ackley(OptimizationProblem):
    """
    Ackley function

    .. math::
        f(x_1,\\ldots,x_n) = -20\\exp\\left( -0.2 \\sqrt{\\frac{1}{n} \
        \\sum_{j=1}^n x_j^2} \\right) -\\exp \\left( \\frac{1}{n} \
        \\sum{j=1}^n \\cos(2 \\pi x_j) \\right) + 20 - e

    subject to

    .. math::
        -15 \\leq x_i \\leq 20

    Global optimum: :math:`f(0,0,...,0)=0`

    :ivar dim: Number of dimensions
    :ivar lb: Lower variable bounds
    :ivar ub: Upper variable bounds
    :ivar int_var: Integer variables
    :ivar cont_var: Continuous variables
    :ivar min: Global minimum value
    :ivar minimum: Global minimizer
    :ivar info: String with problem info
    """
    def __init__(self, dim=10):
        self.dim = dim
        self.min = 0
        self.minimum = np.zeros(dim)
        self.lb = -15 * np.ones(dim)
        self.ub = 20 * np.ones(dim)
        self.int_var = np.array([])
        self.cont_var = np.arange(0, dim)
        self.info = str(dim) + "-dimensional Ackley function \n" + "Global optimum: f(0,0,...,0) = 0"

    def eval(self, x):
        """
        Evaluate the Ackley function  at x

        :param x: Data point
        :type x: numpy.array
        :return: Value at x
        :rtype: float
        """
        print('eval!')
        self.__check_input__(x)
        d = float(self.dim)
        return -20.0 * np.exp(-0.2*np.sqrt(np.sum(x**2) / d)) - np.exp(np.sum(np.cos(2.0*np.pi*x)) / d) + 20 + np.exp(1)


def main_worker(objfunction):
    MPISimpleWorker(objfunction).run()


def main_master(opt_prob, num_workers):
    if not os.path.exists("./logfiles"):
        os.makedirs("logfiles")
    if os.path.exists("./logfiles/mpiexample_mpi.log"):
        os.remove("./logfiles/mpiexample_mpi.log")
    logging.basicConfig(filename="./logfiles/mpiexample_mpi.log",
                        level=logging.INFO)

    max_evals = 500

    rbf = RBFInterpolant(dim=opt_prob.dim,
                         kernel=CubicKernel(),
                         tail=LinearTail(opt_prob.dim))

    slhd = SymmetricLatinHypercube(dim=opt_prob.dim,
                                   num_pts=2*(opt_prob.dim+1))

    # Create a strategy and a controller
    strategy = SRBFStrategy(max_evals=max_evals,
                            opt_prob=opt_prob,
                            exp_design=slhd,
                            surrogate=rbf,
                            asynchronous=True,
                            batch_size=num_workers)
    controller = MPIController(strategy)

    print("Number of workers: {}".format(num_workers))
    print("Maximum number of evaluations: {}".format(max_evals))
    print("Strategy: {}".format(controller.strategy.__class__.__name__))
    print("Experimental design: {}".format(slhd.__class__.__name__))
    print("Surrogate: {}".format(rbf.__class__.__name__))

    print('Running...')
    result = controller.run()
    print('Best value found: {0}'.format(result.value))
    print('Best solution found: {0}\n'.format(np.array_str(result.params[0],
                                                           max_line_width=np.inf,
                                                           precision=5,
                                                           suppress_small=True)))


def mpi_example_simple():

    # Optimization problem
    ackley = Ackley(dim=10)

    # Extract the rank
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    nprocs = comm.Get_size()

    if rank == 0:
        main_master(ackley, nprocs)
    else:
        main_worker(ackley.eval)


if __name__ == '__main__':
    mpi_example_simple()

Do you have a working MPI distribution and are you making the call using mpiexec? The following seems to work fine for me:
mpiexec -n 5 python3 mpiexample_simple_mpi.py

By calling it like that it works!

However, is there another way to call the program?
I'd use this as part of a library that is used in a PyQt GUI application.

I don't know if that is possible. In any case, this question is about mpi4py and not pySOT, so I'm closing for now.