/*-------------------------------------------------------------------------------------*/ /* NOMAD - Nonlinear Optimization by Mesh Adaptive Direct search - version 3.6.1 */ /* */ /* Copyright (C) 2001-2012 Mark Abramson - the Boeing Company, Seattle */ /* Charles Audet - Ecole Polytechnique, Montreal */ /* Gilles Couture - Ecole Polytechnique, Montreal */ /* John Dennis - Rice University, Houston */ /* Sebastien Le Digabel - Ecole Polytechnique, Montreal */ /* Christophe Tribes - Ecole Polytechnique, Montreal */ /* */ /* funded in part by AFOSR and Exxon Mobil */ /* */ /* Author: Sebastien Le Digabel */ /* */ /* Contact information: */ /* Ecole Polytechnique de Montreal - GERAD */ /* C.P. 6079, Succ. Centre-ville, Montreal (Quebec) H3C 3A7 Canada */ /* e-mail: nomad@gerad.ca */ /* phone : 1-514-340-6053 #6928 */ /* fax : 1-514-340-5665 */ /* */ /* This program is free software: you can redistribute it and/or modify it under the */ /* terms of the GNU Lesser General Public License as published by the Free Software */ /* Foundation, either version 3 of the License, or (at your option) any later */ /* version. */ /* */ /* This program is distributed in the hope that it will be useful, but WITHOUT ANY */ /* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A */ /* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License along */ /* with this program. If not, see . */ /* */ /* You can find information on the NOMAD software at www.gerad.ca/nomad */ /*-------------------------------------------------------------------------------------*/ /** \file Slave.hpp \brief Slave process (headers) \author Sebastien Le Digabel \date 2010-04-22 \see Slave.cpp */ #ifndef __SLAVE__ #define __SLAVE__ #include "Evaluator.hpp" namespace NOMAD { /// Slave process for the parallel version. class Slave : private NOMAD::Uncopyable { private: static int _rank; /// Process rank. static int _np; /// Number of processes. static int _data_sent; /// Stats on the sent data. static int _data_rcvd; /// Stats on the received data. static bool _are_running; ///< \c true if the slaves are running. static bool _stop_ok; ///< \c true if the slaves stopped without error. const NOMAD::Parameters * _p; ///< Parameters (may be NULL). NOMAD::Evaluator * _ev; ///< Evaluator (may be NULL). /// Initializations. void init ( void ) const; /// Force quit. /** - Called by pressing Ctrl-C. - Does nothing: the slave will be stopped by the master. \param signalValue Signal value -- \b IN. */ static void force_quit ( int signalValue ) {} public: /// Constructor. /** \param p Parameters -- \b IN. \param ev A pointer to an evaluator -- \b IN. */ Slave ( const NOMAD::Parameters & p , NOMAD::Evaluator * ev ) : _p ( &p ) , _ev ( ev ) { init(); } /// Destructor. virtual ~Slave ( void ) {} /// Run the slave code. void run ( void ) const; /// Access to the stat \c _data_sent. /** \return The stat \c _data_sent. */ static int get_data_sent ( void ) { return Slave::_data_sent; } /// Access to the stat \c _data_rcvd. /** \return The stat \c _data_rcvd. */ static int get_data_rcvd ( void ) { return Slave::_data_rcvd; } /// Access to the process rank. /** \return The process rank. */ static int get_rank ( void ); /// Access to the number of processes. /** \return The number of processes. */ static int get_nb_processes ( void ); /// Check if the slaves are running. /** \return A boolean equal to \c true if the slaves are running. */ static bool are_running ( void ) { return _are_running; } /// Check if the current slave is the master. /** \return A boolean equal to \c true if the current slave is the master. */ static bool is_master ( void ) { return ( Slave::get_rank() == 0 ); } /// Initialize all the slaves. /** \param out Display -- \b IN. */ static void init_slaves ( const NOMAD::Display & out ); /// Stop all the slaves. /** \param out Display -- \b IN. */ static void stop_slaves ( const NOMAD::Display & out ); #ifdef USE_MPI private: /// Receive and evaluate a point from the master. /** \param count_eval Flag indicating if the evaluation has to be counted or not -- \b OUT. \return A pointer to the point. */ NOMAD::Eval_Point * eval_point ( bool & count_eval ) const; /// Send an evaluation result to the master. /** \param x The evaluation point -- \b IN. \param count_eval Flag indicating if the evaluation has to be counted or not -- \b IN. */ void send_eval_result ( const NOMAD::Eval_Point * x , bool count_eval ) const; /// Send data. /** \param buf Data to send -- \b IN. \param count Data quantity -- \b IN. \param datatype Data type -- \b IN. \param dest Destination -- \b IN. \param ready_send Flag equal to \c true if \c Rsend is used instead of \c Send -- \b IN. */ static void send_data ( const void * buf , int count , MPI_Datatype datatype , int dest , bool ready_send ); /// Receive data. /** \param buf Data to receive -- \b OUT. \param count Data quantity -- \b IN. \param datatype Data type -- \b IN. \param source Source (may be \c MPI_ANY_SOURCE) -- \b IN. \param req Pointer to a MPI request (may be \c NULL) -- \b IN/OUT. \return The source. */ static int receive_data ( void * buf , int count , MPI_Datatype datatype , int source , MPI_Request * req ); /// Wait for a MPI request. /** \param req The request -- \b IN/OUT. */ static void wait_request ( MPI_Request & req ); public: /// Send an evaluation point to a slave. /** \param x A pointer to the evaluation point to send -- \b IN. \param slave_rank Destination -- \b IN. \param h_max Maximal feasibility value \c h_max -- \b IN. */ void send_eval_point ( const NOMAD::Eval_Point * x , int slave_rank , const NOMAD::Double & h_max ) const; /// Receive an evaluation result from a slave. /** \param slave_rank Source -- \b IN. \param x A pointer to the evaluation point received -- \b OUT. \param eval_ok Flag indicating if the evaluation succeeded -- \b OUT. \param count_eval Flag indicating if the evaluation has to be counted or not -- \b OUT. */ void receive_eval_result ( int slave_rank , NOMAD::Eval_Point * x , bool & eval_ok , bool & count_eval ) const; /// Receive a signal from a slave. /** \param signal The signal -- \b OUT. \return The source. */ static int receive_signal ( char & signal ) { return Slave::receive_data ( &signal , 1 , MPI_CHAR , MPI_ANY_SOURCE , NULL ); } /// Send a signal to a slave. /** \param signal The signal -- \b IN. \param slave_rank Destination -- \b IN. */ static void send_signal ( char signal , int slave_rank ) { Slave::send_data ( &signal , 1 , MPI_CHAR , slave_rank , true ); } #endif }; } #endif