manual merge in favor of the CMakeLists of the fusion branch
This commit is contained in:
commit
291bb7ce14
967 changed files with 137738 additions and 846 deletions
5
eo/.gitignore
vendored
Normal file
5
eo/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
*.swp
|
||||
debug/
|
||||
release/
|
||||
*CMakeFiles*
|
||||
*Makefile
|
||||
12
eo/AUTHORS
12
eo/AUTHORS
|
|
@ -1,12 +0,0 @@
|
|||
Pedro Angel Castillo Valdivieso
|
||||
Juan Julian Merelo Guervos
|
||||
Victor Manuel Rivas Santos
|
||||
Gustavo Romero Lopez
|
||||
Maarten Keijzer
|
||||
Marc Schoenauer
|
||||
Jeroen Eggermont
|
||||
Jochen K<>pper
|
||||
Thomas Legrand
|
||||
Clive Canape
|
||||
Johann Dréo <johann.dreo@thalesgroup.com>
|
||||
Caner Candan <caner.candan@thalesgroup.com>
|
||||
|
|
@ -1,116 +1,53 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
######################################################################################
|
||||
### 0) If you want to set your variables in eo-conf.cmake and avoid the cmd line
|
||||
######################################################################################
|
||||
|
||||
#INCLUDE(eo-conf.cmake OPTIONAL)
|
||||
|
||||
######################################################################################
|
||||
|
||||
|
||||
######################################################################################
|
||||
### 1) Main project config
|
||||
######################################################################################
|
||||
|
||||
# set the project namef and other variables
|
||||
PROJECT(EO)
|
||||
|
||||
# CMake > 2.8 is needed, because of the FindOpenMP feature
|
||||
#cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
#SET(PROJECT_VERSION_MAJOR 1)
|
||||
#SET(PROJECT_VERSION_MINOR 1)
|
||||
#SET(PROJECT_VERSION_PATCH 1)
|
||||
SET(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" CACHE STRING "Package version" FORCE)
|
||||
SET(VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}${PROJECT_VERSION_MISC}" CACHE STRING "Global version" FORCE)
|
||||
SET(GLOBAL_VERSION "${VERSION}")
|
||||
|
||||
SET(PACKAGE_BUGREPORT "eodev-help@sourceforge.net" CACHE STRING "Package bug report" FORCE)
|
||||
SET(PACKAGE_NAME "Evolving Objects" CACHE STRING "Package name" FORCE)
|
||||
SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}"CACHE STRING "Package string full name" FORCE)
|
||||
SET(PACKAGE_TARNAME "eo" CACHE STRING "Package tar name" FORCE)
|
||||
|
||||
# regular expression checking
|
||||
INCLUDE_REGULAR_EXPRESSION("^.*$" "^$")
|
||||
|
||||
# set a language for the entire project.
|
||||
ENABLE_LANGUAGE(CXX)
|
||||
ENABLE_LANGUAGE(C)
|
||||
|
||||
######################################################################################
|
||||
|
||||
|
||||
#####################################################################################
|
||||
### 2) Include required modules / configuration files
|
||||
### Include required modules / configuration files
|
||||
#####################################################################################
|
||||
|
||||
FIND_PACKAGE(OpenMP)
|
||||
IF(OPENMP_FOUND)
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
|
||||
ENDIF()
|
||||
# For eo::mpi
|
||||
enable_language(C)
|
||||
|
||||
INCLUDE(CMakeBackwardCompatibilityCXX)
|
||||
# For openmp parallel
|
||||
if(ENABLE_OPENMP)
|
||||
find_package(OpenMP)
|
||||
if(OPENMP_FOUND)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
|
||||
else()
|
||||
message( "ERROR: You asked for OpenMP but it has not been found." )
|
||||
set(IS_FATAL 1)
|
||||
endif(OPENMP_FOUND)
|
||||
endif(ENABLE_OPENMP)
|
||||
|
||||
INCLUDE(FindDoxygen)
|
||||
if(ENABLE_GNUPLOT)
|
||||
include(FindGnuplot)
|
||||
endif(ENABLE_GNUPLOT)
|
||||
|
||||
INCLUDE(FindGnuplot)
|
||||
# set a special flag if the environment is windows (should do the same in a config.g file)
|
||||
if (WIN32)
|
||||
add_definitions(-D_WINDOWS=1)
|
||||
endif (WIN32)
|
||||
|
||||
INCLUDE(CheckLibraryExists)
|
||||
|
||||
IF(UNIX)
|
||||
INCLUDE(ConfigureChecks.cmake)
|
||||
ENDIF(UNIX)
|
||||
|
||||
INCLUDE(Dart OPTIONNAL)
|
||||
#####################################################################################
|
||||
### Include required modules / configuration files
|
||||
#####################################################################################
|
||||
|
||||
# now create config headers
|
||||
CONFIGURE_FILE(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
# now create config install_symlink script file
|
||||
CONFIGURE_FILE(install_symlink.py.cmake ${CMAKE_CURRENT_BINARY_DIR}/install_symlink.py)
|
||||
|
||||
# now create PKGBUILD file for archlinux package manager
|
||||
CONFIGURE_FILE(PKGBUILD.cmake ${CMAKE_CURRENT_BINARY_DIR}/PKGBUILD)
|
||||
|
||||
# Set a special flag if the environment is windows (should do the same in a config.g file)
|
||||
IF (WIN32)
|
||||
ADD_DEFINITIONS(-D_WINDOWS=1)
|
||||
ENDIF (WIN32)
|
||||
|
||||
######################################################################################
|
||||
|
||||
######################################################################################
|
||||
configure_file(install_symlink.py.cmake ${CMAKE_CURRENT_BINARY_DIR}/install_symlink.py)
|
||||
|
||||
|
||||
######################################################################################
|
||||
### compilation of examples?
|
||||
######################################################################################
|
||||
|
||||
#SET(ENABLE_CMAKE_EXAMPLE TRUE CACHE BOOL "Enable copy of benchs and parameters file?")
|
||||
|
||||
### Include subdirectories
|
||||
######################################################################################
|
||||
|
||||
|
||||
######################################################################################
|
||||
### 4) Test config
|
||||
######################################################################################
|
||||
|
||||
#IF (ENABLE_CMAKE_TESTING)
|
||||
# ENABLE_TESTING()
|
||||
#ENDIF (ENABLE_CMAKE_TESTING)
|
||||
|
||||
######################################################################################
|
||||
|
||||
|
||||
######################################################################################
|
||||
### 5) Where must cmake go now ?
|
||||
######################################################################################
|
||||
|
||||
#ADD_SUBDIRECTORY(app)
|
||||
ADD_SUBDIRECTORY(doc)
|
||||
ADD_SUBDIRECTORY(src)
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(src)
|
||||
|
||||
if(ENABLE_CMAKE_TESTING)
|
||||
add_subdirectory(test)
|
||||
|
|
@ -118,31 +55,9 @@ endif(ENABLE_CMAKE_TESTING)
|
|||
|
||||
if(ENABLE_CMAKE_EXAMPLE)
|
||||
if(${CMAKE_VERBOSE_MAKEFILE})
|
||||
message("EO Examples :")
|
||||
message("EO examples:")
|
||||
endif(${CMAKE_VERBOSE_MAKEFILE})
|
||||
add_subdirectory(tutorial)
|
||||
#add_subdirectory(app) # FIXME must be updated
|
||||
endif(ENABLE_CMAKE_EXAMPLE)
|
||||
|
||||
######################################################################################
|
||||
|
||||
|
||||
######################################################################################
|
||||
### 6) Install pkg-config config file for EO
|
||||
######################################################################################
|
||||
|
||||
SET(PCPREFIX "/usr")
|
||||
SET(PCFLAGS "-leoutils -leo -les -lga -lcma -lgcov")
|
||||
SET(PCINCLUDEDIR "eo")
|
||||
CONFIGURE_FILE(pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/eo.pc)
|
||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/eo.pc DESTINATION ${LIB}/pkgconfig COMPONENT headers)
|
||||
|
||||
######################################################################################
|
||||
|
||||
|
||||
######################################################################################
|
||||
### 7) Include packaging
|
||||
######################################################################################
|
||||
|
||||
#INCLUDE(Packaging.cmake)
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
In order to create a new release from the current repository, perform the
|
||||
following steps:
|
||||
|
||||
- If necessary, create a branch named "eo_x.y.z"
|
||||
- Set version number in eo-conf.cmake
|
||||
- Check/update NEWS file, set release date and version in NEWS.
|
||||
- use the "archive_current.sh" script to create the source archive
|
||||
- Build the packages
|
||||
- Put source archive and packages files at SourceForge
|
||||
- Post news on SourceForge project-page
|
||||
- Send announcement to mailing lists
|
||||
- Bump version number to next "x.y.z-edge" in eo-conf.cmake
|
||||
|
||||
|
||||
When reaching stable versions:
|
||||
- prepare a message with the following template:
|
||||
-----8<-----
|
||||
A new version of the "Evolving Objects" framework is available.
|
||||
|
||||
EO is a template-based, C++ evolutionary computation library which
|
||||
helps you to write your own stochastic optimization algorithms
|
||||
insanely fast.
|
||||
|
||||
Learn more about EO on the official website:
|
||||
http://eodev.sourceforge.net/
|
||||
|
||||
You will find the release x.y.z at the following address:
|
||||
https://sourceforge.net/projects/eodev/files/eo/
|
||||
|
||||
Here is a summary of the change log:
|
||||
- XXXXX
|
||||
- and more…
|
||||
|
||||
Do not hesitate to submit the bugs you will face:
|
||||
https://sourceforge.net/apps/trac/eodev/wiki/WikiStart
|
||||
|
||||
Happy evolutionary hacking.
|
||||
-----8<-----
|
||||
- Post the message to:
|
||||
- EO news https://sourceforge.net/news/?group_id=9775
|
||||
- EO mailing list: eodev-main@lists.sourceforge.net
|
||||
- ParadisEO mailing list: paradiseo-users@lists.gforge.inria.fr
|
||||
- EC-digest maling list: ec-digest-l@listserv.gmu.edu
|
||||
- JET mailing list: jet@inria.fr
|
||||
|
||||
37
eo/NEWS
37
eo/NEWS
|
|
@ -1,4 +1,29 @@
|
|||
* current version
|
||||
* current release:
|
||||
|
||||
* release 1.3.1 (2012-07-27)
|
||||
- the eo::mpi modules is no longer dependent from boost::mpi
|
||||
- parallel multi-start example
|
||||
- bugfix: an error is now thrown when accessing best_element of an empty population
|
||||
|
||||
* release 1.3.0 (2012-07-24)
|
||||
- features:
|
||||
- delete the deprecated code parts (was marked as deprecated in the release 1.1)
|
||||
- eoSignal: a class to handle signal with eoCheckpoint instances
|
||||
- eoDetSingleBitFlip: bit flip mutation that changes exactly k bits while checking for duplicate
|
||||
- eoFunctorStat: a wrapper to turn any stand-alone function and into an eoStat
|
||||
- generilazed the output of an eoState: now you can change the format, comes with defaults formatting (latex and json)
|
||||
- eoWrongParamTypeException: a new exception to handle cases where a wrong template is given to eoParser::valueOf
|
||||
- added a getParam method to the eoParser, that raise an exception if the parameter has not been declared
|
||||
- eoParserLogger features are now included in the default eoParser
|
||||
- build system:
|
||||
- improvements of the build architecture
|
||||
- create PKGBUILD file for archlinux package manager
|
||||
- a FindEO module for CMake
|
||||
- bugfixes:
|
||||
- fixed regression with gcc 4.7
|
||||
- fixed compilation issues in Microsoft Visual C++, related to time measurement
|
||||
- added several asserts accross the framework (note: asserts are included only in debug mode)
|
||||
- lot of small bugfixes :-)
|
||||
|
||||
* release 1.2 (16. May. 2011)
|
||||
- fixed the incremental allocation issue in variation operators which were
|
||||
|
|
@ -20,11 +45,11 @@
|
|||
- GCC 4.3 compatibility
|
||||
- new versatile log system with several nested verbose levels
|
||||
- classes using intern verbose parameters marked as deprecated, please update your code accordingly if you use one of the following files:
|
||||
eo/src/eoCombinedInit.h
|
||||
eo/src/eoGenContinue.h
|
||||
eo/src/eoProportionalCombinedOp.h
|
||||
eo/src/utils/eoData.h
|
||||
eo/src/utils/eoStdoutMonitor.h
|
||||
eo/src/eoCombinedInit.h
|
||||
eo/src/eoGenContinue.h
|
||||
eo/src/eoProportionalCombinedOp.h
|
||||
eo/src/utils/eoData.h
|
||||
eo/src/utils/eoStdoutMonitor.h
|
||||
- an evaluator that throw an exception if a maximum eval numbers has been reached, independently of the number of generations
|
||||
- new monitor that can write on any ostream
|
||||
- new continuator that can catch POSIX system user signals
|
||||
|
|
|
|||
|
|
@ -2,30 +2,30 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries (mandatory: before 3) )
|
||||
### 2) specify where cmake can find the libraries (mandatory: before 3) )
|
||||
######################################################################################
|
||||
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
link_directories(${EO_BIN_DIR}/lib)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your target(s): just an executable here
|
||||
### 3) define your target(s): just an executable here
|
||||
######################################################################################
|
||||
|
||||
SET (GPROP_SOURCES gprop.cpp)
|
||||
set (GPROP_SOURCES gprop.cpp)
|
||||
|
||||
# especially for Visual Studio
|
||||
IF(NOT WIN32 OR CYGWIN)
|
||||
ADD_EXECUTABLE(gprop ${GPROP_SOURCES})
|
||||
ADD_DEPENDENCIES(gprop eo eoutils)
|
||||
if(NOT WIN32 OR CYGWIN)
|
||||
add_executable(gprop ${GPROP_SOURCES})
|
||||
add_dependencies(gprop eo eoutils)
|
||||
|
||||
TARGET_LINK_LIBRARIES(gprop eo eoutils)
|
||||
target_link_libraries(gprop eo eoutils)
|
||||
|
||||
SET(GPROP_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(gprop PROPERTIES VERSION "${GPROP_VERSION}")
|
||||
ENDIF(NOT WIN32 OR CYGWIN)
|
||||
set(GPROP_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(gprop PROPERTIES VERSION "${GPROP_VERSION}")
|
||||
endif(NOT WIN32 OR CYGWIN)
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
|
|
@ -2,37 +2,37 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries (mandatory: before 3) )
|
||||
### 2) specify where cmake can find the libraries (mandatory: before 3) )
|
||||
######################################################################################
|
||||
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
link_directories(${EO_BIN_DIR}/lib)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your target(s): just an executable here
|
||||
### 3) define your target(s): just an executable here
|
||||
######################################################################################
|
||||
|
||||
SET (GPSYMREG_SOURCES main.cpp)
|
||||
set (GPSYMREG_SOURCES main.cpp)
|
||||
|
||||
# no matter what is the OS, hopefully
|
||||
ADD_EXECUTABLE(gpsymreg ${GPSYMREG_SOURCES})
|
||||
add_executable(gpsymreg ${GPSYMREG_SOURCES})
|
||||
|
||||
ADD_DEPENDENCIES(gpsymreg eo eoutils)
|
||||
add_dependencies(gpsymreg eo eoutils)
|
||||
|
||||
######################################################################################
|
||||
### 4) Optionnal: define your target(s)'s version: no effect for windows
|
||||
### 4) optionnal: define your target(s)'s version: no effect for windows
|
||||
######################################################################################
|
||||
|
||||
SET(GPSYMREG_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(gpsymreg PROPERTIES VERSION "${GPSYMREG_VERSION}")
|
||||
set(GPSYMREG_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(gpsymreg PROPERTIES VERSION "${GPSYMREG_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
### 5) Link the librairies for your target(s)
|
||||
### 5) link the librairies for your target(s)
|
||||
######################################################################################
|
||||
|
||||
TARGET_LINK_LIBRARIES(gpsymreg eo eoutils)
|
||||
target_link_libraries(gpsymreg eo eoutils)
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${EO_SRC_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries (mandatory: before 3) )
|
||||
######################################################################################
|
||||
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
LINK_DIRECTORIES(${EO_BIN_DIR}/${LIB})
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your target(s): just an executable here
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@
|
|||
##########################################################################################
|
||||
IF (DOXYGEN_FOUND)
|
||||
|
||||
SET(DOC_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH "EO documentation directory")
|
||||
SET(EO_DOC_CONFIG_FILE "eo.cfg" CACHE PATH "EO documentation configuration file")
|
||||
SET(EO_DOC_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "EO documentation directory" FORCE)
|
||||
SET(EO_DOC_CONFIG_FILE "eo.doxyfile" CACHE INTERNAL "EO documentation configuration file")
|
||||
|
||||
# Copy necessary doc files
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/index.h ${DOC_DIR}/index.h COPYONLY)
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/index.h ${EO_DOC_DIR}/index.h COPYONLY)
|
||||
FILE(GLOB header_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.htm*)
|
||||
FILE(GLOB pdf_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.pdf)
|
||||
FILE(GLOB jpg_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.jpg)
|
||||
FOREACH (file ${header_files} ${pdf_files} ${jpg_files})
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${file} ${DOC_DIR}/${file} COPYONLY)
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${file} ${EO_DOC_DIR}/${file} COPYONLY)
|
||||
ENDFOREACH (file)
|
||||
|
||||
# define the doc target
|
||||
|
|
|
|||
|
|
@ -31,8 +31,16 @@ def uninstall():
|
|||
print('All symlinks have been removed.')
|
||||
|
||||
def install():
|
||||
for dirname in DATA['dirs']: os.mkdir(dirname)
|
||||
for src, dst in DATA['links']: os.symlink(src, dst)
|
||||
for dirname in DATA['dirs']:
|
||||
try:
|
||||
os.makedirs(dirname)
|
||||
except(os.error):
|
||||
pass
|
||||
for src, dst in DATA['links']:
|
||||
try:
|
||||
os.symlink(src, dst)
|
||||
except:
|
||||
pass
|
||||
print('All symlinks have been installed.')
|
||||
|
||||
def data():
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Define the eo target
|
||||
######################################################################################
|
||||
|
||||
SET(EO_LIB_OUTPUT_PATH ${EO_BINARY_DIR}/lib)
|
||||
SET(LIBRARY_OUTPUT_PATH ${EO_LIB_OUTPUT_PATH})
|
||||
set(EO_LIB_OUTPUT_PATH ${EO_BIN_DIR}/lib)
|
||||
set(LIBRARY_OUTPUT_PATH ${EO_LIB_OUTPUT_PATH})
|
||||
|
||||
SET(EO_SOURCES
|
||||
set(EO_SOURCES
|
||||
eoFunctorStore.cpp
|
||||
eoPersistent.cpp
|
||||
eoPrintable.cpp
|
||||
|
|
@ -20,35 +20,36 @@ SET(EO_SOURCES
|
|||
eoSIGContinue.cpp
|
||||
)
|
||||
|
||||
ADD_LIBRARY(eo STATIC ${EO_SOURCES})
|
||||
INSTALL(TARGETS eo ARCHIVE DESTINATION ${LIB} COMPONENT libraries)
|
||||
|
||||
FILE(GLOB HDRS *.h eo)
|
||||
INSTALL(FILES ${HDRS} DESTINATION include${INSTALL_SUB_DIR}/eo COMPONENT headers)
|
||||
|
||||
INSTALL(DIRECTORY do es ga gp other utils
|
||||
DESTINATION include${INSTALL_SUB_DIR}/eo
|
||||
COMPONENT headers
|
||||
FILES_MATCHING PATTERN "*.h" PATTERN "checkpointing" PATTERN external_eo
|
||||
)
|
||||
add_library(eo STATIC ${EO_SOURCES})
|
||||
|
||||
######################################################################################
|
||||
### 3) Optionnal: define your target(s)'s version: no effect for windows
|
||||
######################################################################################
|
||||
|
||||
SET(EO_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(eo PROPERTIES VERSION "${EO_VERSION}")
|
||||
set(EO_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(eo PROPERTIES VERSION "${EO_VERSION}")
|
||||
|
||||
install(TARGETS eo ARCHIVE DESTINATION local/${LIB} COMPONENT libraries)
|
||||
|
||||
file(GLOB HDRS *.h eo)
|
||||
install(FILES ${HDRS} DESTINATION local/include${INSTALL_SUB_DIR}/eo COMPONENT headers)
|
||||
|
||||
install(DIRECTORY do es ga gp other utils
|
||||
DESTINATION local/include${INSTALL_SUB_DIR}/eo
|
||||
COMPONENT headers
|
||||
FILES_MATCHING PATTERN "*.h" PATTERN "checkpointing" PATTERN external_eo
|
||||
)
|
||||
|
||||
######################################################################################
|
||||
### 4) Where must cmake go now ?
|
||||
######################################################################################
|
||||
|
||||
ADD_SUBDIRECTORY(es)
|
||||
ADD_SUBDIRECTORY(ga)
|
||||
ADD_SUBDIRECTORY(utils)
|
||||
add_subdirectory(es)
|
||||
add_subdirectory(ga)
|
||||
add_subdirectory(utils)
|
||||
|
||||
IF(ENABLE_PYEO)
|
||||
ADD_SUBDIRECTORY(pyeo)
|
||||
ENDIF(ENABLE_PYEO)
|
||||
if(ENABLE_PYEO)
|
||||
add_subdirectory(pyeo)
|
||||
endif(ENABLE_PYEO)
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
|
||||
mak@dhi.dk
|
||||
mak@dhi.dk
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -31,7 +31,10 @@
|
|||
#include <utils/eoLogger.h>
|
||||
#include <eoFunctor.h>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
Applies a unary function to a std::vector of things.
|
||||
|
|
@ -48,29 +51,41 @@ void apply(eoUF<EOT&, void>& _proc, std::vector<EOT>& _pop)
|
|||
double t1 = 0;
|
||||
|
||||
if ( eo::parallel.enableResults() )
|
||||
{
|
||||
t1 = omp_get_wtime();
|
||||
}
|
||||
{
|
||||
t1 = omp_get_wtime();
|
||||
}
|
||||
|
||||
if (!eo::parallel.isDynamic())
|
||||
{
|
||||
{
|
||||
#pragma omp parallel for if(eo::parallel.isEnabled()) //default(none) shared(_proc, _pop, size)
|
||||
for (size_t i = 0; i < size; ++i) { _proc(_pop[i]); }
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
//Visual Studio supports only OpenMP version 2.0 in which
|
||||
//an index variable must be of a signed integral type
|
||||
for (long long i = 0; i < size; ++i) { _proc(_pop[i]); }
|
||||
#else // _MSC_VER
|
||||
for (size_t i = 0; i < size; ++i) { _proc(_pop[i]); }
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
#pragma omp parallel for schedule(dynamic) if(eo::parallel.isEnabled())
|
||||
//doesnot work with gcc 4.1.2
|
||||
//default(none) shared(_proc, _pop, size)
|
||||
for (size_t i = 0; i < size; ++i) { _proc(_pop[i]); }
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
//Visual Studio supports only OpenMP version 2.0 in which
|
||||
//an index variable must be of a signed integral type
|
||||
for (long long i = 0; i < size; ++i) { _proc(_pop[i]); }
|
||||
#else // _MSC_VER
|
||||
//doesnot work with gcc 4.1.2
|
||||
//default(none) shared(_proc, _pop, size)
|
||||
for (size_t i = 0; i < size; ++i) { _proc(_pop[i]); }
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( eo::parallel.enableResults() )
|
||||
{
|
||||
double t2 = omp_get_wtime();
|
||||
eoLogger log;
|
||||
log << eo::file(eo::parallel.prefix()) << t2 - t1 << ' ';
|
||||
}
|
||||
{
|
||||
double t2 = omp_get_wtime();
|
||||
eoLogger log;
|
||||
log << eo::file(eo::parallel.prefix()) << t2 - t1 << ' ';
|
||||
}
|
||||
|
||||
#else // _OPENMP
|
||||
|
||||
|
|
@ -94,7 +109,7 @@ void apply(eoUF<EOT&, void>& _proc, std::vector<EOT>& _pop)
|
|||
// //default(none) shared(_proc, _pop, size)
|
||||
// for (size_t i = 0; i < size; ++i)
|
||||
// {
|
||||
// _proc(_pop[i]);
|
||||
// _proc(_pop[i]);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
|
@ -112,7 +127,7 @@ void apply(eoUF<EOT&, void>& _proc, std::vector<EOT>& _pop)
|
|||
// //default(none) shared(_proc, _pop, size)
|
||||
// for (size_t i = 0; i < size; ++i)
|
||||
// {
|
||||
// _proc(_pop[i]);
|
||||
// _proc(_pop[i]);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ eoCheckPoint<EOT>& do_make_checkpoint(eoParser& _parser, eoState& _state, eoValu
|
|||
// The Stdout monitor will print parameters to the screen ...
|
||||
if ( needStdoutMonitor )
|
||||
{
|
||||
eoStdoutMonitor *monitor = new eoStdoutMonitor(false);
|
||||
eoStdoutMonitor *monitor = new eoStdoutMonitor(/*false FIXME remove this deprecated prototype*/);
|
||||
_state.storeFunctor(monitor);
|
||||
|
||||
// when called by the checkpoint (i.e. at every generation)
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ eoCheckPoint<EOT>& do_make_checkpoint(eoParser& _parser, eoState& _state, eoEval
|
|||
// The Stdout monitor will print parameters to the screen ...
|
||||
if ( needStdoutMonitor )
|
||||
{
|
||||
eoStdoutMonitor *monitor = new eoStdoutMonitor(false);
|
||||
eoStdoutMonitor *monitor = new eoStdoutMonitor(/*false FIXME remove this deprecated prototype*/);
|
||||
_state.storeFunctor(monitor);
|
||||
|
||||
// when called by the checkpoint (i.e. at every generation)
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ eoCheckPoint<EOT>& do_make_checkpoint_assembled(eoParser& _parser, eoState& _sta
|
|||
|
||||
// STDOUT
|
||||
// ------
|
||||
eoStdoutMonitor *monitor = new eoStdoutMonitor(false);
|
||||
eoStdoutMonitor *monitor = new eoStdoutMonitor(/*false FIXME remove this deprecated prototype*/);
|
||||
_state.storeFunctor(monitor);
|
||||
checkpoint->add(*monitor);
|
||||
monitor->add(*generationCounter);
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@
|
|||
#include <eoEvalCounterThrowException.h>
|
||||
#include <eoEvalTimeThrowException.h>
|
||||
#include <eoEvalUserTimeThrowException.h>
|
||||
#include <eoEvalKeepBest.h>
|
||||
|
||||
// Continuators - all include eoContinue.h
|
||||
#include <eoCombinedContinue.h>
|
||||
|
|
@ -102,6 +103,7 @@
|
|||
#include <eoSharingSelect.h>
|
||||
// Embedding truncation selection
|
||||
#include <eoTruncatedSelectOne.h>
|
||||
#include <eoRankMuSelect.h>
|
||||
|
||||
// the batch selection - from an eoSelectOne
|
||||
#include <eoSelectPerc.h>
|
||||
|
|
@ -141,6 +143,9 @@
|
|||
#include <utils/eoRealVectorBounds.h> // includes eoRealBounds.h
|
||||
#include <utils/eoIntBounds.h> // no eoIntVectorBounds
|
||||
|
||||
// Serialization stuff
|
||||
#include <serial/eoSerial.h>
|
||||
|
||||
// aliens
|
||||
#include <other/external_eo>
|
||||
#include <eoCounter.h>
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
/* FIXME remove in next release
|
||||
/// Ctor - for historical reasons ... should disspear some day
|
||||
eoCombinedContinue( eoContinue<EOT>& _cont1, eoContinue<EOT>& _cont2)
|
||||
: eoContinue<EOT>(), std::vector<eoContinue<EOT>* >()
|
||||
|
|
@ -68,12 +69,14 @@ public:
|
|||
this->push_back(&_cont1);
|
||||
this->push_back(&_cont2);
|
||||
}
|
||||
*/
|
||||
|
||||
void add(eoContinue<EOT> & _cont)
|
||||
{
|
||||
this->push_back(&_cont);
|
||||
}
|
||||
|
||||
/* FIXME remove in next release
|
||||
void removeLast(void)
|
||||
{
|
||||
#ifndef DEPRECATED_MESSAGES
|
||||
|
|
@ -82,6 +85,7 @@ public:
|
|||
|
||||
this->pop_back();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/** Returns false when one of the embedded continuators say so (logical and)
|
||||
|
|
|
|||
|
|
@ -44,11 +44,13 @@ public:
|
|||
rates.push_back(_rate);
|
||||
}
|
||||
|
||||
/* FIXME remove in next release
|
||||
void add(eoInit<EOT> & _init, double _rate, bool _verbose)
|
||||
{
|
||||
eo::log << eo::warnings << "WARNING: the use of the verbose parameter in eoCombinedInit::add is deprecated and will be removed in the next release." << std::endl;
|
||||
add( _init, _rate );
|
||||
}
|
||||
*/
|
||||
|
||||
/** The usual method to add objects to the combination
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -67,4 +67,43 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Termination condition with a count condition (totalGenerations). This continuator contains
|
||||
* a count of cycles, which can be retrieved or set.
|
||||
*
|
||||
* @ingroup Continuators
|
||||
* @ingroup Core
|
||||
*/
|
||||
template< class EOT >
|
||||
class eoCountContinue : public eoContinue< EOT >
|
||||
{
|
||||
public:
|
||||
|
||||
eoCountContinue( ) :
|
||||
thisGenerationPlaceholder( 0 ),
|
||||
thisGeneration( thisGenerationPlaceholder )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
eoCountContinue( unsigned long& currentGen ) :
|
||||
thisGenerationPlaceholder( 0 ),
|
||||
thisGeneration( currentGen )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual std::string className( void ) const { return "eoCountContinue"; }
|
||||
|
||||
virtual void reset( )
|
||||
{
|
||||
thisGeneration = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
unsigned long thisGenerationPlaceholder;
|
||||
unsigned long& thisGeneration;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include <math.h>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** eoDetSelect selects many individuals determinisctically
|
||||
/** eoDetSelect selects many individuals deterministically
|
||||
*
|
||||
* @ingroup Selectors
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@
|
|||
#include <eoMergeReduce.h>
|
||||
#include <eoReplacement.h>
|
||||
|
||||
|
||||
|
||||
template <class EOT> class eoIslandsEasyEA ;
|
||||
|
||||
template <class EOT> class eoDistEvalEasyEA ;
|
||||
|
|
@ -102,6 +100,33 @@ template<class EOT> class eoEasyEA: public eoAlgo<EOT>
|
|||
offspring.reserve(_offspringSize); // This line avoids an incremental resize of offsprings.
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ctor allowing to specify which pop eval function we're going to use.
|
||||
*
|
||||
* Ctor taking a breed and merge, an overload of ctor to define an offspring size, and
|
||||
* the pop eval function used. This allows to precise if we would like to use the
|
||||
* parallel evaluation, for instance.
|
||||
*/
|
||||
eoEasyEA(
|
||||
eoContinue<EOT>& _continuator,
|
||||
eoEvalFunc<EOT>& _eval,
|
||||
eoPopEvalFunc<EOT>& _pop_eval,
|
||||
eoBreed<EOT>& _breed,
|
||||
eoReplacement<EOT>& _replace,
|
||||
unsigned _offspringSize
|
||||
) : continuator(_continuator),
|
||||
eval (_eval),
|
||||
loopEval(_eval),
|
||||
popEval(_pop_eval),
|
||||
selectTransform(dummySelect, dummyTransform),
|
||||
breed(_breed),
|
||||
mergeReduce(dummyMerge, dummyReduce),
|
||||
replace(_replace),
|
||||
isFirstCall(true)
|
||||
{
|
||||
offspring.reserve(_offspringSize); // This line avoids an incremental resize of offsprings.
|
||||
}
|
||||
|
||||
/*
|
||||
eoEasyEA(eoContinue <EOT> & _continuator,
|
||||
eoPopEvalFunc <EOT> & _pop_eval,
|
||||
|
|
@ -219,45 +244,44 @@ template<class EOT> class eoEasyEA: public eoAlgo<EOT>
|
|||
/// Apply a few generation of evolution to the population.
|
||||
virtual void operator()(eoPop<EOT>& _pop)
|
||||
{
|
||||
if (isFirstCall)
|
||||
{
|
||||
size_t total_capacity = _pop.capacity() + offspring.capacity();
|
||||
_pop.reserve(total_capacity);
|
||||
offspring.reserve(total_capacity);
|
||||
isFirstCall = false;
|
||||
}
|
||||
|
||||
eoPop<EOT> empty_pop;
|
||||
|
||||
popEval(empty_pop, _pop); // A first eval of pop.
|
||||
|
||||
do
|
||||
if (isFirstCall)
|
||||
{
|
||||
try
|
||||
size_t total_capacity = _pop.capacity() + offspring.capacity();
|
||||
_pop.reserve(total_capacity);
|
||||
offspring.reserve(total_capacity);
|
||||
isFirstCall = false;
|
||||
}
|
||||
|
||||
eoPop<EOT> empty_pop;
|
||||
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
unsigned pSize = _pop.size();
|
||||
offspring.clear(); // new offspring
|
||||
unsigned pSize = _pop.size();
|
||||
|
||||
breed(_pop, offspring);
|
||||
offspring.clear(); // new offspring
|
||||
|
||||
popEval(_pop, offspring); // eval of parents + offspring if necessary
|
||||
breed(_pop, offspring);
|
||||
|
||||
replace(_pop, offspring); // after replace, the new pop. is in _pop
|
||||
popEval(_pop, offspring); // eval of parents + offspring if necessary
|
||||
|
||||
if (pSize > _pop.size())
|
||||
throw std::runtime_error("Population shrinking!");
|
||||
else if (pSize < _pop.size())
|
||||
throw std::runtime_error("Population growing!");
|
||||
replace(_pop, offspring); // after replace, the new pop. is in _pop
|
||||
|
||||
if (pSize > _pop.size())
|
||||
throw std::runtime_error("Population shrinking!");
|
||||
else if (pSize < _pop.size())
|
||||
throw std::runtime_error("Population growing!");
|
||||
}
|
||||
catch (std::exception& e)
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::string s = e.what();
|
||||
s.append( " in eoEasyEA");
|
||||
throw std::runtime_error( s );
|
||||
std::string s = e.what();
|
||||
s.append( " in eoEasyEA");
|
||||
throw std::runtime_error( s );
|
||||
}
|
||||
}
|
||||
while ( continuator( _pop ) );
|
||||
while ( continuator( _pop ) );
|
||||
}
|
||||
|
||||
protected :
|
||||
|
|
|
|||
134
eo/src/eoEvalDump.h
Normal file
134
eo/src/eoEvalDump.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
|
||||
/*
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
© 2012 Thales group
|
||||
|
||||
Authors:
|
||||
Johann Dreo <johann.dreo@thalesgroup.com>
|
||||
*/
|
||||
|
||||
#ifndef eoEvalDump_H
|
||||
#define eoEvalDump_H
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <eoEvalFunc.h>
|
||||
|
||||
/**
|
||||
Dump an evaluated individual to a given file.
|
||||
|
||||
Note: test if the file could be open only in debug mode
|
||||
If the file cannot be open during the calls, everything will fail in an standard exception.
|
||||
|
||||
The file name should be given at instanciation, if you asked for a single file, it will
|
||||
erase the previously written one and write the new individual in it.
|
||||
|
||||
If you do not ask for a single file, it will create several files,
|
||||
one different each time it found a individual. The filenames have then the form:
|
||||
<filename><count_prefix><count>
|
||||
"<count>" being a integer, incremented by one each time a new file is written down.
|
||||
|
||||
If you asked for a filename="RESULT", by default, the first dump file will be named "RESULT.0".
|
||||
*/
|
||||
template<class EOT>
|
||||
class eoEvalDump : public eoEvalFunc<EOT>
|
||||
{
|
||||
public:
|
||||
//! A constructor for wrapping your own evaluator in a eoEvalDump.
|
||||
eoEvalDump(
|
||||
eoEvalFunc<EOT>& func, std::string filename, bool single_file = false,
|
||||
unsigned int file_count = 0, std::string count_prefix = "."
|
||||
) :
|
||||
_func(func),
|
||||
_filename(filename), _single_file(single_file), _file_count(file_count), _sep(count_prefix),
|
||||
_of()
|
||||
{}
|
||||
|
||||
//! A constructor without an eval func, the eoEvalDump will thus just write to the file, without evaluating
|
||||
eoEvalDump(
|
||||
std::string filename, bool single_file = false,
|
||||
unsigned int file_count = 0, std::string count_prefix = "."
|
||||
) :
|
||||
_dummy_eval(), _func(_dummy_eval),
|
||||
_filename(filename), _single_file(single_file), _file_count(file_count), _sep(count_prefix),
|
||||
_of()
|
||||
{}
|
||||
|
||||
virtual void operator()(EOT& sol)
|
||||
{
|
||||
_func( sol );
|
||||
dump(sol);
|
||||
}
|
||||
|
||||
unsigned int file_count() { return _file_count; }
|
||||
|
||||
protected:
|
||||
|
||||
// FIXME on x86-64, when called inside a ofstream::open, this function call returns a corrupted string !??
|
||||
/*
|
||||
const char * filename()
|
||||
{
|
||||
if( _single_file ) {
|
||||
return _filename.c_str();
|
||||
|
||||
} else {
|
||||
std::ostringstream afilename;
|
||||
afilename << _filename << _sep << _file_count;
|
||||
return afilename.str().c_str();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void dump( EOT & sol )
|
||||
{
|
||||
if( _single_file ) {
|
||||
// explicitely erase the file before writing in it
|
||||
_of.open( _filename.c_str(), std::ios_base::out | std::ios_base::trunc );
|
||||
|
||||
} else {
|
||||
std::ostringstream afilename;
|
||||
afilename << _filename << _sep << _file_count;
|
||||
_of.open( afilename.str().c_str() /* NOTE : defaults to : , std::ios_base::out | std::ios_base::trunc */);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
if ( !_of.is_open() ) {
|
||||
std::string str = "Error, eoEvalDump could not open: " + _filename;
|
||||
throw std::runtime_error( str );
|
||||
}
|
||||
#endif
|
||||
// here, in release mode, we assume that the file could be opened
|
||||
// thus, we avoid a supplementary test in this costly evaluator
|
||||
_of << sol << std::endl;
|
||||
_of.close();
|
||||
|
||||
_file_count++;
|
||||
}
|
||||
|
||||
protected:
|
||||
class DummyEval : public eoEvalFunc<EOT>
|
||||
{
|
||||
void operator()(EOT& sol) {/*empty*/}
|
||||
};
|
||||
DummyEval _dummy_eval;
|
||||
eoEvalFunc<EOT>& _func;
|
||||
std::string _filename;
|
||||
bool _single_file;
|
||||
unsigned int _file_count;
|
||||
std::string _sep;
|
||||
std::ofstream _of;
|
||||
};
|
||||
|
||||
#endif // eoEvalDump_H
|
||||
153
eo/src/eoEvalKeepBest.h
Normal file
153
eo/src/eoEvalKeepBest.h
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
|
||||
/*
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
© 2012 Thales group
|
||||
|
||||
Authors:
|
||||
Johann Dreo <johann.dreo@thalesgroup.com>
|
||||
*/
|
||||
|
||||
#ifndef eoEvalKeepBest_H
|
||||
#define eoEvalKeepBest_H
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <eoEvalFunc.h>
|
||||
#include <utils/eoParam.h>
|
||||
|
||||
/**
|
||||
Evaluate with the given evaluator and keep the best individual found so far.
|
||||
|
||||
This is useful if you use a non-monotonic algorithm, such as CMA-ES, where the
|
||||
population's best fitness can decrease between two generations. This is
|
||||
sometime necessary and one can't use elitist replacors, as one do not want to
|
||||
introduce a bias in the population.
|
||||
|
||||
The eoEvalBestKeep can be used as a wrapper around a classical evaluator,
|
||||
that keep the best individual it has found since its instanciation.
|
||||
|
||||
To get the best individual, you have to call best_element() on the
|
||||
eoEvalKeepBest itself, and not on the population (or else you would get the
|
||||
best individual found at the last generation).
|
||||
|
||||
Example:
|
||||
|
||||
MyEval true_eval;
|
||||
eoEvalKeepBest<T> wrapped_eval( true_eval );
|
||||
|
||||
// as an interesting side effect, you will get the best individual since
|
||||
// initalization.
|
||||
eoPop<T> pop( my_init );
|
||||
eoPopLoopEval<T> loop_eval( wrapped_eval );
|
||||
|
||||
loop_eval( pop );
|
||||
|
||||
eoEasyEA algo( …, wrapped_eval, … );
|
||||
|
||||
algo(pop);
|
||||
|
||||
// do not use pop.best_element()!
|
||||
std::cout << wrapped_eval.best_element() << std::endl;
|
||||
|
||||
|
||||
You can also inherits from eoEvalKeepBest, if you want to add its interface
|
||||
with your own one. But then, you will have to explicitely call the base class
|
||||
functor:
|
||||
class MyEval : public eoEvalKeepBest<EOT>
|
||||
{
|
||||
MyEval() : eoEvalKeepBest<EOT>() {}
|
||||
virtual void operator()(EOT& sol)
|
||||
{
|
||||
// evaluate sol here
|
||||
// ...
|
||||
|
||||
// keep the best
|
||||
eoEvalKeepBest<EOT>::operator()( sol );
|
||||
};
|
||||
|
||||
@ingroup Evaluation
|
||||
*/
|
||||
template<class EOT> class eoEvalKeepBest : public eoEvalFunc<EOT>, public eoValueParam<EOT>
|
||||
{
|
||||
public :
|
||||
|
||||
/** A constructor for inheritance: if you want to inherit from eoEvalKeepBest.
|
||||
*
|
||||
* Keep in mind that you will have to call eoEvalKeepBest in your own implementation of operator().
|
||||
*
|
||||
* This constructor uses a dummy evaluator.
|
||||
*/
|
||||
eoEvalKeepBest( std::string _name = "VeryBest. " )
|
||||
: eoValueParam<EOT>(EOT(), _name), dummy_eval(), func(dummy_eval), _found(false) {}
|
||||
|
||||
|
||||
/** A constructor for wrapping your own evaluator in a eoEvalKeepBest.
|
||||
*/
|
||||
eoEvalKeepBest(eoEvalFunc<EOT>& _func, std::string _name = "VeryBest. ")
|
||||
: eoValueParam<EOT>(EOT(), _name), dummy_eval(), func(_func), _found(false) {}
|
||||
|
||||
virtual void operator()(EOT& sol)
|
||||
{
|
||||
_found = false;
|
||||
|
||||
func(sol); // evaluate
|
||||
assert( ! sol.invalid() );
|
||||
|
||||
// if there is no best kept
|
||||
if( this->value().invalid() ) {
|
||||
// FIXME replace this test by a reference fitness passed at instanciation
|
||||
// take the first individual as best
|
||||
this->value() = sol;
|
||||
} else {
|
||||
// if sol is better than the kept individual
|
||||
if( sol.fitness() > this->value().fitness() ) {
|
||||
this->value() = sol;
|
||||
_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Return the best individual found so far.
|
||||
EOT best_element()
|
||||
{
|
||||
return this->value();
|
||||
}
|
||||
|
||||
/** Reset the best individual to the given one. If no individual is
|
||||
* provided, the next evaluated one will be taken as a reference.
|
||||
*/
|
||||
void reset( const EOT& new_best = EOT() )
|
||||
{
|
||||
this->value() = new_best;
|
||||
}
|
||||
|
||||
//! Tell if a best individual has been found during the last call
|
||||
bool found() const
|
||||
{
|
||||
return _found;
|
||||
}
|
||||
|
||||
class DummyEval : public eoEvalFunc<EOT>
|
||||
{
|
||||
void operator()(EOT& sol) {/*empty*/}
|
||||
};
|
||||
|
||||
protected :
|
||||
DummyEval dummy_eval;
|
||||
eoEvalFunc<EOT>& func;
|
||||
bool _found;
|
||||
};
|
||||
#endif
|
||||
|
|
@ -21,28 +21,30 @@ Authors:
|
|||
Johann Dréo <johann.dreo@thalesgroup.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __unix__
|
||||
/*#warning "Warning: class 'eoEvalUserTimeThrowException' is only available under UNIX systems (defining 'rusage' in 'sys/resource.h'), contributions for other systems are welcomed."*/
|
||||
#else
|
||||
#if !defined(__unix__) && !defined(_WINDOWS)
|
||||
#warning "Warning: class 'eoEvalUserTimeThrowException' is only available under UNIX (defining 'rusage' in 'sys/resource.h') or Win32 (defining 'GetProcessTimes' in 'WinBase.h') systems, contributions for other systems are welcomed."
|
||||
#else //!defined(__unix__) && !defined(_WINDOWS)
|
||||
|
||||
#ifndef __EOEVALUSERTIMETHROWEXCEPTION_H__
|
||||
#define __EOEVALUSERTIMETHROWEXCEPTION_H__
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include <eoExceptions.h>
|
||||
|
||||
/** Check at each evaluation if a given CPU user time contract has been reached.
|
||||
*
|
||||
* Throw an eoMaxTimeException if the given max time has been reached.
|
||||
* Usefull if you want to end the search independently of generations.
|
||||
* This class uses (almost-)POSIX headers.
|
||||
* This class uses (almost-)POSIX or Win32 headers, depending on the platform.
|
||||
* It uses a computation of the user time used on the CPU. For a wallclock time measure, see eoEvalTimeThrowException
|
||||
*
|
||||
* @ingroup Evaluation
|
||||
*/
|
||||
|
||||
#include <eoExceptions.h>
|
||||
|
||||
#ifdef __unix__
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
template< class EOT >
|
||||
class eoEvalUserTimeThrowException : public eoEvalFuncCounter< EOT >
|
||||
{
|
||||
|
|
@ -59,7 +61,7 @@ public:
|
|||
if( current >= _max ) {
|
||||
throw eoMaxTimeException( current );
|
||||
} else {
|
||||
func(eo);
|
||||
this->func(eo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -69,5 +71,41 @@ protected:
|
|||
struct rusage _usage;
|
||||
};
|
||||
|
||||
#else
|
||||
#ifdef _WINDOWS
|
||||
//here _WINDOWS is defined
|
||||
|
||||
#include <WinBase.h>
|
||||
|
||||
template< class EOT >
|
||||
class eoEvalUserTimeThrowException : public eoEvalFuncCounter< EOT >
|
||||
{
|
||||
public:
|
||||
eoEvalUserTimeThrowException( eoEvalFunc<EOT> & func, const long max ) : eoEvalFuncCounter<EOT>( func, "CPU-user"), _max(max) {}
|
||||
|
||||
virtual void operator() ( EOT & eo )
|
||||
{
|
||||
if( eo.invalid() ) {
|
||||
FILETIME dummy;
|
||||
GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, &dummy, &_usage);
|
||||
|
||||
ULARGE_INTEGER current;
|
||||
current.LowPart = _usage.dwLowDateTime;
|
||||
current.HighPart = _usage.dwHighDateTime;
|
||||
if( current.QuadPart >= _max ) {
|
||||
throw eoMaxTimeException( current.QuadPart );
|
||||
} else {
|
||||
func(eo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
const long _max;
|
||||
FILETIME _usage;
|
||||
};
|
||||
|
||||
#endif // _WINDOWS
|
||||
#endif //__unix__
|
||||
#endif // __EOEVALUSERTIMETHROWEXCEPTION_H__
|
||||
#endif // __UNIX__
|
||||
#endif //!defined(__unix__) && !defined(_WINDOWS)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
#define _eoFunctorStore_h
|
||||
|
||||
#include <vector>
|
||||
#include<algorithm>
|
||||
|
||||
#include "utils/eoLogger.h"
|
||||
|
||||
class eoFunctorBase;
|
||||
|
||||
|
|
@ -52,6 +55,13 @@ public:
|
|||
template <class Functor>
|
||||
Functor& storeFunctor(Functor* r)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
unsigned int existing = std::count( vec.begin(), vec.end(), r );
|
||||
if( existing > 0 ) {
|
||||
eo::log << eo::warnings << "WARNING: you asked eoFunctorStore to store the functor " << r << " "
|
||||
<< existing + 1 << " times, a segmentation fault may occur in the destructor." << std::endl;
|
||||
}
|
||||
#endif
|
||||
// If the compiler complains about the following line,
|
||||
// check if you really are giving it a pointer to an
|
||||
// eoFunctorBase derived object
|
||||
|
|
@ -67,6 +77,7 @@ private :
|
|||
/** no assignment allowed */
|
||||
eoFunctorStore operator=(const eoFunctorStore&);
|
||||
|
||||
protected:
|
||||
std::vector<eoFunctorBase*> vec;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,24 +35,24 @@
|
|||
@ingroup Continuators
|
||||
*/
|
||||
template< class EOT>
|
||||
class eoGenContinue: public eoContinue<EOT>, public eoValueParam<unsigned>
|
||||
class eoGenContinue: public eoCountContinue<EOT>, public eoValueParam<unsigned>
|
||||
{
|
||||
public:
|
||||
|
||||
using eoCountContinue<EOT>::thisGeneration;
|
||||
using eoCountContinue<EOT>::thisGenerationPlaceholder;
|
||||
|
||||
/// Ctor for setting a
|
||||
eoGenContinue( unsigned long _totalGens)
|
||||
: eoValueParam<unsigned>(0, "Generations", "Generations"),
|
||||
repTotalGenerations( _totalGens ),
|
||||
thisGenerationPlaceHolder(0),
|
||||
thisGeneration(thisGenerationPlaceHolder)
|
||||
: eoCountContinue<EOT>( ),
|
||||
eoValueParam<unsigned>(0, "Generations", "Generations"),
|
||||
repTotalGenerations( _totalGens )
|
||||
{};
|
||||
|
||||
/// Ctor for enabling the save/load the no. of generations counted
|
||||
eoGenContinue( unsigned long _totalGens, unsigned long& _currentGen)
|
||||
: eoValueParam<unsigned>(0, "Generations", "Generations"),
|
||||
repTotalGenerations( _totalGens ),
|
||||
thisGenerationPlaceHolder(0),
|
||||
thisGeneration(_currentGen)
|
||||
: eoCountContinue<EOT>( _currentGen ), eoValueParam<unsigned>(0, "Generations", "Generations"),
|
||||
repTotalGenerations( _totalGens )
|
||||
{};
|
||||
|
||||
/** Returns false when a certain number of generations is
|
||||
|
|
@ -77,7 +77,7 @@ public:
|
|||
*/
|
||||
virtual void totalGenerations( unsigned long _tg ) {
|
||||
repTotalGenerations = _tg;
|
||||
thisGeneration = 0;
|
||||
eoCountContinue<EOT>::reset();
|
||||
};
|
||||
|
||||
/** Returns the number of generations to reach*/
|
||||
|
|
@ -86,7 +86,6 @@ public:
|
|||
return repTotalGenerations;
|
||||
};
|
||||
|
||||
|
||||
virtual std::string className(void) const { return "eoGenContinue"; }
|
||||
|
||||
/** Read from a stream
|
||||
|
|
@ -107,8 +106,6 @@ public:
|
|||
|
||||
private:
|
||||
unsigned long repTotalGenerations;
|
||||
unsigned long thisGenerationPlaceHolder;
|
||||
unsigned long& thisGeneration;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class eoMergeReduce : public eoReplacement<EOT>
|
|||
merge(_merge), reduce(_reduce)
|
||||
{}
|
||||
|
||||
void operator()(eoPop<EOT>& _parents, eoPop<EOT>& _offspring)
|
||||
virtual void operator()(eoPop<EOT>& _parents, eoPop<EOT>& _offspring)
|
||||
{
|
||||
merge(_parents, _offspring); // parents untouched, result in offspring
|
||||
reduce(_offspring, _parents.size());
|
||||
|
|
@ -92,6 +92,14 @@ class eoCommaReplacement : public eoMergeReduce<EOT>
|
|||
public :
|
||||
eoCommaReplacement() : eoMergeReduce<EOT>(no_elite, truncate) {}
|
||||
|
||||
virtual void operator()(eoPop<EOT>& _parents, eoPop<EOT>& _offspring)
|
||||
{
|
||||
// There must be more offsprings than parents, or else an exception will be raised
|
||||
assert( _offspring.size() >= _parents.size() );
|
||||
|
||||
eoMergeReduce<EOT>::operator()( _parents, _offspring );
|
||||
}
|
||||
|
||||
private :
|
||||
eoNoElitism<EOT> no_elite;
|
||||
eoTruncate<EOT> truncate;
|
||||
|
|
|
|||
483
eo/src/eoPop.h
483
eo/src/eoPop.h
|
|
@ -4,31 +4,41 @@
|
|||
// eoPop.h
|
||||
// (c) GeNeura Team, 1998
|
||||
/*
|
||||
This library 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 2 of the License, or (at your option) any later version.
|
||||
This library 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 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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.
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
|
||||
*/
|
||||
Authors:
|
||||
todos@geneura.ugr.es, http://geneura.ugr.es
|
||||
jmerelo
|
||||
gustavoromero
|
||||
mac
|
||||
maartenkeijzer
|
||||
kuepper
|
||||
okoenig
|
||||
evomarc
|
||||
Johann Dréo <johann.dreo@thalesgroup.com>
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _EOPOP_H
|
||||
#define _EOPOP_H
|
||||
#ifndef _EOPOP_H_
|
||||
#define _EOPOP_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator> // needed for GCC 3.2
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
|
||||
// EO includes
|
||||
#include <eoOp.h> // for eoInit
|
||||
|
|
@ -54,18 +64,18 @@
|
|||
template<class EOT>
|
||||
class eoPop: public std::vector<EOT>, public eoObject, public eoPersistent
|
||||
{
|
||||
public:
|
||||
public:
|
||||
|
||||
using std::vector<EOT>::size;
|
||||
using std::vector<EOT>::resize;
|
||||
using std::vector<EOT>::operator[];
|
||||
using std::vector<EOT>::begin;
|
||||
using std::vector<EOT>::end;
|
||||
using std::vector<EOT>::size;
|
||||
using std::vector<EOT>::resize;
|
||||
using std::vector<EOT>::operator[];
|
||||
using std::vector<EOT>::begin;
|
||||
using std::vector<EOT>::end;
|
||||
|
||||
typedef typename EOT::Fitness Fitness;
|
||||
typedef typename EOT::Fitness Fitness;
|
||||
#if defined(__CUDACC__)
|
||||
typedef typename std::vector<EOT>::iterator iterator;
|
||||
typedef typename std::vector<EOT>::const_iterator const_iterator;
|
||||
typedef typename std::vector<EOT>::iterator iterator;
|
||||
typedef typename std::vector<EOT>::const_iterator const_iterator;
|
||||
#endif
|
||||
|
||||
/** Default ctor. Creates empty pop
|
||||
|
|
@ -74,266 +84,297 @@ public:
|
|||
|
||||
/** Ctor for the initialization of chromosomes
|
||||
|
||||
@param _popSize total population size
|
||||
@param _chromInit Initialization routine, produces EO's, needs to be an eoInit
|
||||
@param _popSize total population size
|
||||
@param _chromInit Initialization routine, produces EO's, needs to be an eoInit
|
||||
*/
|
||||
eoPop( unsigned _popSize, eoInit<EOT>& _chromInit )
|
||||
:std::vector<EOT>()
|
||||
{
|
||||
resize(_popSize);
|
||||
for ( unsigned i = 0; i < _popSize; i++ )
|
||||
{
|
||||
eoPop( unsigned _popSize, eoInit<EOT>& _chromInit )
|
||||
: std::vector<EOT>()
|
||||
{
|
||||
resize(_popSize);
|
||||
for ( unsigned i = 0; i < _popSize; i++ )
|
||||
{
|
||||
_chromInit(operator[](i));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/** appends random guys at end of pop.
|
||||
Can be used to initialize it pop is empty
|
||||
Can be used to initialize it pop is empty
|
||||
|
||||
@param _newPopSize total population size
|
||||
@param _chromInit Initialization routine, produces EO's, needs to be an eoInit
|
||||
@param _newPopSize total population size
|
||||
@param _chromInit Initialization routine, produces EO's, needs to be an eoInit
|
||||
*/
|
||||
void append( unsigned _newPopSize, eoInit<EOT>& _chromInit )
|
||||
{
|
||||
unsigned oldSize = size();
|
||||
if (_newPopSize < oldSize)
|
||||
void append( unsigned _newPopSize, eoInit<EOT>& _chromInit )
|
||||
{
|
||||
throw std::runtime_error("New size smaller than old size in pop.append");
|
||||
return;
|
||||
unsigned oldSize = size();
|
||||
if (_newPopSize < oldSize)
|
||||
{
|
||||
throw std::runtime_error("New size smaller than old size in pop.append");
|
||||
return;
|
||||
}
|
||||
if (_newPopSize == oldSize)
|
||||
return;
|
||||
resize(_newPopSize); // adjust the size
|
||||
for ( unsigned i = oldSize; i < _newPopSize; i++ )
|
||||
{
|
||||
_chromInit(operator[](i));
|
||||
}
|
||||
}
|
||||
if (_newPopSize == oldSize)
|
||||
return;
|
||||
resize(_newPopSize); // adjust the size
|
||||
for ( unsigned i = oldSize; i < _newPopSize; i++ )
|
||||
|
||||
|
||||
/** Ctor from an std::istream; reads the population from a stream,
|
||||
each element should be in different lines
|
||||
@param _is the stream
|
||||
*/
|
||||
eoPop( std::istream& _is ) :std::vector<EOT>()
|
||||
{
|
||||
_chromInit(operator[](i));
|
||||
readFrom( _is );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Ctor from an std::istream; reads the population from a stream,
|
||||
each element should be in different lines
|
||||
@param _is the stream
|
||||
*/
|
||||
eoPop( std::istream& _is ) :std::vector<EOT>() {
|
||||
readFrom( _is );
|
||||
}
|
||||
|
||||
/** Empty Dtor */
|
||||
/** Empty Dtor */
|
||||
virtual ~eoPop() {}
|
||||
|
||||
|
||||
/// helper struct for getting a pointer
|
||||
struct Ref { const EOT* operator()(const EOT& eot) { return &eot;}};
|
||||
/// helper struct for comparing on pointers
|
||||
struct Cmp {
|
||||
bool operator()(const EOT* a, const EOT* b) const
|
||||
/// helper struct for getting a pointer
|
||||
struct Ref { const EOT* operator()(const EOT& eot) { return &eot;}};
|
||||
|
||||
/// helper struct for comparing on pointers
|
||||
struct Cmp {
|
||||
bool operator()(const EOT* a, const EOT* b) const
|
||||
{ return b->operator<(*a); }
|
||||
};
|
||||
/// helper struct for comparing (EA or PSO)
|
||||
struct Cmp2
|
||||
{
|
||||
bool operator()(const EOT & a,const EOT & b) const
|
||||
};
|
||||
|
||||
/// helper struct for comparing (EA or PSO)
|
||||
struct Cmp2
|
||||
{
|
||||
bool operator()(const EOT & a,const EOT & b) const
|
||||
{
|
||||
return b.operator<(a);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
sort the population. Use this member to sort in order
|
||||
of descending Fitness, so the first individual is the best!
|
||||
*/
|
||||
void sort(void)
|
||||
{
|
||||
std::sort(begin(), end(), Cmp2());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** creates a std::vector<EOT*> pointing to the individuals in descending order */
|
||||
void sort(std::vector<const EOT*>& result) const
|
||||
{
|
||||
result.resize(size());
|
||||
|
||||
/**
|
||||
sort the population. Use this member to sort in order
|
||||
of descending Fitness, so the first individual is the best!
|
||||
*/
|
||||
void sort(void)
|
||||
{
|
||||
std::sort(begin(), end(), Cmp2());
|
||||
}
|
||||
std::transform(begin(), end(), result.begin(), Ref());
|
||||
|
||||
/** creates a std::vector<EOT*> pointing to the individuals in descending order */
|
||||
void sort(std::vector<const EOT*>& result) const
|
||||
{
|
||||
result.resize(size());
|
||||
std::sort(result.begin(), result.end(), Cmp());
|
||||
}
|
||||
|
||||
std::transform(begin(), end(), result.begin(), Ref());
|
||||
|
||||
std::sort(result.begin(), result.end(), Cmp());
|
||||
}
|
||||
/**
|
||||
shuffle the population. Use this member to put the population
|
||||
in random order
|
||||
*/
|
||||
void shuffle(void)
|
||||
{
|
||||
UF_random_generator<unsigned int> gen;
|
||||
std::random_shuffle(begin(), end(), gen);
|
||||
}
|
||||
|
||||
/**
|
||||
shuffle the population. Use this member to put the population
|
||||
in random order
|
||||
*/
|
||||
void shuffle(void)
|
||||
{
|
||||
UF_random_generator<unsigned int> gen;
|
||||
std::random_shuffle(begin(), end(), gen);
|
||||
}
|
||||
|
||||
/** creates a std::vector<EOT*> pointing to the individuals in random order */
|
||||
void shuffle(std::vector<const EOT*>& result) const
|
||||
{
|
||||
result.resize(size());
|
||||
/** creates a std::vector<EOT*> pointing to the individuals in random order */
|
||||
void shuffle(std::vector<const EOT*>& result) const
|
||||
{
|
||||
result.resize(size());
|
||||
|
||||
std::transform(begin(), end(), result.begin(), Ref());
|
||||
std::transform(begin(), end(), result.begin(), Ref());
|
||||
|
||||
UF_random_generator<unsigned int> gen;
|
||||
std::random_shuffle(result.begin(), result.end(), gen);
|
||||
}
|
||||
UF_random_generator<unsigned int> gen;
|
||||
std::random_shuffle(result.begin(), result.end(), gen);
|
||||
}
|
||||
|
||||
/** returns an iterator to the best individual DOES NOT MOVE ANYBODY */
|
||||
|
||||
/** returns an iterator to the best individual DOES NOT MOVE ANYBODY */
|
||||
#if defined(__CUDACC__)
|
||||
eoPop<EOT>::iterator it_best_element()
|
||||
{
|
||||
eoPop<EOT>:: iterator it = std::max_element(begin(), end());
|
||||
eoPop<EOT>::iterator it_best_element()
|
||||
{
|
||||
eoPop<EOT>:: iterator it = std::max_element(begin(), end());
|
||||
#else
|
||||
typename eoPop<EOT>::iterator it_best_element() {
|
||||
typename eoPop<EOT>::iterator it = std::max_element(begin(), end());
|
||||
typename eoPop<EOT>::iterator it_best_element()
|
||||
{
|
||||
assert( this->size() > 0 );
|
||||
typename eoPop<EOT>::iterator it = std::max_element(begin(), end());
|
||||
#endif
|
||||
return it;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
/** returns an iterator to the best individual DOES NOT MOVE ANYBODY */
|
||||
const EOT & best_element() const
|
||||
{
|
||||
|
||||
/** returns an iterator to the best individual DOES NOT MOVE ANYBODY */
|
||||
const EOT & best_element() const
|
||||
{
|
||||
#if defined(__CUDACC__)
|
||||
eoPop<EOT>::const_iterator it = std::max_element(begin(), end());
|
||||
eoPop<EOT>::const_iterator it = std::max_element(begin(), end());
|
||||
#else
|
||||
typename eoPop<EOT>::const_iterator it = std::max_element(begin(), end());
|
||||
typename eoPop<EOT>::const_iterator it = std::max_element(begin(), end());
|
||||
#endif
|
||||
return (*it);
|
||||
}
|
||||
if( it == end() )
|
||||
throw std::runtime_error("eoPop<EOT>: Empty population, when calling best_element().");
|
||||
return (*it);
|
||||
}
|
||||
|
||||
/** returns a const reference to the worse individual DOES NOT MOVE ANYBODY */
|
||||
const EOT & worse_element() const
|
||||
{
|
||||
/** returns a const reference to the worse individual DOES NOT MOVE ANYBODY */
|
||||
const EOT & worse_element() const
|
||||
{
|
||||
#if defined(__CUDACC__)
|
||||
eoPop<EOT>::const_iterator it = std::min_element(begin(), end());
|
||||
eoPop<EOT>::const_iterator it = std::min_element(begin(), end());
|
||||
#else
|
||||
typename eoPop<EOT>::const_iterator it = std::min_element(begin(), end());
|
||||
assert( this->size() > 0 );
|
||||
typename eoPop<EOT>::const_iterator it = std::min_element(begin(), end());
|
||||
#endif
|
||||
return (*it);
|
||||
}
|
||||
return (*it);
|
||||
}
|
||||
|
||||
/** returns an iterator to the worse individual DOES NOT MOVE ANYBODY */
|
||||
|
||||
/** returns an iterator to the worse individual DOES NOT MOVE ANYBODY */
|
||||
#if defined(__CUDACC__)
|
||||
eoPop<EOT>::iterator it_worse_element()
|
||||
{
|
||||
eoPop<EOT>::iterator it = std::min_element(begin(), end());
|
||||
eoPop<EOT>::iterator it_worse_element()
|
||||
{
|
||||
eoPop<EOT>::iterator it = std::min_element(begin(), end());
|
||||
#else
|
||||
typename eoPop<EOT>::iterator it_worse_element()
|
||||
{
|
||||
typename eoPop<EOT>::iterator it = std::min_element(begin(), end());
|
||||
typename eoPop<EOT>::iterator it_worse_element()
|
||||
{
|
||||
assert( this->size() > 0 );
|
||||
typename eoPop<EOT>::iterator it = std::min_element(begin(), end());
|
||||
#endif
|
||||
return it;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
/**
|
||||
slightly faster algorithm than sort to find all individuals that are better
|
||||
than the nth individual. INDIVIDUALS ARE MOVED AROUND in the pop.
|
||||
*/
|
||||
|
||||
/**
|
||||
slightly faster algorithm than sort to find all individuals that are better
|
||||
than the nth individual. INDIVIDUALS ARE MOVED AROUND in the pop.
|
||||
*/
|
||||
#if defined(__CUDACC__)
|
||||
eoPop<EOT>::iterator nth_element(int nth)
|
||||
{
|
||||
eoPop<EOT>::iterator it = begin() + nth;
|
||||
eoPop<EOT>::iterator nth_element(int nth)
|
||||
{
|
||||
eoPop<EOT>::iterator it = begin() + nth;
|
||||
#else
|
||||
typename eoPop<EOT>::iterator nth_element(int nth)
|
||||
{
|
||||
typename eoPop<EOT>::iterator it = begin() + nth;
|
||||
typename eoPop<EOT>::iterator nth_element(int nth)
|
||||
{
|
||||
assert( this->size() > 0 );
|
||||
typename eoPop<EOT>::iterator it = begin() + nth;
|
||||
#endif
|
||||
std::nth_element(begin(), it, end(), std::greater<EOT>());
|
||||
return it;
|
||||
}
|
||||
std::nth_element(begin(), it, end(), std::greater<EOT>());
|
||||
return it;
|
||||
}
|
||||
|
||||
struct GetFitness { Fitness operator()(const EOT& _eo) const { return _eo.fitness(); } };
|
||||
|
||||
/** returns the fitness of the nth element */
|
||||
Fitness nth_element_fitness(int which) const
|
||||
{ // probably not the fastest way to do this, but what the heck
|
||||
struct GetFitness { Fitness operator()(const EOT& _eo) const { return _eo.fitness(); } };
|
||||
|
||||
std::vector<Fitness> fitness(size());
|
||||
std::transform(begin(), end(), fitness.begin(), GetFitness());
|
||||
|
||||
typename std::vector<Fitness>::iterator it = fitness.begin() + which;
|
||||
std::nth_element(fitness.begin(), it, fitness.end(), std::greater<Fitness>());
|
||||
return *it;
|
||||
}
|
||||
/** returns the fitness of the nth element */
|
||||
Fitness nth_element_fitness(int which) const
|
||||
{ // probably not the fastest way to do this, but what the heck
|
||||
|
||||
/** const nth_element function, returns pointers to sorted individuals
|
||||
* up the the nth
|
||||
*/
|
||||
void nth_element(int which, std::vector<const EOT*>& result) const
|
||||
{
|
||||
std::vector<Fitness> fitness(size());
|
||||
std::transform(begin(), end(), fitness.begin(), GetFitness());
|
||||
|
||||
result.resize(size());
|
||||
std::transform(begin(), end(), result.begin(), Ref());
|
||||
typename std::vector<Fitness>::iterator it = fitness.begin() + which;
|
||||
std::nth_element(fitness.begin(), it, fitness.end(), std::greater<Fitness>());
|
||||
return *it;
|
||||
}
|
||||
|
||||
typename std::vector<const EOT*>::iterator it = result.begin() + which;
|
||||
|
||||
std::nth_element(result.begin(), it, result.end(), Cmp());
|
||||
}
|
||||
/** const nth_element function, returns pointers to sorted individuals
|
||||
* up the the nth
|
||||
*/
|
||||
void nth_element(int which, std::vector<const EOT*>& result) const
|
||||
{
|
||||
|
||||
/** does STL swap with other pop */
|
||||
void swap(eoPop<EOT>& other)
|
||||
{
|
||||
std::swap(static_cast<std::vector<EOT>& >(*this), static_cast<std::vector<EOT>& >(other));
|
||||
}
|
||||
assert( this->size() > 0 );
|
||||
result.resize(size());
|
||||
std::transform(begin(), end(), result.begin(), Ref());
|
||||
|
||||
/**
|
||||
* Prints sorted pop but does NOT modify it!
|
||||
*
|
||||
* @param _os A std::ostream.
|
||||
*/
|
||||
virtual void sortedPrintOn(std::ostream& _os) const
|
||||
{
|
||||
std::vector<const EOT*> result;
|
||||
sort(result);
|
||||
_os << size() << '\n';
|
||||
for (unsigned i = 0; i < size(); ++i)
|
||||
{
|
||||
_os << *result[i] << std::endl;
|
||||
}
|
||||
}
|
||||
typename std::vector<const EOT*>::iterator it = result.begin() + which;
|
||||
|
||||
/**
|
||||
* Write object. It's called printOn since it prints the object _on_ a stream.
|
||||
* @param _os A std::ostream.
|
||||
*/
|
||||
virtual void printOn(std::ostream& _os) const
|
||||
{
|
||||
_os << size() << '\n';
|
||||
std::copy( begin(), end(), std::ostream_iterator<EOT>( _os, "\n") );
|
||||
}
|
||||
std::nth_element(result.begin(), it, result.end(), Cmp());
|
||||
}
|
||||
|
||||
/** @name Methods from eoObject */
|
||||
//@{
|
||||
/**
|
||||
* Read object. The EOT class must have a ctor from a stream;
|
||||
* @param _is A std::istream.
|
||||
*/
|
||||
virtual void readFrom(std::istream& _is)
|
||||
{
|
||||
size_t sz;
|
||||
_is >> sz;
|
||||
|
||||
resize(sz);
|
||||
/** does STL swap with other pop */
|
||||
void swap(eoPop<EOT>& other)
|
||||
{
|
||||
std::swap(static_cast<std::vector<EOT>& >(*this), static_cast<std::vector<EOT>& >(other));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sz; ++i) {
|
||||
operator[](i).readFrom( _is );
|
||||
}
|
||||
}
|
||||
|
||||
/** Inherited from eoObject. Returns the class name.
|
||||
@see eoObject
|
||||
*/
|
||||
virtual std::string className() const {return "eoPop";};
|
||||
//@}
|
||||
/**
|
||||
* Prints sorted pop but does NOT modify it!
|
||||
*
|
||||
* @param _os A std::ostream.
|
||||
*/
|
||||
virtual void sortedPrintOn(std::ostream& _os) const
|
||||
{
|
||||
std::vector<const EOT*> result;
|
||||
sort(result);
|
||||
_os << size() << '\n';
|
||||
for (unsigned i = 0; i < size(); ++i)
|
||||
{
|
||||
_os << *result[i] << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void invalidate()
|
||||
{
|
||||
for (unsigned i=0; i<size(); i++)
|
||||
this->operator[](i).invalidate();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Write object. It's called printOn since it prints the object _on_ a stream.
|
||||
* @param _os A std::ostream.
|
||||
*/
|
||||
virtual void printOn(std::ostream& _os) const
|
||||
{
|
||||
_os << size() << '\n';
|
||||
std::copy( begin(), end(), std::ostream_iterator<EOT>( _os, "\n") );
|
||||
}
|
||||
|
||||
|
||||
/** @name Methods from eoObject */
|
||||
//@{
|
||||
/**
|
||||
* Read object. The EOT class must have a ctor from a stream;
|
||||
* @param _is A std::istream.
|
||||
*/
|
||||
virtual void readFrom(std::istream& _is)
|
||||
{
|
||||
size_t sz;
|
||||
_is >> sz;
|
||||
|
||||
resize(sz);
|
||||
|
||||
for (size_t i = 0; i < sz; ++i) {
|
||||
operator[](i).readFrom( _is );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Inherited from eoObject. Returns the class name.
|
||||
@see eoObject
|
||||
*/
|
||||
virtual std::string className() const {return "eoPop";};
|
||||
//@}
|
||||
|
||||
|
||||
/** Invalidate the whole population
|
||||
*/
|
||||
virtual void invalidate()
|
||||
{
|
||||
for (unsigned i=0; i<size(); i++)
|
||||
this->operator[](i).invalidate();
|
||||
}
|
||||
|
||||
}; // class eoPop
|
||||
|
||||
#endif // _EOPOP_H_
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,16 @@
|
|||
#include <eoEvalFunc.h>
|
||||
#include <apply.h>
|
||||
|
||||
# ifdef WITH_MPI
|
||||
#include <mpi/eoMpi.h>
|
||||
#include <mpi/eoTerminateJob.h>
|
||||
#include <mpi/eoMpiAssignmentAlgorithm.h>
|
||||
#include <mpi/eoParallelApply.h>
|
||||
#include <utils/eoParallel.h>
|
||||
|
||||
#include <cmath> // ceil
|
||||
# endif // WITH_MPI
|
||||
|
||||
/** eoPopEvalFunc: This abstract class is for GLOBAL evaluators
|
||||
* of a population after variation.
|
||||
* It takes 2 populations (typically the parents and the offspring)
|
||||
|
|
@ -77,6 +87,142 @@ private:
|
|||
eoEvalFunc<EOT> & eval;
|
||||
};
|
||||
|
||||
#ifdef WITH_MPI
|
||||
/**
|
||||
* @brief Evaluator of a population of EOT which uses parallelization to evaluate individuals.
|
||||
*
|
||||
* This class implements an instance of eoPopEvalFunc that applies a private eoEvalFunc to
|
||||
* all offspring, but in a parallel way. The original process becomes the central host from a network ("master"), and
|
||||
* other machines disponible in the MPI network ("slaves") are used as evaluators. Population to evaluate is splitted in
|
||||
* little packets of individuals, which are sent to the evaluators, that process the effective call to eval. Once all
|
||||
* the individuals have been evaluated, they are returned to the master. The whole process is entirely invisible to the
|
||||
* eyes of the user, who just has to launch a certain number of processes in MPI so as to have a result.
|
||||
*
|
||||
* The eoEvalFunc is no more directly given, but it is stored in the eo::mpi::ParallelApplyStore, which can be
|
||||
* instanciated if no one is given at construction.
|
||||
*
|
||||
* The use of this class requires the user to have called the eo::mpi::Node::init function, at the beginning of its
|
||||
* program.
|
||||
*
|
||||
* @ingroup Evaluation Parallel
|
||||
*
|
||||
* @author Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
template<class EOT>
|
||||
class eoParallelPopLoopEval : public eoPopEvalFunc<EOT>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor which creates the job store for the user.
|
||||
*
|
||||
* This constructor is the simplest to use, as it creates the store used by the parallel job, for the user.
|
||||
* The user just precises the scheduling algorithm, the rank of the master and then gives its eval function and
|
||||
* the size of a packet (how many individuals should be in a single message to evaluator).
|
||||
*
|
||||
* @param _assignAlgo The scheduling algorithm used to give orders to evaluators.
|
||||
* @param _masterRank The MPI rank of the master.
|
||||
* @param _eval The evaluation functor used to evaluate each individual in the population.
|
||||
* @param _packetSize The number of individuals to send in one message to evaluator, and which are evaluated at
|
||||
* a time.
|
||||
*/
|
||||
eoParallelPopLoopEval(
|
||||
// Job parameters
|
||||
eo::mpi::AssignmentAlgorithm& _assignAlgo,
|
||||
int _masterRank,
|
||||
// Default parameters for store
|
||||
eoEvalFunc<EOT> & _eval,
|
||||
int _packetSize = 1
|
||||
) :
|
||||
assignAlgo( _assignAlgo ),
|
||||
masterRank( _masterRank ),
|
||||
needToDeleteStore( true ) // we used new, we'll have to use delete (RAII)
|
||||
{
|
||||
store = new eo::mpi::ParallelApplyStore<EOT>( _eval, _masterRank, _packetSize );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor which allows the user to customize its job store.
|
||||
*
|
||||
* This constructor allows the user to customize the store, for instance by adding wrappers and other
|
||||
* functionnalities, before using it for the parallelized evaluation.
|
||||
*
|
||||
* @param _assignAlgo The scheduling algorithm used to give orders to evaluators.
|
||||
* @param _masterRank The MPI rank of the master.
|
||||
* @param _store Pointer to a parallel eval store given by the user.
|
||||
*/
|
||||
eoParallelPopLoopEval(
|
||||
// Job parameters
|
||||
eo::mpi::AssignmentAlgorithm& _assignAlgo,
|
||||
int _masterRank,
|
||||
eo::mpi::ParallelApplyStore<EOT>* _store
|
||||
) :
|
||||
assignAlgo( _assignAlgo ),
|
||||
masterRank( _masterRank ),
|
||||
store( _store ),
|
||||
needToDeleteStore( false ) // we haven't used new for creating store, we don't care if we have to delete it (RAII).
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Default destructor. Sends a message to all evaluators indicating that the global loop (eoEasyEA, for
|
||||
* instance) is over.
|
||||
*/
|
||||
~eoParallelPopLoopEval()
|
||||
{
|
||||
// Only the master has to send the termination message
|
||||
if( eo::mpi::Node::comm().rank() == masterRank )
|
||||
{
|
||||
eo::mpi::EmptyJob job( assignAlgo, masterRank );
|
||||
job.run();
|
||||
}
|
||||
|
||||
// RAII
|
||||
if( needToDeleteStore )
|
||||
{
|
||||
delete store;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parallel implementation of the operator().
|
||||
*
|
||||
* @param _parents Population of parents (ignored).
|
||||
* @param _offspring Population of children, which will be evaluated.
|
||||
*/
|
||||
void operator()( eoPop<EOT> & _parents, eoPop<EOT> & _offspring )
|
||||
{
|
||||
(void)_parents;
|
||||
// Reinits the store and the scheduling algorithm
|
||||
store->data( _offspring );
|
||||
// For static scheduling, it's mandatory to reinit attributions
|
||||
int nbWorkers = assignAlgo.availableWorkers();
|
||||
assignAlgo.reinit( nbWorkers );
|
||||
if( ! eo::parallel.isDynamic() ) {
|
||||
store->data()->packetSize = ceil( static_cast<double>( _offspring.size() ) / nbWorkers );
|
||||
}
|
||||
// Effectively launches the job.
|
||||
eo::mpi::ParallelApply<EOT> job( assignAlgo, masterRank, *store );
|
||||
job.run();
|
||||
}
|
||||
|
||||
private:
|
||||
// Scheduling algorithm
|
||||
eo::mpi::AssignmentAlgorithm & assignAlgo;
|
||||
// Master MPI rank
|
||||
int masterRank;
|
||||
|
||||
// Store
|
||||
eo::mpi::ParallelApplyStore<EOT>* store;
|
||||
// Do we have to delete the store by ourselves ?
|
||||
bool needToDeleteStore;
|
||||
};
|
||||
|
||||
/**
|
||||
* @example t-mpi-eval.cpp
|
||||
*/
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// eoTimeVaryingLoopEval
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ public:
|
|||
|
||||
virtual std::string className() const { return "eoPropCombinedQuadOp"; }
|
||||
|
||||
/* FIXME remove in next release
|
||||
virtual void add(eoQuadOp<EOT> & _op, const double _rate, bool _verbose)
|
||||
{
|
||||
#ifndef DEPRECATED_MESSAGES
|
||||
|
|
@ -195,6 +196,7 @@ public:
|
|||
|
||||
add(_op,_rate);
|
||||
}
|
||||
*/
|
||||
|
||||
// addition of a true operator
|
||||
virtual void add(eoQuadOp<EOT> & _op, const double _rate)
|
||||
|
|
@ -202,7 +204,7 @@ public:
|
|||
ops.push_back(&_op);
|
||||
rates.push_back(_rate);
|
||||
// compute the relative rates in percent - to warn the user!
|
||||
printOn( eo::log << eo::logging );
|
||||
printOn( eo::log << eo::logging );
|
||||
}
|
||||
|
||||
// outputs the operators and percentages
|
||||
|
|
|
|||
54
eo/src/eoRankMuSelect.h
Normal file
54
eo/src/eoRankMuSelect.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
The Evolving Distribution Objects framework (EDO) is a template-based,
|
||||
ANSI-C++ evolutionary computation library which helps you to write your
|
||||
own estimation of distribution algorithms.
|
||||
|
||||
This library 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 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Copyright (C) 2012 Thales group
|
||||
*/
|
||||
/*
|
||||
Authors:
|
||||
Johann Dréo <johann.dreo@thalesgroup.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _eoRankMuSelect_h
|
||||
#define _eoRankMuSelect_h
|
||||
|
||||
#include "eoDetSelect.h"
|
||||
|
||||
/** Selects the "Mu" bests individuals.
|
||||
*
|
||||
* Note: sorts the population before trucating it.
|
||||
*
|
||||
* @ingroup Selectors
|
||||
*/
|
||||
template<typename EOT>
|
||||
class eoRankMuSelect : public eoDetSelect<EOT>
|
||||
{
|
||||
public :
|
||||
// false, because mu is not a rate
|
||||
eoRankMuSelect( unsigned int mu ) : eoDetSelect<EOT>( mu, false ) {}
|
||||
|
||||
void operator()(const eoPop<EOT>& source, eoPop<EOT>& dest)
|
||||
{
|
||||
eoPop<EOT> tmp( source );
|
||||
tmp.sort();
|
||||
eoDetSelect<EOT>::operator()( tmp, dest );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // !_eoRankMuselect_h
|
||||
|
|
@ -35,23 +35,26 @@
|
|||
@ingroup Continuators
|
||||
*/
|
||||
template< class EOT>
|
||||
class eoSteadyFitContinue: public eoContinue<EOT>
|
||||
class eoSteadyFitContinue: public eoCountContinue<EOT>
|
||||
{
|
||||
public:
|
||||
typedef typename EOT::Fitness Fitness;
|
||||
|
||||
using eoCountContinue<EOT>::thisGenerationPlaceholder;
|
||||
using eoCountContinue<EOT>::thisGeneration;
|
||||
|
||||
/// Ctor for setting a
|
||||
eoSteadyFitContinue( unsigned long _minGens, unsigned long _steadyGens)
|
||||
: repMinGenerations( _minGens ), repSteadyGenerations( _steadyGens),
|
||||
steadyState(false), thisGenerationPlaceHolder(0),
|
||||
thisGeneration(thisGenerationPlaceHolder){};
|
||||
: eoCountContinue<EOT>( ), repMinGenerations( _minGens ), repSteadyGenerations( _steadyGens),
|
||||
steadyState(false)
|
||||
{};
|
||||
|
||||
/// Ctor for enabling the save/load the no. of generations counted
|
||||
eoSteadyFitContinue( unsigned long _minGens, unsigned long _steadyGen,
|
||||
unsigned long& _currentGen)
|
||||
: repMinGenerations( _minGens ), repSteadyGenerations( _steadyGen),
|
||||
steadyState(_currentGen>_minGens), thisGenerationPlaceHolder(0),
|
||||
thisGeneration(_currentGen){};
|
||||
: eoCountContinue<EOT>( _currentGen ), repMinGenerations( _minGens ), repSteadyGenerations( _steadyGen),
|
||||
steadyState(_currentGen>_minGens)
|
||||
{};
|
||||
|
||||
/** Returns false when a certain number of generations is
|
||||
* reached withtout improvement */
|
||||
|
|
@ -96,7 +99,7 @@ public:
|
|||
/// Resets the state after it's been reached
|
||||
virtual void reset () {
|
||||
steadyState=false;
|
||||
thisGeneration = 0;
|
||||
eoCountContinue<EOT>::reset();
|
||||
}
|
||||
|
||||
/** accessors*/
|
||||
|
|
@ -110,8 +113,6 @@ private:
|
|||
unsigned long repMinGenerations;
|
||||
unsigned long repSteadyGenerations;
|
||||
bool steadyState;
|
||||
unsigned long thisGenerationPlaceHolder;
|
||||
unsigned long& thisGeneration;
|
||||
unsigned int lastImprovement;
|
||||
Fitness bestSoFar;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Define the es and cma targets
|
||||
######################################################################################
|
||||
|
||||
SET(ES_LIB_OUTPUT_PATH ${EO_BINARY_DIR}/lib)
|
||||
SET(CMA_LIB_OUTPUT_PATH ${EO_BINARY_DIR}/lib)
|
||||
set(ES_LIB_OUTPUT_PATH ${EO_BIN_DIR}/lib)
|
||||
set(CMA_LIB_OUTPUT_PATH ${EO_BIN_DIR}/lib)
|
||||
|
||||
SET(LIBRARY_OUTPUT_PATH ${ES_LIB_OUTPUT_PATH}) # the same output for the two libs
|
||||
set(LIBRARY_OUTPUT_PATH ${ES_LIB_OUTPUT_PATH}) # the same output for the two libs
|
||||
|
||||
SET(ES_SOURCES
|
||||
set(ES_SOURCES
|
||||
make_algo_scalar_es.cpp
|
||||
make_algo_scalar_real.cpp
|
||||
make_checkpoint_es.cpp
|
||||
|
|
@ -31,26 +31,26 @@ SET(ES_SOURCES
|
|||
make_run_real.cpp
|
||||
)
|
||||
|
||||
SET(CMA_SOURCES
|
||||
set(CMA_SOURCES
|
||||
eig.cpp
|
||||
CMAState.cpp
|
||||
CMAParams.cpp
|
||||
)
|
||||
|
||||
ADD_LIBRARY(es STATIC ${ES_SOURCES})
|
||||
INSTALL(TARGETS es ARCHIVE DESTINATION ${LIB} COMPONENT libraries)
|
||||
add_library(es STATIC ${ES_SOURCES})
|
||||
install(TARGETS es ARCHIVE DESTINATION local/${LIB} COMPONENT libraries)
|
||||
|
||||
ADD_LIBRARY(cma STATIC ${CMA_SOURCES})
|
||||
INSTALL(TARGETS cma ARCHIVE DESTINATION ${LIB} COMPONENT libraries)
|
||||
add_library(cma STATIC ${CMA_SOURCES})
|
||||
install(TARGETS cma ARCHIVE DESTINATION local/${LIB} COMPONENT libraries)
|
||||
|
||||
######################################################################################
|
||||
### 3) Optionnal
|
||||
######################################################################################
|
||||
|
||||
SET(ES_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(es PROPERTIES VERSION "${ES_VERSION}")
|
||||
set(ES_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(es PROPERTIES VERSION "${ES_VERSION}")
|
||||
|
||||
SET(CMA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(cma PROPERTIES VERSION "${CMA_VERSION}")
|
||||
set(CMA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(cma PROPERTIES VERSION "${CMA_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Define the ga target
|
||||
######################################################################################
|
||||
|
||||
SET(GA_LIB_OUTPUT_PATH ${EO_BINARY_DIR}/lib)
|
||||
SET(LIBRARY_OUTPUT_PATH ${GA_LIB_OUTPUT_PATH})
|
||||
set(GA_LIB_OUTPUT_PATH ${EO_BIN_DIR}/lib)
|
||||
set(LIBRARY_OUTPUT_PATH ${GA_LIB_OUTPUT_PATH})
|
||||
|
||||
SET(GA_SOURCES
|
||||
set(GA_SOURCES
|
||||
make_algo_scalar_ga.cpp
|
||||
make_checkpoint_ga.cpp
|
||||
make_continue_ga.cpp
|
||||
|
|
@ -22,14 +22,17 @@ SET(GA_SOURCES
|
|||
make_run_ga.cpp
|
||||
)
|
||||
|
||||
ADD_LIBRARY(ga STATIC ${GA_SOURCES})
|
||||
INSTALL(TARGETS ga ARCHIVE DESTINATION ${LIB} COMPONENT libraries)
|
||||
add_library(ga STATIC ${GA_SOURCES})
|
||||
install(TARGETS ga ARCHIVE DESTINATION lib COMPONENT libraries)
|
||||
|
||||
file(GLOB HDRS *.h)
|
||||
install(FILES ${HDRS} DESTINATION include/eo/ga COMPONENT headers)
|
||||
|
||||
######################################################################################
|
||||
### 3) Optionnal
|
||||
######################################################################################
|
||||
|
||||
SET(GA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(ga PROPERTIES VERSION "${GA_VERSION}")
|
||||
set(GA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(ga PROPERTIES VERSION "${GA_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
35
eo/src/mpi/CMakeLists.txt
Normal file
35
eo/src/mpi/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
######################################################################################
|
||||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Define the eompi target
|
||||
######################################################################################
|
||||
|
||||
set(EOMPI_LIB_OUTPUT_PATH ${EO_BIN_DIR}/lib)
|
||||
set(LIBRARY_OUTPUT_PATH ${EOMPI_LIB_OUTPUT_PATH})
|
||||
|
||||
set(EOMPI_SOURCES
|
||||
eoMpi.cpp
|
||||
eoMpiAssignmentAlgorithm.cpp
|
||||
eoMpiNode.cpp
|
||||
implMpi.cpp
|
||||
)
|
||||
|
||||
add_library(eompi STATIC ${EOMPI_SOURCES})
|
||||
install(TARGETS eompi ARCHIVE DESTINATION local/${LIB} COMPONENT libraries)
|
||||
|
||||
file(GLOB HDRS *.h)
|
||||
install(FILES ${HDRS} DESTINATION local/include${INSTALL_SUB_DIR}/eo/mpi COMPONENT headers)
|
||||
|
||||
######################################################################################
|
||||
### 3) Optionnal
|
||||
######################################################################################
|
||||
|
||||
set(EOMPI_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(eompi PROPERTIES VERSION "${EOMPI_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
48
eo/src/mpi/eoMpi.cpp
Normal file
48
eo/src/mpi/eoMpi.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# include "eoMpi.h"
|
||||
|
||||
namespace eo
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
/**********************************************
|
||||
* *********** GLOBALS ************************
|
||||
* *******************************************/
|
||||
eoTimerStat timerStat;
|
||||
|
||||
namespace Channel
|
||||
{
|
||||
const int Commands = 0;
|
||||
const int Messages = 1;
|
||||
}
|
||||
|
||||
namespace Message
|
||||
{
|
||||
const int Continue = 0;
|
||||
const int Finish = 1;
|
||||
const int Kill = 2;
|
||||
}
|
||||
|
||||
const int DEFAULT_MASTER = 0;
|
||||
}
|
||||
}
|
||||
868
eo/src/mpi/eoMpi.h
Normal file
868
eo/src/mpi/eoMpi.h
Normal file
|
|
@ -0,0 +1,868 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EO_MPI_H__
|
||||
# define __EO_MPI_H__
|
||||
|
||||
# include <vector> // std::vector
|
||||
|
||||
# include <utils/eoLogger.h>
|
||||
# include <utils/eoTimer.h>
|
||||
# include <eoFunctor.h>
|
||||
# include <eoExceptions.h>
|
||||
|
||||
# include "eoMpiNode.h"
|
||||
# include "eoMpiAssignmentAlgorithm.h"
|
||||
|
||||
namespace eo
|
||||
{
|
||||
/**
|
||||
* @ingroup Parallel
|
||||
* @defgroup MPI Message Passing Interface
|
||||
* @brief See namespace eo::mpi to have all explanations about this module.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief MPI parallelization helpers for EO.
|
||||
*
|
||||
* This namespace contains parallelization functions which help to parallelize computations in EO. It is based on a
|
||||
* generic algorithm, which is then customized with functors, corresponding to the algorithm main steps. These
|
||||
* computations are centralized, i.e there is one central host whose role is to handle the steps of the algorithm ;
|
||||
* we call it the "master". The other hosts just have to perform a "dummy" computation, which may be any kind of
|
||||
* processing ; we call them, the "slaves", or less pejoratively, the "workers". Workers can communicate to each
|
||||
* other, but they receive their orders from the Master and send him back some results. A worker can also be the
|
||||
* master of a different parallelization process, as soon as it is a part of its work. Machines of the network, also
|
||||
* called hosts, are identified by an unique number: their rank. At any time during the execution of the program,
|
||||
* all the hosts know the total number of hosts.
|
||||
*
|
||||
* A parallelized Job is a set of tasks which are independant (i.e can be executed in random order without
|
||||
* modifiying the result) and take a data input and compute a data output to be sent to the Master. The data can be
|
||||
* of any type, however they have to be serialized to be sent over a network. It is sufficient that they can be
|
||||
* serialized through boost.
|
||||
*
|
||||
* @todo For serialization purposes, don't depend upon boost. It would be easy to use only eoserial and send strings
|
||||
* via mpi.
|
||||
*
|
||||
* The main steps of the algorithm are the following:
|
||||
* - For the master:
|
||||
* - Have we done with the treatment we are doing ?
|
||||
* - If this is the case, we can quit.
|
||||
* - Otherwise, send an input data to some available worker.
|
||||
* - If there's no available worker, wait for a worker to be free.
|
||||
* - When receiving the response, handle it (eventually compute something on the output data, store it...).
|
||||
* - Go back to the first step.
|
||||
* - For the worker, it is even easier:
|
||||
* - Wait for an order.
|
||||
* - If there's nothing to do, just quit.
|
||||
* - Otherwise, eventually retrieve data and do the work.
|
||||
* - Go back to the first step.
|
||||
*
|
||||
* There is of course some network adjustements to do and precisions to give there, but the main ideas are present. As the
|
||||
* job is fully centralized, this is the master who tells the workers when to quit and when to work.
|
||||
*
|
||||
* The idea behind these MPI helpers is to be the most generic possible. If we look back at the steps of the
|
||||
* algorithm, we found that the steps can be splitted into 2 parts: the first consists in the steps of any
|
||||
* parallelization algorithm and the other consists in the specific parts of the algorithm. Ideally, the user should
|
||||
* just have to implement the specific parts of the algorithm. We identified these parts to be:
|
||||
* - For the master:
|
||||
* - What does mean to have terminated ? There are only two alternatives, in our binary world: either it is
|
||||
* terminated, or it is not. Hence we only need a function returning a boolean to know if we're done with the
|
||||
* computation : we'll call it IsFinished.
|
||||
* - What do we have to do when we send a task ? We don't have any a priori on the form of the sent data, or
|
||||
* the number of sent data. Moreover, as the tasks are all independant, we don't care of who will do the
|
||||
* computation, as soon as it's done. Knowing the rank of the worker will be sufficient to send him data. We
|
||||
* have identified another function, taking a single argument which is the rank of the worker: we'll call it
|
||||
* SendTask.
|
||||
* - What do we have to do when we receive a response from a worker ? One more time, we don't know which form
|
||||
* or structure can have the receive data, only the user can know. Also we let the user the charge to retrieve
|
||||
* the data ; he just has to know from who the master will retrieve the data. Here is another function, taking
|
||||
* a rank (the sender's one) as a function argument : this will be HandleResponse.
|
||||
* - For the worker:
|
||||
* - What is the processing ? It can have any nature. We just need to be sure that a data is sent back to the
|
||||
* master, but it seems difficult to check that: it will be the role of the user to assert that data is sent by
|
||||
* the worker at the end of an execution. We've got identified our last function: ProcessTask.
|
||||
*
|
||||
* In term of implementation, it would be annoying to have only abstract classes with these 4 methods to implement. It
|
||||
* would mean that if you want to alter just one of these 4 functions, you have to implement a new sub class, with a
|
||||
* new constructor which could have the same signature. Besides, this fashion doesn't allow you to add dynamic
|
||||
* functionalities, using the design pattern Decorator for instance, without implement a class for each type of
|
||||
* decoration you want to add. For these reasons, we decided to transform function into functors ; the user can then
|
||||
* wrap the existing, basic comportments into more sophisticated computations, whenever he wants, and without the
|
||||
* notion of order. We retrieve here the power of extension given by the design pattern Decorator.
|
||||
*
|
||||
* Our 4 functors could have a big amount of data in common (see eoParallelApply to have an idea).
|
||||
* So as to make it easy for the user to implement these 4 functors, we consider that these functors
|
||||
* have to share a common data structure. This data structure is referenced (as a pointer) in the 4 functors, so the
|
||||
* user doesn't need to pass a lot of parameters to each functor constructor.
|
||||
*
|
||||
* There are two kinds of jobs:
|
||||
* - The job which are launched a fixed and well known amount of times, i.e both master and workers know how many
|
||||
* times they will be launched. They are "one shot jobs".
|
||||
* - The job which are launched an unknown amount of times, for instance embedded in a while loop for which we don't
|
||||
* know the amount of repetitions (typically, eoEasyEA loop is a good example, as we don't know the continuator
|
||||
* condition). They are called "multi job".
|
||||
* As the master tells the workers to quit, we have to differentiate these two kinds of jobs. When the job is of the
|
||||
* kind "multi job", the workers would have to perform a while(true) loop so as to receive the orders ; but even if
|
||||
* the master tells them to quit, they would begin another job and wait for another order, while the master would
|
||||
* have quit: this would cause a deadlock and workers processes would be blocked, waiting for an order.
|
||||
*/
|
||||
namespace mpi
|
||||
{
|
||||
/**
|
||||
* @brief A timer which allows user to generate statistics about computation times.
|
||||
*/
|
||||
extern eoTimerStat timerStat;
|
||||
|
||||
/**
|
||||
* @brief Tags used in MPI messages for framework communication
|
||||
*
|
||||
* These tags are used for framework communication and fits "channels", so as to differentiate when we're
|
||||
* sending an order to a worker (Commands) or data (Messages). They are not reserved by the framework and can be
|
||||
* used by the user, but he is not bound to.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
namespace Channel
|
||||
{
|
||||
extern const int Commands;
|
||||
extern const int Messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simple orders used by the framework.
|
||||
*
|
||||
* These orders are sent by the master to the workers, to indicate to them if they should receive another task
|
||||
* to do (Continue), if an one shot job is done (Finish) or if a multi job is done (Kill).
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
namespace Message
|
||||
{
|
||||
extern const int Continue;
|
||||
extern const int Finish;
|
||||
extern const int Kill;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief If the job only has one master, the user can use this constant, so as not to worry with integer ids.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
extern const int DEFAULT_MASTER;
|
||||
|
||||
/**
|
||||
* @brief Base class for the 4 algorithm functors.
|
||||
*
|
||||
* This class can embed a data (JobData) and a wrapper, so as to make all the 4 functors wrappable.
|
||||
* We can add a wrapper at initialization or at any time when executing the program.
|
||||
*
|
||||
* According to RAII, the boolean needDelete helps to know if we have to use the operator delete on the wrapper
|
||||
* or not. Hence, if any functor is wrapped, user has just to put this boolean to true, to indicate to wrapper
|
||||
* that it should call delete. This allows to mix wrapper initialized in the heap (with new) or in the stack.
|
||||
*
|
||||
* @param JobData a Data type, which can have any form. It can a struct, a single int, anything.
|
||||
*
|
||||
* @param Wrapped the type of the functor, which will be stored as a pointer under the name _wrapped.
|
||||
* This allows to wrap directly the functor in functors of the same type
|
||||
* here, instead of dealing with SharedDataFunction* that we would have to cast all the time.
|
||||
* Doing also allows to handle the wrapped functor as the functor we're writing, when coding the wrappers,
|
||||
* instead of doing some static_cast. For instance, if there are 2 functors subclasses, fA and fB, fA
|
||||
* implementing doFa() and fB implementing doFb(), we could have the following code:
|
||||
* @code
|
||||
* struct fA_wrapper
|
||||
* {
|
||||
* // some code
|
||||
* void doFa()
|
||||
* {
|
||||
* _wrapped->doFa();
|
||||
* std::cout << "I'm a fA wrapper!" << std::endl;
|
||||
* // if we didn't have the second template parameter, but a SharedDataFunction, we would have to do this:
|
||||
* static_cast<fA*>(_wrapped)->doFa();
|
||||
* // do other things (it's a wrapper)
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* struct fB_wrapper
|
||||
* {
|
||||
* // some code
|
||||
* void doFb()
|
||||
* {
|
||||
* _wrapped->doFb(); // and not: static_cast<fB*>(_wrapped)->doFb();
|
||||
* }
|
||||
* };
|
||||
* @endcode
|
||||
* This makes the code easier to write for the user.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
template< typename JobData, typename Wrapped >
|
||||
struct SharedDataFunction
|
||||
{
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*
|
||||
* The user is not bound to give a wrapped functor.
|
||||
*/
|
||||
SharedDataFunction( Wrapped * w = 0 ) : _data( 0 ), _wrapped( w ), _needDelete( false )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*
|
||||
* Calls delete on the wrapped function, only if necessary.
|
||||
*/
|
||||
virtual ~SharedDataFunction()
|
||||
{
|
||||
if( _wrapped && _wrapped->needDelete() )
|
||||
{
|
||||
delete _wrapped;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setter for the wrapped function.
|
||||
*
|
||||
* It doesn't do anything on the current wrapped function, like deleting it.
|
||||
*/
|
||||
void wrapped( Wrapped * w )
|
||||
{
|
||||
_wrapped = w;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setter for the data present in the functor.
|
||||
*
|
||||
* Calls the setter on the functor and on the wrapped functors, in a Composite pattern fashion.
|
||||
*/
|
||||
void data( JobData* d )
|
||||
{
|
||||
_data = d;
|
||||
if( _wrapped )
|
||||
{
|
||||
_wrapped->data( d );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if we need to use operator delete on this wrapper, false otherwise.
|
||||
*
|
||||
* Allows the user to reject delete responsability to the framework, by setting this value to true.
|
||||
**/
|
||||
bool needDelete() { return _needDelete; }
|
||||
void needDelete( bool b ) { _needDelete = b; }
|
||||
|
||||
protected:
|
||||
JobData* _data;
|
||||
Wrapped* _wrapped; // Pointer and not a reference so as to be set at any time and to avoid affectation
|
||||
bool _needDelete;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Functor (master side) used to send a task to the worker.
|
||||
*
|
||||
* The user doesn't have to know which worker will receive a task, so we just indicate to master the rank of the
|
||||
* worker. The data used for computation have to be explicitly sent by the master to the worker, with indicated
|
||||
* rank. Once this functor has been called, the worker is considered busy until it sends a return message to the
|
||||
* master.
|
||||
*
|
||||
* This is a functor implementing void operator()(int), and also a shared data function, containing wrapper on its
|
||||
* own type.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
template< typename JobData >
|
||||
struct SendTaskFunction : public eoUF<int, void>, public SharedDataFunction< JobData, SendTaskFunction<JobData> >
|
||||
{
|
||||
public:
|
||||
|
||||
SendTaskFunction( SendTaskFunction<JobData>* w = 0 ) : SharedDataFunction<JobData, SendTaskFunction<JobData> >( w )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual ~SendTaskFunction() {} // for inherited classes
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Functor (master side) used to indicate what to do when receiving a response.
|
||||
*
|
||||
* The master calls this function as soon as it receives some data, in some channel. Thanks to MPI, we retrieve
|
||||
* the rank of the data's sender. This functor is then called with this rank. There is no memoization of a link
|
||||
* between sent data and rank, so the user has to implement it, if he needs it.
|
||||
*
|
||||
* This is a functor implementing void operator()(int), and also a shared data function, containing wrapper on
|
||||
* its own type.
|
||||
*
|
||||
* The master has to receive worker's data on channel (= MPI tag) eo::mpi::Channel::Messages. No other tags are
|
||||
* allowed.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
template< typename JobData >
|
||||
struct HandleResponseFunction : public eoUF<int, void>, public SharedDataFunction< JobData, HandleResponseFunction<JobData> >
|
||||
{
|
||||
public:
|
||||
|
||||
HandleResponseFunction( HandleResponseFunction<JobData>* w = 0 ) : SharedDataFunction<JobData, HandleResponseFunction<JobData> >( w )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual ~HandleResponseFunction() {} // for inherited classes
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Functor (worker side) implementing the processing to do.
|
||||
*
|
||||
* This is where the real computation happen.
|
||||
* Whenever the master sends the command "Continue" to workers, which indicates the worker will receive a task,
|
||||
* the worker calls this functor. The user has to explicitly retrieve the data, handle it and transmit it,
|
||||
* processed, back to the master. Data sent back needs to be transmitted via channel (= MPI tag)
|
||||
* eo::mpi::Channel::Messages, and no one else. If the worker does not send any data back to the master, the latter will
|
||||
* consider the worker isn't done and a deadlock could occur.
|
||||
*
|
||||
* This is a functor implementing void operator()(), and also a shared data function, containing wrapper on its
|
||||
* own type.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
template< typename JobData >
|
||||
struct ProcessTaskFunction : public eoF<void>, public SharedDataFunction< JobData, ProcessTaskFunction<JobData> >
|
||||
{
|
||||
public:
|
||||
|
||||
ProcessTaskFunction( ProcessTaskFunction<JobData>* w = 0 ) : SharedDataFunction<JobData, ProcessTaskFunction<JobData> >( w )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual ~ProcessTaskFunction() {} // for inherited classes
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Functor (master side) indicating whether the job is done or not.
|
||||
*
|
||||
* The master loops on this functor to know when to stop. When this functor returns true, the master will wait
|
||||
* for the last responses and properly stops the job. Whenever this functor returns false, the master will send
|
||||
* tasks, until this functor returns true.
|
||||
*
|
||||
* This is a functor implementing bool operator()(), and also a shared function, containing wrapper on its own
|
||||
* type.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
template< typename JobData >
|
||||
struct IsFinishedFunction : public eoF<bool>, public SharedDataFunction< JobData, IsFinishedFunction<JobData> >
|
||||
{
|
||||
public:
|
||||
|
||||
IsFinishedFunction( IsFinishedFunction<JobData>* w = 0 ) : SharedDataFunction<JobData, IsFinishedFunction<JobData> >( w )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual ~IsFinishedFunction() {} // for inherited classes
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Contains all the required data and the functors to launch a job.
|
||||
*
|
||||
* Splitting the functors and data from the job in itself allows to use the same functors and data for multiples
|
||||
* instances of the same job. You define your store once and can use it a lot of times during your program. If
|
||||
* the store was included in the job, you'd have to give again all the functors and all the datas to each
|
||||
* invokation of the job.
|
||||
*
|
||||
* Job store contains the 4 functors (pointers, so as to be able to wrap them ; references couldn't have
|
||||
* permitted that) described above and the JobData used by all these functors. It contains
|
||||
* also helpers to easily wrap the functors, getters and setters on all of them.
|
||||
*
|
||||
* The user has to implement data(), which is the getter for retrieving JobData. We don't have any idea of who
|
||||
* owns the data, moreover it is impossible to initialize it in this generic JobStore, as we don't know its
|
||||
* form. As a matter of fact, the user has to define this in the JobStore subclasses.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
template< typename JobData >
|
||||
struct JobStore
|
||||
{
|
||||
/**
|
||||
* @brief Default ctor with the 4 functors.
|
||||
*/
|
||||
JobStore(
|
||||
SendTaskFunction<JobData>* stf,
|
||||
HandleResponseFunction<JobData>* hrf,
|
||||
ProcessTaskFunction<JobData>* ptf,
|
||||
IsFinishedFunction<JobData>* iff
|
||||
) :
|
||||
_stf( stf ), _hrf( hrf ), _ptf( ptf ), _iff( iff )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Empty ctor, useful for not forcing users to call the other constructor.
|
||||
*
|
||||
* When using this constructor, the user have to care about the 4 functors pointers, otherwise null pointer
|
||||
* segfaults have to be expected.
|
||||
*/
|
||||
JobStore()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Default destructor.
|
||||
*
|
||||
* JobStore is the highest layer which calls needDelete on its functors.
|
||||
*/
|
||||
~JobStore()
|
||||
{
|
||||
if( _stf->needDelete() ) delete _stf;
|
||||
if( _hrf->needDelete() ) delete _hrf;
|
||||
if( _ptf->needDelete() ) delete _ptf;
|
||||
if( _iff->needDelete() ) delete _iff;
|
||||
}
|
||||
|
||||
// Getters
|
||||
SendTaskFunction<JobData> & sendTask() { return *_stf; }
|
||||
HandleResponseFunction<JobData> & handleResponse() { return *_hrf; }
|
||||
ProcessTaskFunction<JobData> & processTask() { return *_ptf; }
|
||||
IsFinishedFunction<JobData> & isFinished() { return *_iff; }
|
||||
|
||||
// Setters
|
||||
void sendTask( SendTaskFunction<JobData>* stf )
|
||||
{
|
||||
if( !stf )
|
||||
return;
|
||||
|
||||
if( _stf && _stf->needDelete() )
|
||||
{
|
||||
delete _stf;
|
||||
}
|
||||
_stf = stf;
|
||||
}
|
||||
|
||||
void handleResponse( HandleResponseFunction<JobData>* hrf )
|
||||
{
|
||||
if( !hrf )
|
||||
return;
|
||||
|
||||
if( _hrf && _hrf->needDelete() )
|
||||
{
|
||||
delete _hrf;
|
||||
}
|
||||
_hrf = hrf;
|
||||
}
|
||||
|
||||
void processTask( ProcessTaskFunction<JobData>* ptf )
|
||||
{
|
||||
if( !ptf )
|
||||
return;
|
||||
|
||||
if( _ptf && _ptf->needDelete() )
|
||||
{
|
||||
delete _ptf;
|
||||
}
|
||||
_ptf = ptf;
|
||||
}
|
||||
|
||||
void isFinished( IsFinishedFunction<JobData>* iff )
|
||||
{
|
||||
if( !iff )
|
||||
return;
|
||||
|
||||
if( _iff && _iff->needDelete() )
|
||||
{
|
||||
delete _iff;
|
||||
}
|
||||
_iff = iff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helpers for wrapping send task functor.
|
||||
*/
|
||||
void wrapSendTask( SendTaskFunction<JobData>* stf )
|
||||
{
|
||||
if( stf )
|
||||
{
|
||||
stf->wrapped( _stf );
|
||||
_stf = stf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helpers for wrapping handle response functor.
|
||||
*/
|
||||
void wrapHandleResponse( HandleResponseFunction<JobData>* hrf )
|
||||
{
|
||||
if( hrf )
|
||||
{
|
||||
hrf->wrapped( _hrf );
|
||||
_hrf = hrf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helpers for wrapping process task functor.
|
||||
*/
|
||||
void wrapProcessTask( ProcessTaskFunction<JobData>* ptf )
|
||||
{
|
||||
if( ptf )
|
||||
{
|
||||
ptf->wrapped( _ptf );
|
||||
_ptf = ptf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helpers for wrapping is finished functor.
|
||||
*/
|
||||
void wrapIsFinished( IsFinishedFunction<JobData>* iff )
|
||||
{
|
||||
if( iff )
|
||||
{
|
||||
iff->wrapped( _iff );
|
||||
_iff = iff;
|
||||
}
|
||||
}
|
||||
|
||||
virtual JobData* data() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
SendTaskFunction< JobData >* _stf;
|
||||
HandleResponseFunction< JobData >* _hrf;
|
||||
ProcessTaskFunction< JobData >* _ptf;
|
||||
IsFinishedFunction< JobData >* _iff;
|
||||
};
|
||||
|
||||
/**
|
||||
* @example t-mpi-wrapper.cpp
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Class implementing the centralized job algorithm.
|
||||
*
|
||||
* This class handles all the job algorithm. With its store and its assignment (scheduling) algorithm, it
|
||||
* executes the general algorithm described above, adding some networking, so as to make the global process
|
||||
* work. It initializes all the functors with the data, then launches the main loop, indicating to workers when
|
||||
* they will have to work and when they will finish, by sending them a termination message (integer that can be
|
||||
* customized). As the algorithm is centralized, it is also mandatory to indicate what is the MPI rank of the
|
||||
* master process, hence the workers will know from who they should receive their commands.
|
||||
*
|
||||
* Any of the 3 master functors can launch exception, it will be catched and rethrown as a std::runtime_exception
|
||||
* to the higher layers.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
template< class JobData >
|
||||
class Job
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Main constructor for Job.
|
||||
*
|
||||
* @param _algo The used assignment (scheduling) algorithm. It has to be initialized, with its maximum
|
||||
* possible number of workers (some workers referenced in this algorithm shouldn't be busy). See
|
||||
* AssignmentAlgorithm for more details.
|
||||
*
|
||||
* @param _masterRank The MPI rank of the master.
|
||||
*
|
||||
* @param _workerStopCondition Number of the message which will cause the workers to terminate. It could
|
||||
* be one of the constants defined in eo::mpi::Commands, or any other integer. The user has to be sure
|
||||
* that a message containing this integer will be sent to each worker on the Commands channel, otherwise
|
||||
* deadlock will happen. Master sends Finish messages at the end of a simple job, but as a job can
|
||||
* happen multiples times (multi job), workers don't have to really finish on these messages but on
|
||||
* another message. This is here where you can configurate it. See also OneShotJob and MultiJob.
|
||||
*
|
||||
* @param store The JobStore containing functors and data for this job.
|
||||
*/
|
||||
Job( AssignmentAlgorithm& _algo,
|
||||
int _masterRank,
|
||||
int _workerStopCondition,
|
||||
JobStore<JobData> & _store
|
||||
) :
|
||||
assignmentAlgo( _algo ),
|
||||
masterRank( _masterRank ),
|
||||
workerStopCondition( _workerStopCondition ),
|
||||
comm( Node::comm() ),
|
||||
// Functors
|
||||
store( _store ),
|
||||
sendTask( _store.sendTask() ),
|
||||
handleResponse( _store.handleResponse() ),
|
||||
processTask( _store.processTask() ),
|
||||
isFinished( _store.isFinished() )
|
||||
{
|
||||
_isMaster = Node::comm().rank() == _masterRank;
|
||||
|
||||
sendTask.data( _store.data() );
|
||||
handleResponse.data( _store.data() );
|
||||
processTask.data( _store.data() );
|
||||
isFinished.data( _store.data() );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief Finally block of the main algorithm
|
||||
*
|
||||
* Herb Sutter's trick for having a finally block, in a try/catch section: invoke a class at the
|
||||
* beginning of the try, its destructor will be called in every cases.
|
||||
*
|
||||
* This implements the end of the master algorithm:
|
||||
* - sends to all available workers that they are free,
|
||||
* - waits for last responses, handles them and sends termination messages to last workers.
|
||||
*/
|
||||
struct FinallyBlock
|
||||
{
|
||||
FinallyBlock(
|
||||
int _totalWorkers,
|
||||
AssignmentAlgorithm& _algo,
|
||||
Job< JobData > & _that
|
||||
) :
|
||||
totalWorkers( _totalWorkers ),
|
||||
assignmentAlgo( _algo ),
|
||||
that( _that ),
|
||||
// global field
|
||||
comm( Node::comm() )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
~FinallyBlock()
|
||||
{
|
||||
eo::log << eo::debug << "[M" << comm.rank() << "] Frees all the idle." << std::endl;
|
||||
|
||||
// frees all the idle workers
|
||||
timerStat.start("master_wait_for_idles");
|
||||
std::vector<int> idles = assignmentAlgo.idles();
|
||||
for(unsigned int i = 0; i < idles.size(); ++i)
|
||||
{
|
||||
comm.send( idles[i], Channel::Commands, Message::Finish );
|
||||
}
|
||||
timerStat.stop("master_wait_for_idles");
|
||||
|
||||
eo::log << eo::debug << "[M" << comm.rank() << "] Waits for all responses." << std::endl;
|
||||
|
||||
// wait for all responses
|
||||
timerStat.start("master_wait_for_all_responses");
|
||||
while( assignmentAlgo.availableWorkers() != totalWorkers )
|
||||
{
|
||||
bmpi::status status = comm.probe( bmpi::any_source, eo::mpi::Channel::Messages );
|
||||
int wrkRank = status.source();
|
||||
that.handleResponse( wrkRank );
|
||||
comm.send( wrkRank, Channel::Commands, Message::Finish );
|
||||
assignmentAlgo.confirm( wrkRank );
|
||||
}
|
||||
timerStat.stop("master_wait_for_all_responses");
|
||||
|
||||
eo::log << eo::debug << "[M" << comm.rank() << "] Leaving master task." << std::endl;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
int totalWorkers;
|
||||
AssignmentAlgorithm& assignmentAlgo;
|
||||
Job< JobData > & that;
|
||||
|
||||
bmpi::communicator & comm;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Master part of the job.
|
||||
*
|
||||
* Launches the parallelized job algorithm : while there is something to do (! IsFinished ), get a
|
||||
* worker who will be the assignee ; if no worker is available, wait for a response, handle it and reask
|
||||
* for an assignee. Then send the command and the task.
|
||||
* Once there is no more to do (IsFinished), indicate to all available workers that they're free, wait
|
||||
* for all the responses and send termination messages (see also FinallyBlock).
|
||||
*/
|
||||
void master( )
|
||||
{
|
||||
int totalWorkers = assignmentAlgo.availableWorkers();
|
||||
eo::log << eo::debug << "[M" << comm.rank() << "] Have " << totalWorkers << " workers." << std::endl;
|
||||
|
||||
try {
|
||||
FinallyBlock finally( totalWorkers, assignmentAlgo, *this );
|
||||
while( ! isFinished() )
|
||||
{
|
||||
timerStat.start("master_wait_for_assignee");
|
||||
int assignee = assignmentAlgo.get( );
|
||||
while( assignee <= 0 )
|
||||
{
|
||||
eo::log << eo::debug << "[M" << comm.rank() << "] Waitin' for node..." << std::endl;
|
||||
|
||||
bmpi::status status = comm.probe( bmpi::any_source, eo::mpi::Channel::Messages );
|
||||
int wrkRank = status.source();
|
||||
|
||||
eo::log << eo::debug << "[M" << comm.rank() << "] Node " << wrkRank << " just terminated." << std::endl;
|
||||
|
||||
handleResponse( wrkRank );
|
||||
assignmentAlgo.confirm( wrkRank );
|
||||
assignee = assignmentAlgo.get( );
|
||||
}
|
||||
timerStat.stop("master_wait_for_assignee");
|
||||
|
||||
eo::log << eo::debug << "[M" << comm.rank() << "] Assignee : " << assignee << std::endl;
|
||||
|
||||
timerStat.start("master_wait_for_send");
|
||||
comm.send( assignee, Channel::Commands, Message::Continue );
|
||||
sendTask( assignee );
|
||||
timerStat.stop("master_wait_for_send");
|
||||
}
|
||||
} catch( const std::exception & e )
|
||||
{
|
||||
std::string s = e.what();
|
||||
s.append( " in eoMpi loop");
|
||||
throw std::runtime_error( s );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Worker part of the algorithm.
|
||||
*
|
||||
* The algorithm is more much simpler: wait for an order; if it's termination message, leave. Otherwise,
|
||||
* prepare to work.
|
||||
*/
|
||||
void worker( )
|
||||
{
|
||||
int order;
|
||||
|
||||
timerStat.start("worker_wait_for_order");
|
||||
comm.recv( masterRank, Channel::Commands, order );
|
||||
timerStat.stop("worker_wait_for_order");
|
||||
|
||||
while( true )
|
||||
{
|
||||
eo::log << eo::debug << "[W" << comm.rank() << "] Waiting for an order..." << std::endl;
|
||||
|
||||
if ( order == workerStopCondition )
|
||||
{
|
||||
eo::log << eo::debug << "[W" << comm.rank() << "] Leaving worker task." << std::endl;
|
||||
return;
|
||||
} else if( order == Message::Continue )
|
||||
{
|
||||
eo::log << eo::debug << "[W" << comm.rank() << "] Processing task..." << std::endl;
|
||||
processTask( );
|
||||
}
|
||||
|
||||
timerStat.start("worker_wait_for_order");
|
||||
comm.recv( masterRank, Channel::Commands, order );
|
||||
timerStat.stop("worker_wait_for_order");
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Launches the job algorithm, according to the role of the host (roles are deduced from the
|
||||
* master rank indicated in the constructor).
|
||||
*/
|
||||
void run( )
|
||||
{
|
||||
( _isMaster ) ? master( ) : worker( );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the current host is the master, false otherwise.
|
||||
*/
|
||||
bool isMaster( )
|
||||
{
|
||||
return _isMaster;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
AssignmentAlgorithm& assignmentAlgo;
|
||||
int masterRank;
|
||||
const int workerStopCondition;
|
||||
bmpi::communicator& comm;
|
||||
|
||||
JobStore<JobData>& store;
|
||||
SendTaskFunction<JobData> & sendTask;
|
||||
HandleResponseFunction<JobData> & handleResponse;
|
||||
ProcessTaskFunction<JobData> & processTask;
|
||||
IsFinishedFunction<JobData> & isFinished;
|
||||
|
||||
bool _isMaster;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Job that will be launched only once.
|
||||
*
|
||||
* As explained in eo::mpi documentation, jobs can happen either a well known amount of times or an unknown
|
||||
* amount of times. This class implements the general case when the job is launched a well known amount of
|
||||
* times. The job will be terminated on both sides (master and worker) once the master would have said it.
|
||||
*
|
||||
* It uses the message Message::Finish as the termination message.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
template< class JobData >
|
||||
class OneShotJob : public Job< JobData >
|
||||
{
|
||||
public:
|
||||
OneShotJob( AssignmentAlgorithm& algo,
|
||||
int masterRank,
|
||||
JobStore<JobData> & store )
|
||||
: Job<JobData>( algo, masterRank, Message::Finish, store )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Job that will be launched an unknown amount of times, in worker side.
|
||||
*
|
||||
* As explained in eo::mpi documentation, jobs can happen either a well known amount of times or an unknown
|
||||
* amount of times. This class implements the general case when the job is launched an unknown amount of times, for
|
||||
* instance in a while loop. The master will run many jobs (or the same job many times), but the workers will
|
||||
* launch it only once.
|
||||
*
|
||||
* It uses the message Message::Kill as the termination message. This message can be launched with an EmptyJob,
|
||||
* launched only by the master. If no Message::Kill is sent on the Channels::Commands, the worker will wait
|
||||
* forever, which will cause a deadlock.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
template< class JobData >
|
||||
class MultiJob : public Job< JobData >
|
||||
{
|
||||
public:
|
||||
MultiJob ( AssignmentAlgorithm& algo,
|
||||
int masterRank,
|
||||
JobStore<JobData> & store )
|
||||
: Job<JobData>( algo, masterRank, Message::Kill, store )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
}
|
||||
# endif // __EO_MPI_H__
|
||||
|
||||
224
eo/src/mpi/eoMpiAssignmentAlgorithm.cpp
Normal file
224
eo/src/mpi/eoMpiAssignmentAlgorithm.cpp
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
# include "eoMpiAssignmentAlgorithm.h"
|
||||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# include "eoMpiNode.h"
|
||||
|
||||
namespace eo
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
const int REST_OF_THE_WORLD = -1;
|
||||
|
||||
/********************************************************
|
||||
* DYNAMIC ASSIGNMENT ALGORITHM *************************
|
||||
*******************************************************/
|
||||
|
||||
DynamicAssignmentAlgorithm::DynamicAssignmentAlgorithm( )
|
||||
{
|
||||
for(int i = 1; i < Node::comm().size(); ++i)
|
||||
{
|
||||
availableWrk.push_back( i );
|
||||
}
|
||||
}
|
||||
|
||||
DynamicAssignmentAlgorithm::DynamicAssignmentAlgorithm( int unique )
|
||||
{
|
||||
availableWrk.push_back( unique );
|
||||
}
|
||||
|
||||
DynamicAssignmentAlgorithm::DynamicAssignmentAlgorithm( const std::vector<int> & workers )
|
||||
{
|
||||
availableWrk = workers;
|
||||
}
|
||||
|
||||
DynamicAssignmentAlgorithm::DynamicAssignmentAlgorithm( int first, int last )
|
||||
{
|
||||
if( last == REST_OF_THE_WORLD )
|
||||
{
|
||||
last = Node::comm().size() - 1;
|
||||
}
|
||||
|
||||
for( int i = first; i <= last; ++i)
|
||||
{
|
||||
availableWrk.push_back( i );
|
||||
}
|
||||
}
|
||||
|
||||
int DynamicAssignmentAlgorithm::get( )
|
||||
{
|
||||
int assignee = -1;
|
||||
if (! availableWrk.empty() )
|
||||
{
|
||||
assignee = availableWrk.back();
|
||||
availableWrk.pop_back();
|
||||
}
|
||||
return assignee;
|
||||
}
|
||||
|
||||
int DynamicAssignmentAlgorithm::availableWorkers()
|
||||
{
|
||||
return availableWrk.size();
|
||||
}
|
||||
|
||||
void DynamicAssignmentAlgorithm::confirm( int rank )
|
||||
{
|
||||
availableWrk.push_back( rank );
|
||||
}
|
||||
|
||||
std::vector<int> DynamicAssignmentAlgorithm::idles( )
|
||||
{
|
||||
return availableWrk;
|
||||
}
|
||||
|
||||
void DynamicAssignmentAlgorithm::reinit( int _ )
|
||||
{
|
||||
++_;
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* STATIC ASSIGNMENT ALGORITHM **************************
|
||||
*******************************************************/
|
||||
|
||||
StaticAssignmentAlgorithm::StaticAssignmentAlgorithm( const std::vector<int>& workers, int runs )
|
||||
{
|
||||
init( workers, runs );
|
||||
}
|
||||
|
||||
StaticAssignmentAlgorithm::StaticAssignmentAlgorithm( int first, int last, int runs )
|
||||
{
|
||||
std::vector<int> workers;
|
||||
|
||||
if( last == REST_OF_THE_WORLD )
|
||||
{
|
||||
last = Node::comm().size() - 1;
|
||||
}
|
||||
|
||||
for(int i = first; i <= last; ++i)
|
||||
{
|
||||
workers.push_back( i );
|
||||
}
|
||||
init( workers, runs );
|
||||
}
|
||||
|
||||
StaticAssignmentAlgorithm::StaticAssignmentAlgorithm( int runs )
|
||||
{
|
||||
std::vector<int> workers;
|
||||
for(int i = 1; i < Node::comm().size(); ++i)
|
||||
{
|
||||
workers.push_back( i );
|
||||
}
|
||||
|
||||
init( workers, runs );
|
||||
}
|
||||
|
||||
StaticAssignmentAlgorithm::StaticAssignmentAlgorithm( int unique, int runs )
|
||||
{
|
||||
std::vector<int> workers;
|
||||
workers.push_back( unique );
|
||||
init( workers, runs );
|
||||
}
|
||||
|
||||
void StaticAssignmentAlgorithm::init( const std::vector<int> & workers, int runs )
|
||||
{
|
||||
unsigned int nbWorkers = workers.size();
|
||||
freeWorkers = nbWorkers;
|
||||
|
||||
busy.clear();
|
||||
busy.resize( nbWorkers, false );
|
||||
realRank = workers;
|
||||
|
||||
if( runs <= 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
attributions.clear();
|
||||
attributions.reserve( nbWorkers );
|
||||
|
||||
// Let be the euclidean division of runs by nbWorkers :
|
||||
// runs == q * nbWorkers + r, 0 <= r < nbWorkers
|
||||
// This one liner affects q requests to each worker
|
||||
for (unsigned int i = 0; i < nbWorkers; attributions[i++] = runs / nbWorkers) ;
|
||||
// The first line computes r and the one liner affects the remaining
|
||||
// r requests to workers, in ascending order
|
||||
unsigned int diff = runs - (runs / nbWorkers) * nbWorkers;
|
||||
for (unsigned int i = 0; i < diff; ++attributions[i++]);
|
||||
}
|
||||
|
||||
int StaticAssignmentAlgorithm::get( )
|
||||
{
|
||||
int assignee = -1;
|
||||
for( unsigned i = 0; i < busy.size(); ++i )
|
||||
{
|
||||
if( !busy[i] && attributions[i] > 0 )
|
||||
{
|
||||
busy[i] = true;
|
||||
--freeWorkers;
|
||||
assignee = realRank[ i ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return assignee;
|
||||
}
|
||||
|
||||
int StaticAssignmentAlgorithm::availableWorkers( )
|
||||
{
|
||||
return freeWorkers;
|
||||
}
|
||||
|
||||
std::vector<int> StaticAssignmentAlgorithm::idles()
|
||||
{
|
||||
std::vector<int> ret;
|
||||
for(unsigned int i = 0; i < busy.size(); ++i)
|
||||
{
|
||||
if( !busy[i] )
|
||||
{
|
||||
ret.push_back( realRank[i] );
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void StaticAssignmentAlgorithm::confirm( int rank )
|
||||
{
|
||||
int i = -1; // i is the real index in table
|
||||
for( unsigned int j = 0; j < realRank.size(); ++j )
|
||||
{
|
||||
if( realRank[j] == rank )
|
||||
{
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
--attributions[ i ];
|
||||
busy[ i ] = false;
|
||||
++freeWorkers;
|
||||
}
|
||||
|
||||
void StaticAssignmentAlgorithm::reinit( int runs )
|
||||
{
|
||||
init( realRank, runs );
|
||||
}
|
||||
}
|
||||
}
|
||||
239
eo/src/mpi/eoMpiAssignmentAlgorithm.h
Normal file
239
eo/src/mpi/eoMpiAssignmentAlgorithm.h
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __MPI_ASSIGNMENT_ALGORITHM_H__
|
||||
# define __MPI_ASSIGNMENT_ALGORITHM_H__
|
||||
|
||||
# include <vector> // std::vector
|
||||
|
||||
namespace eo
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
/**
|
||||
* @brief Constant indicating to use all the resting available workers, in assignment algorithms constructor
|
||||
* using an interval.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
extern const int REST_OF_THE_WORLD;
|
||||
|
||||
/**
|
||||
* @brief Contains informations on the available workers and allows to find assignees for jobs.
|
||||
*
|
||||
* Available workers are workers who aren't processing anything. When they've received an order, workers switch
|
||||
* from the state "available" to the state "busy", and the master has to wait for their response for considering
|
||||
* them available again.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
struct AssignmentAlgorithm
|
||||
{
|
||||
/**
|
||||
* @brief Gets the rank of an available worker, so as to send it a task.
|
||||
*
|
||||
* @return The MPI rank of an available worker, or -1 if there is no available worker.
|
||||
*/
|
||||
virtual int get( ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of total available workers.
|
||||
*
|
||||
* Before the first call, it is equal to the total number of present workers, as specified in the
|
||||
* specific assignment algorithm constructor. It allows the Job class to know when all the responses have
|
||||
* been received, by comparing this number to the total number of workers.
|
||||
*
|
||||
* @return Integer indicating how many workers are available.
|
||||
*/
|
||||
virtual int availableWorkers( ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Reinject the worker of indicated rank in the available state.
|
||||
*
|
||||
* @param wrkRank The MPI rank of the worker who has finished its job.
|
||||
*/
|
||||
virtual void confirm( int wrkRank ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Indicates who are the workers which do nothing.
|
||||
*
|
||||
* At the end of the algorithm, the master has to warn all the workers that it's done. All the workers mean,
|
||||
* the workers which are currently processing data, and the other ones who could be waiting : the idles.
|
||||
* This function indicates to the master which worker aren't doing anything.
|
||||
*
|
||||
* @return A std::vector containing all the MPI ranks of the idles workers.
|
||||
*/
|
||||
virtual std::vector<int> idles( ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Reinitializes the assignment algorithm with the right number of runs.
|
||||
*
|
||||
* In fact, this is only useful for static assignment algorithm, which has to be reinitialized every time
|
||||
* it's used, in the case of a Multi Job. It's the user's responsability to call this function.
|
||||
*
|
||||
* @todo Not really clean. Find a better way to do it.
|
||||
*/
|
||||
virtual void reinit( int runs ) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Assignment (scheduling) algorithm which handles workers in a queue.
|
||||
*
|
||||
* With this assignment algorithm, workers are put in a queue and may be called an unlimited number of times.
|
||||
* Whenever a worker returns, it is added to the queue, and it becomes available for the next call to get().
|
||||
* The available workers are all located in the queue at any time, so the number of available workers is
|
||||
* directly equal to the size of the queue.
|
||||
*
|
||||
* This kind of assignment is adapted for tasks whose execution time is stochastic or unknown, but without any
|
||||
* warranty to be faster than other assignments.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
struct DynamicAssignmentAlgorithm : public AssignmentAlgorithm
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Uses all the hosts whose rank is higher to 1, inclusive, as workers.
|
||||
*/
|
||||
DynamicAssignmentAlgorithm( );
|
||||
|
||||
/**
|
||||
* @brief Uses the unique host with given rank as a worker.
|
||||
*
|
||||
* @param unique MPI rank of the unique worker.
|
||||
*/
|
||||
DynamicAssignmentAlgorithm( int unique );
|
||||
|
||||
/**
|
||||
* @brief Uses the workers whose ranks are present in the argument as workers.
|
||||
*
|
||||
* @param workers std::vector containing MPI ranks of workers.
|
||||
*/
|
||||
DynamicAssignmentAlgorithm( const std::vector<int> & workers );
|
||||
|
||||
/**
|
||||
* @brief Uses a range of ranks as workers.
|
||||
*
|
||||
* @param first The first worker to be included (inclusive)
|
||||
* @param last The last worker to be included (inclusive). If last == eo::mpi::REST_OF_THE_WORLD, all
|
||||
* hosts whose rank is higher than first are taken.
|
||||
*/
|
||||
DynamicAssignmentAlgorithm( int first, int last );
|
||||
|
||||
virtual int get( );
|
||||
|
||||
int availableWorkers();
|
||||
|
||||
void confirm( int rank );
|
||||
|
||||
std::vector<int> idles( );
|
||||
|
||||
void reinit( int _ );
|
||||
|
||||
protected:
|
||||
std::vector< int > availableWrk;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Assignment algorithm which gives to each worker a precise number of tasks to do, in a round robin
|
||||
* fashion.
|
||||
*
|
||||
* This scheduling algorithm attributes, at initialization or when calling reinit(), a fixed amount of runs to
|
||||
* distribute to the workers. The amount of runs is then equally distributed between all workers ; if total
|
||||
* number of runs is not a direct multiple of workers number, then remainding unaffected runs are distributed to
|
||||
* workers from the first to the last, in a round-robin fashion.
|
||||
*
|
||||
* This scheduling should be used when the amount of runs can be computed or is fixed and when we guess that the
|
||||
* duration of processing task will be the same for each run. There is no warranty that this algorithm is more
|
||||
* or less efficient that another one. When having a doubt, use DynamicAssignmentAlgorithm.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
struct StaticAssignmentAlgorithm : public AssignmentAlgorithm
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Uses a given precise set of workers.
|
||||
*
|
||||
* @param workers std::vector of MPI ranks of workers which will be used.
|
||||
* @param runs Fixed amount of runs, strictly positive.
|
||||
*/
|
||||
StaticAssignmentAlgorithm( const std::vector<int>& workers, int runs );
|
||||
|
||||
/**
|
||||
* @brief Uses a range of workers.
|
||||
*
|
||||
* @param first The first MPI rank of worker to use
|
||||
* @param last The last MPI rank of worker to use. If it's equal to REST_OF_THE_WORLD, then all the
|
||||
* workers from the first one are taken as workers.
|
||||
* @param runs Fixed amount of runs, strictly positive.
|
||||
*/
|
||||
StaticAssignmentAlgorithm( int first, int last, int runs );
|
||||
|
||||
/**
|
||||
* @brief Uses all the hosts whose rank is higher than 1 (inclusive) as workers.
|
||||
*
|
||||
* @param runs Fixed amount of runs, strictly positive. If it's not set, you'll have to call reinit()
|
||||
* later.
|
||||
*/
|
||||
StaticAssignmentAlgorithm( int runs = 0 );
|
||||
|
||||
/**
|
||||
* @brief Uses an unique host as worker.
|
||||
*
|
||||
* @param unique The MPI rank of the host which will be the worker.
|
||||
* @param runs Fixed amount of runs, strictly positive.
|
||||
*/
|
||||
StaticAssignmentAlgorithm( int unique, int runs );
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Initializes the static scheduling.
|
||||
*
|
||||
* Gives to each worker an equal attribution number, equal to runs / workers.size(), eventually plus one
|
||||
* if number of workers is not a divisor of runs.
|
||||
*
|
||||
* @param workers Vector of hosts' ranks
|
||||
* @param runs Fixed amount of runs, strictly positive.
|
||||
*/
|
||||
void init( const std::vector<int> & workers, int runs );
|
||||
|
||||
public:
|
||||
int get( );
|
||||
|
||||
int availableWorkers( );
|
||||
|
||||
std::vector<int> idles();
|
||||
|
||||
void confirm( int rank );
|
||||
|
||||
void reinit( int runs );
|
||||
|
||||
private:
|
||||
std::vector<int> attributions;
|
||||
std::vector<int> realRank;
|
||||
std::vector<bool> busy;
|
||||
unsigned int freeWorkers;
|
||||
};
|
||||
}
|
||||
}
|
||||
# endif // __MPI_ASSIGNMENT_ALGORITHM_H__
|
||||
40
eo/src/mpi/eoMpiNode.cpp
Normal file
40
eo/src/mpi/eoMpiNode.cpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# include "eoMpiNode.h"
|
||||
|
||||
namespace eo
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
void Node::init( int argc, char** argv )
|
||||
{
|
||||
static bmpi::environment env( argc, argv );
|
||||
}
|
||||
|
||||
bmpi::communicator& Node::comm()
|
||||
{
|
||||
return _comm;
|
||||
}
|
||||
|
||||
bmpi::communicator Node::_comm;
|
||||
}
|
||||
}
|
||||
65
eo/src/mpi/eoMpiNode.h
Normal file
65
eo/src/mpi/eoMpiNode.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __MPI_NODE_H__
|
||||
# define __MPI_NODE_H__
|
||||
|
||||
# include "implMpi.h"
|
||||
namespace bmpi = mpi;
|
||||
|
||||
namespace eo
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
/**
|
||||
* @brief Global object used to reach mpi::communicator everywhere.
|
||||
*
|
||||
* mpi::communicator is the main object used to send and receive messages between the different hosts of
|
||||
* a MPI algorithm.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Initializes the MPI environment with argc and argv.
|
||||
*
|
||||
* Should be called at the beginning of every parallel program.
|
||||
*
|
||||
* @param argc Main's argc
|
||||
* @param argv Main's argv
|
||||
*/
|
||||
static void init( int argc, char** argv );
|
||||
|
||||
/**
|
||||
* @brief Returns the global mpi::communicator
|
||||
*/
|
||||
static bmpi::communicator& comm();
|
||||
|
||||
protected:
|
||||
static bmpi::communicator _comm;
|
||||
};
|
||||
}
|
||||
}
|
||||
# endif // __MPI_NODE_H__
|
||||
|
||||
515
eo/src/mpi/eoMultiStart.h
Normal file
515
eo/src/mpi/eoMultiStart.h
Normal file
|
|
@ -0,0 +1,515 @@
|
|||
# ifndef __EO_MULTISTART_H__
|
||||
# define __EO_MULTISTART_H__
|
||||
|
||||
# include <eo>
|
||||
# include "eoMpi.h"
|
||||
|
||||
/**
|
||||
* @ingroup MPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eoMultiStart.h
|
||||
*
|
||||
* Contains implementation of a MPI job which consists in a multi start, which basically consists in the following:
|
||||
* the same eoAlgo is launched on computers of a clusters, with different seeds for each. As the eoAlgo are most of
|
||||
* the time stochastics, the results won't be the same. It is fully equivalent to launch the same program but with
|
||||
* different seeds.
|
||||
*
|
||||
* It follows the structure of a MPI job, as described in eoMpi.h. The basic algorithm is trivial:
|
||||
* - Loop while we have a run to perform.
|
||||
* - Worker performs runs and send their best solution (individual with best fitness) to the master.
|
||||
* - Master retrieves the best solution and adds it to a eoPop of best solutions (the user can chooses what he does
|
||||
* with this population, for instance: retrieve the best element, etc.)
|
||||
*
|
||||
* The principal concerns about this algorithm are:
|
||||
* - How do we reinitialize the algorithm? An eoAlgo can have several forms, and initializations have to be performed
|
||||
* before each "start". We can hence decide whether we reinits the population or keep the same population obtained
|
||||
* after the previous start, we have to reinitialize continuator, etc. This is customizable in the store.
|
||||
*
|
||||
* - Which seeds should be chosen? If we want the run to be re-runnable with the same results, we need to be sure that
|
||||
* the seeds are the same. But user can not care about this, and just want random seeds. This is customizable in the
|
||||
* store.
|
||||
*
|
||||
* These concerns are handled by functors, inheriting from MultiStartStore<EOT>::ResetAlgo (for the first concern), and
|
||||
* MultiStartStore<EOT>::GetSeeds (for the second one). There are default implementations, but there is no problem about
|
||||
* specializing them or coding your own, by directly inheriting from them.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
|
||||
namespace eo
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
/**
|
||||
* @brief Data used by the Multi Start job.
|
||||
*
|
||||
* This data is shared between the different Job functors. More details are given for each attribute.
|
||||
*/
|
||||
template< class EOT >
|
||||
struct MultiStartData
|
||||
{
|
||||
typedef eoUF< eoPop<EOT>&, void> ResetAlgo;
|
||||
|
||||
MultiStartData(
|
||||
bmpi::communicator& _comm,
|
||||
eoAlgo<EOT>& _algo,
|
||||
int _masterRank,
|
||||
ResetAlgo & _resetAlgo )
|
||||
:
|
||||
runs( 0 ), bests(), pop(),
|
||||
comm( _comm ), algo( _algo ), resetAlgo( _resetAlgo ), masterRank( _masterRank )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
// dynamic parameters
|
||||
/**
|
||||
* @brief Total remaining number of runs.
|
||||
*
|
||||
* It's decremented as the runs are performed.
|
||||
*/
|
||||
int runs;
|
||||
|
||||
/**
|
||||
* @brief eoPop of the best individuals, which are the one sent by the workers.
|
||||
*/
|
||||
eoPop< EOT > bests;
|
||||
|
||||
/**
|
||||
* @brief eoPop on which the worker is working.
|
||||
*/
|
||||
eoPop< EOT > pop;
|
||||
|
||||
// static parameters
|
||||
/**
|
||||
* @brief Communicator, used to send and retrieve messages.
|
||||
*/
|
||||
bmpi::communicator& comm;
|
||||
|
||||
/**
|
||||
* @brief Algorithm which will be performed by the worker.
|
||||
*/
|
||||
eoAlgo<EOT>& algo;
|
||||
|
||||
/**
|
||||
* @brief Reset Algo functor, which defines how to reset the algo (above) before re running it.
|
||||
*/
|
||||
ResetAlgo& resetAlgo;
|
||||
|
||||
// Rank of master
|
||||
int masterRank;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Send task (master side) in the Multi Start job.
|
||||
*
|
||||
* It only consists in decrementing the number of runs, as the worker already have the population and
|
||||
* all the necessary parameters to run the eoAlgo.
|
||||
*/
|
||||
template< class EOT >
|
||||
class SendTaskMultiStart : public SendTaskFunction< MultiStartData< EOT > >
|
||||
{
|
||||
public:
|
||||
using SendTaskFunction< MultiStartData< EOT > >::_data;
|
||||
|
||||
void operator()( int wrkRank )
|
||||
{
|
||||
wrkRank++; // unused
|
||||
--(_data->runs);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Handle Response (master side) in the Multi Start job.
|
||||
*
|
||||
* It consists in retrieving the best solution sent by the worker and adds it to a population of best
|
||||
* solutions.
|
||||
*/
|
||||
template< class EOT >
|
||||
class HandleResponseMultiStart : public HandleResponseFunction< MultiStartData< EOT > >
|
||||
{
|
||||
public:
|
||||
using HandleResponseFunction< MultiStartData< EOT > >::_data;
|
||||
|
||||
void operator()( int wrkRank )
|
||||
{
|
||||
EOT individual;
|
||||
MultiStartData< EOT >& d = *_data;
|
||||
d.comm.recv( wrkRank, eo::mpi::Channel::Messages, individual );
|
||||
d.bests.push_back( individual );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Process Task (worker side) in the Multi Start job.
|
||||
*
|
||||
* Consists in resetting the algorithm and launching it on the population, then
|
||||
* send the best individual (the one with the best fitness) to the master.
|
||||
*/
|
||||
template< class EOT >
|
||||
class ProcessTaskMultiStart : public ProcessTaskFunction< MultiStartData< EOT > >
|
||||
{
|
||||
public:
|
||||
using ProcessTaskFunction< MultiStartData<EOT > >::_data;
|
||||
|
||||
void operator()()
|
||||
{
|
||||
_data->resetAlgo( _data->pop );
|
||||
_data->algo( _data->pop );
|
||||
_data->comm.send( _data->masterRank, eo::mpi::Channel::Messages, _data->pop.best_element() );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Is Finished (master side) in the Multi Start job.
|
||||
*
|
||||
* The job is finished if and only if all the runs have been performed.
|
||||
*/
|
||||
template< class EOT >
|
||||
class IsFinishedMultiStart : public IsFinishedFunction< MultiStartData< EOT > >
|
||||
{
|
||||
public:
|
||||
using IsFinishedFunction< MultiStartData< EOT > >::_data;
|
||||
|
||||
bool operator()()
|
||||
{
|
||||
return _data->runs <= 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Store for the Multi Start job.
|
||||
*
|
||||
* Contains the data used by the workers (algo,...) and functor to
|
||||
* send the seeds.
|
||||
*/
|
||||
template< class EOT >
|
||||
class MultiStartStore : public JobStore< MultiStartData< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Generic functor to reset an algorithm before it's launched by
|
||||
* the worker.
|
||||
*
|
||||
* This reset algorithm should reinits population (if necessary), continuator, etc.
|
||||
*/
|
||||
typedef typename MultiStartData<EOT>::ResetAlgo ResetAlgo;
|
||||
|
||||
/**
|
||||
* @brief Generic functor which returns a vector of seeds for the workers.
|
||||
*
|
||||
* If this vector hasn't enough seeds to send, random ones are generated and
|
||||
* sent to the workers.
|
||||
*/
|
||||
typedef eoUF< int, std::vector<int> > GetSeeds;
|
||||
|
||||
/**
|
||||
* @brief Default ctor for MultiStartStore.
|
||||
*
|
||||
* @param algo The algorithm to launch in parallel
|
||||
* @param masterRank The MPI rank of the master
|
||||
* @param resetAlgo The ResetAlgo functor
|
||||
* @param getSeeds The GetSeeds functor
|
||||
*/
|
||||
MultiStartStore(
|
||||
eoAlgo<EOT> & algo,
|
||||
int masterRank,
|
||||
ResetAlgo & resetAlgo,
|
||||
GetSeeds & getSeeds
|
||||
)
|
||||
: _data( eo::mpi::Node::comm(), algo, masterRank, resetAlgo ),
|
||||
_getSeeds( getSeeds ),
|
||||
_masterRank( masterRank )
|
||||
{
|
||||
// Default job functors for this one.
|
||||
this->_iff = new IsFinishedMultiStart< EOT >;
|
||||
this->_iff->needDelete(true);
|
||||
this->_stf = new SendTaskMultiStart< EOT >;
|
||||
this->_stf->needDelete(true);
|
||||
this->_hrf = new HandleResponseMultiStart< EOT >;
|
||||
this->_hrf->needDelete(true);
|
||||
this->_ptf = new ProcessTaskMultiStart< EOT >;
|
||||
this->_ptf->needDelete(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send new seeds to the workers before a job.
|
||||
*
|
||||
* Uses the GetSeeds functor given in constructor. If there's not
|
||||
* enough seeds to send, random seeds are sent to the workers.
|
||||
*
|
||||
* @param workers Vector of MPI ranks of the workers
|
||||
* @param runs The number of runs to perform
|
||||
*/
|
||||
void init( const std::vector<int>& workers, int runs )
|
||||
{
|
||||
_data.runs = runs;
|
||||
|
||||
unsigned nbWorkers = workers.size();
|
||||
std::vector< int > seeds = _getSeeds( nbWorkers );
|
||||
if( eo::mpi::Node::comm().rank() == _masterRank )
|
||||
{
|
||||
if( seeds.size() < nbWorkers )
|
||||
{
|
||||
// Random seeds
|
||||
for( unsigned i = seeds.size(); i < nbWorkers; ++i )
|
||||
{
|
||||
seeds.push_back( eo::rng.rand() );
|
||||
}
|
||||
}
|
||||
|
||||
for( unsigned i = 0 ; i < nbWorkers ; ++i )
|
||||
{
|
||||
int wrkRank = workers[i];
|
||||
eo::mpi::Node::comm().send( wrkRank, eo::mpi::Channel::Commands, seeds[ i ] );
|
||||
}
|
||||
} else
|
||||
{
|
||||
int seed;
|
||||
eo::mpi::Node::comm().recv( _masterRank, eo::mpi::Channel::Commands, seed );
|
||||
eo::log << eo::debug << eo::mpi::Node::comm().rank() << "- Seed: " << seed << std::endl;
|
||||
eo::rng.reseed( seed );
|
||||
}
|
||||
}
|
||||
|
||||
MultiStartData<EOT>* data()
|
||||
{
|
||||
return &_data;
|
||||
}
|
||||
|
||||
private:
|
||||
MultiStartData< EOT > _data;
|
||||
GetSeeds & _getSeeds;
|
||||
int _masterRank;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief MultiStart job, created for convenience.
|
||||
*
|
||||
* This is an OneShotJob, which means workers leave it along with
|
||||
* the master.
|
||||
*/
|
||||
template< class EOT >
|
||||
class MultiStart : public OneShotJob< MultiStartData< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
MultiStart( AssignmentAlgorithm & algo,
|
||||
int masterRank,
|
||||
MultiStartStore< EOT > & store,
|
||||
// dynamic parameters
|
||||
int runs ) :
|
||||
OneShotJob< MultiStartData< EOT > >( algo, masterRank, store )
|
||||
{
|
||||
store.init( algo.idles(), runs );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the best solution, at the end of the job.
|
||||
*
|
||||
* Warning: if you call this function from a worker, or from the master before the
|
||||
* launch of the job, you will only get an empty population!
|
||||
*
|
||||
* @return Population of best individuals retrieved by the master.
|
||||
*/
|
||||
eoPop<EOT>& best_individuals()
|
||||
{
|
||||
return this->store.data()->bests;
|
||||
}
|
||||
};
|
||||
|
||||
/*************************************
|
||||
* DEFAULT GET SEEDS IMPLEMENTATIONS *
|
||||
************************************/
|
||||
|
||||
/**
|
||||
* @brief Uses the internal default seed generator to get seeds,
|
||||
* which means: random seeds are sent.
|
||||
*/
|
||||
template<class EOT>
|
||||
struct DummyGetSeeds : public MultiStartStore<EOT>::GetSeeds
|
||||
{
|
||||
std::vector<int> operator()( int n )
|
||||
{
|
||||
return std::vector<int>();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Sends seeds to the workers, which are multiple of a number
|
||||
* given by the master. If no number is given, a random one is used.
|
||||
*
|
||||
* This functor ensures that even if the same store is used with
|
||||
* different jobs, the seeds will be different.
|
||||
*/
|
||||
template<class EOT>
|
||||
struct MultiplesOfNumber : public MultiStartStore<EOT>::GetSeeds
|
||||
{
|
||||
MultiplesOfNumber ( int n = 0 )
|
||||
{
|
||||
while( n == 0 )
|
||||
{
|
||||
n = eo::rng.rand();
|
||||
}
|
||||
_seed = n;
|
||||
_i = 0;
|
||||
}
|
||||
|
||||
std::vector<int> operator()( int n )
|
||||
{
|
||||
std::vector<int> ret;
|
||||
for( unsigned int i = 0; i < n; ++i )
|
||||
{
|
||||
ret.push_back( (++_i) * _seed );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
unsigned int _seed;
|
||||
unsigned int _i;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Returns random seeds to the workers. We can controle which seeds are generated
|
||||
* by precising the seed of the master.
|
||||
*/
|
||||
template<class EOT>
|
||||
struct GetRandomSeeds : public MultiStartStore<EOT>::GetSeeds
|
||||
{
|
||||
GetRandomSeeds( int seed )
|
||||
{
|
||||
eo::rng.reseed( seed );
|
||||
}
|
||||
|
||||
std::vector<int> operator()( int n )
|
||||
{
|
||||
std::vector<int> ret;
|
||||
for(int i = 0; i < n; ++i)
|
||||
{
|
||||
ret.push_back( eo::rng.rand() );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************
|
||||
* DEFAULT RESET ALGO IMPLEMENTATIONS *
|
||||
**************************************/
|
||||
|
||||
/**
|
||||
* @brief For a Genetic Algorithm, reinits the population by copying the original one
|
||||
* given in constructor, and reinits the continuator.
|
||||
*
|
||||
* The evaluator should also be given, as the population needs to be evaluated
|
||||
* before each run.
|
||||
*/
|
||||
template<class EOT>
|
||||
struct ReuseOriginalPopEA: public MultiStartStore<EOT>::ResetAlgo
|
||||
{
|
||||
ReuseOriginalPopEA(
|
||||
eoCountContinue<EOT> & continuator,
|
||||
const eoPop<EOT>& originalPop,
|
||||
eoEvalFunc<EOT>& eval) :
|
||||
_continuator( continuator ),
|
||||
_originalPop( originalPop ),
|
||||
_pop_eval( eval )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
ReuseOriginalPopEA(
|
||||
eoCountContinue<EOT> & continuator,
|
||||
const eoPop<EOT>& originalPop,
|
||||
eoPopEvalFunc<EOT>& pop_eval
|
||||
) :
|
||||
_continuator( continuator ),
|
||||
_originalPop( originalPop ),
|
||||
_pop_eval( pop_eval )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
void operator()( eoPop<EOT>& pop )
|
||||
{
|
||||
pop = _originalPop; // copies the original population
|
||||
_pop_eval( pop, pop );
|
||||
_continuator.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
eoCountContinue<EOT> & _continuator;
|
||||
const eoPop<EOT>& _originalPop;
|
||||
eoPopEvalFunc<EOT>& _pop_eval;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief For a Genetic Algorithm, reuses the same population without
|
||||
* modifying it after a run.
|
||||
*
|
||||
* This means, if you launch a run after another one, you'll make evolve
|
||||
* the same population.
|
||||
*
|
||||
* The evaluator should also be sent, as the population needs to be evaluated
|
||||
* at the first time.
|
||||
*/
|
||||
template< class EOT >
|
||||
struct ReuseSamePopEA : public MultiStartStore<EOT>::ResetAlgo
|
||||
{
|
||||
ReuseSamePopEA(
|
||||
eoCountContinue<EOT>& continuator,
|
||||
const eoPop<EOT>& originalPop,
|
||||
eoEvalFunc<EOT>& eval
|
||||
) :
|
||||
_continuator( continuator ),
|
||||
_originalPop( originalPop ),
|
||||
_firstTime( true )
|
||||
{
|
||||
for( unsigned i = 0, size = originalPop.size();
|
||||
i < size; ++i )
|
||||
{
|
||||
eval(_originalPop[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ReuseSamePopEA(
|
||||
eoCountContinue<EOT>& continuator,
|
||||
const eoPop<EOT>& originalPop,
|
||||
eoPopEvalFunc<EOT>& pop_eval
|
||||
) :
|
||||
_continuator( continuator ),
|
||||
_originalPop( originalPop ),
|
||||
_firstTime( true )
|
||||
{
|
||||
pop_eval( _originalPop, _originalPop );
|
||||
}
|
||||
|
||||
void operator()( eoPop<EOT>& pop )
|
||||
{
|
||||
if( _firstTime )
|
||||
{
|
||||
pop = _originalPop;
|
||||
_firstTime = false;
|
||||
}
|
||||
_continuator.reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
eoCountContinue<EOT>& _continuator;
|
||||
eoPop<EOT> _originalPop;
|
||||
bool _firstTime;
|
||||
};
|
||||
} // namespace mpi
|
||||
} // namespace eo
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
# endif // __EO_MULTISTART_H__
|
||||
387
eo/src/mpi/eoParallelApply.h
Normal file
387
eo/src/mpi/eoParallelApply.h
Normal file
|
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EO_PARALLEL_APPLY_H__
|
||||
# define __EO_PARALLEL_APPLY_H__
|
||||
|
||||
# include "eoMpi.h"
|
||||
|
||||
# include <eoFunctor.h> // eoUF
|
||||
# include <vector> // std::vector population
|
||||
|
||||
/**
|
||||
* @file eoParallelApply.h
|
||||
*
|
||||
* @brief Applies a functor with single parameter to elements of a table, in a parallel fashion.
|
||||
*
|
||||
* This file contains all the required classes to do a parallel apply of a table, in a parallel fashion. This can be
|
||||
* very useful when applying the function can be made without any dependances within the data. In EO, it occurs in
|
||||
* particular during the evaluation: the number of individuals to evaluate can be really high, and the evaluation of one
|
||||
* individual is independant from the evaluation of other individuals.
|
||||
*
|
||||
* Elements in the table are directly replaced, as the table is given by reference. No new table is made during the
|
||||
* process.
|
||||
*
|
||||
* User can tune this job, indicating how many elements of the table should be sent and evaluated by a worker, at a
|
||||
* time: this is called the "packet size", as individuals are groupped into a packet of individuals which are sent to
|
||||
* the worker before evaluation. The problem of choosing the optimal packet size is beyond the purposes of this documentation
|
||||
* and deserves a theoritical study.
|
||||
*
|
||||
* This job is the parallel equivalent to the function apply<EOT>, defined in apply.h. It just applies the function to
|
||||
* every element of a table. In Python or Javascript, it's the equivalent of the function Map.
|
||||
*/
|
||||
|
||||
namespace eo
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
/**
|
||||
* @brief Structure used to save assignment to a worker, i.e which slice of the table it has to process.
|
||||
*
|
||||
* This slice is defined by the index of the first evaluated argument and the number of processed elements.
|
||||
*/
|
||||
struct ParallelApplyAssignment
|
||||
{
|
||||
int index;
|
||||
int size;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Data useful for a parallel apply (map).
|
||||
*
|
||||
* A parallel apply needs at least the functor to apply to every element of the table, and the table itself,
|
||||
* whereas it can be set later with the function init(). Master rank is also needed, to send it informations and
|
||||
* receive informations from it, inside the functors (the job knows these values, but the functors don't). The
|
||||
* size of a packet can be tuned here.
|
||||
*
|
||||
* Internal attributes contain:
|
||||
* - (useful for master) the index of the next element to be evaluated.
|
||||
* - (useful for master) a map containing links between MPI ranks and slices of the table which the worker with
|
||||
* this rank has evaluated. Without this map, when receiving results from a worker, the master couldn't be
|
||||
* able to replace the right elements in the table.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
template<class EOT>
|
||||
struct ParallelApplyData
|
||||
{
|
||||
/**
|
||||
* @brief Ctor for Parallel apply (map) data.
|
||||
*
|
||||
* @param _proc The functor to apply on each element in the table
|
||||
* @param _masterRank The MPI rank of the master
|
||||
* @param _packetSize The number of elements on which the function will be applied by the worker, at a time.
|
||||
* @param table The table to apply. If this value is NULL, user will have to call init() before launching the
|
||||
* job.
|
||||
*/
|
||||
ParallelApplyData(
|
||||
eoUF<EOT&, void> & _proc,
|
||||
int _masterRank,
|
||||
int _packetSize,
|
||||
std::vector<EOT> * table = 0
|
||||
) :
|
||||
_table( table ), func( _proc ), index( 0 ), packetSize( _packetSize ), masterRank( _masterRank ), comm( Node::comm() )
|
||||
{
|
||||
if ( _packetSize <= 0 )
|
||||
{
|
||||
throw std::runtime_error("Packet size should not be negative.");
|
||||
}
|
||||
|
||||
if( table )
|
||||
{
|
||||
size = table->size();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reinitializes the data for a new table to evaluate.
|
||||
*/
|
||||
void init( std::vector<EOT>& table )
|
||||
{
|
||||
index = 0;
|
||||
size = table.size();
|
||||
_table = &table;
|
||||
assignedTasks.clear();
|
||||
}
|
||||
|
||||
std::vector<EOT>& table()
|
||||
{
|
||||
return *_table;
|
||||
}
|
||||
|
||||
// All elements are public since functors will often use them.
|
||||
std::vector<EOT> * _table;
|
||||
eoUF<EOT&, void> & func;
|
||||
int index;
|
||||
int size;
|
||||
std::map< int /* worker rank */, ParallelApplyAssignment /* last assignment */> assignedTasks;
|
||||
int packetSize;
|
||||
std::vector<EOT> tempArray;
|
||||
|
||||
int masterRank;
|
||||
bmpi::communicator& comm;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Send task functor implementation for the parallel apply (map) job.
|
||||
*
|
||||
* Master side: Sends a slice of the table to evaluate to the worker.
|
||||
*
|
||||
* Implementation details:
|
||||
* Finds the next slice of data to send to the worker, sends first the size and then the data, and memorizes
|
||||
* that this slice has been distributed to the worker, then updates the next position of element to evaluate.
|
||||
*/
|
||||
template< class EOT >
|
||||
class SendTaskParallelApply : public SendTaskFunction< ParallelApplyData<EOT> >
|
||||
{
|
||||
public:
|
||||
using SendTaskFunction< ParallelApplyData<EOT> >::_data;
|
||||
|
||||
SendTaskParallelApply( SendTaskParallelApply<EOT> * w = 0 ) : SendTaskFunction< ParallelApplyData<EOT> >( w )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
void operator()(int wrkRank)
|
||||
{
|
||||
int futureIndex;
|
||||
|
||||
if( _data->index + _data->packetSize < _data->size )
|
||||
{
|
||||
futureIndex = _data->index + _data->packetSize;
|
||||
} else {
|
||||
futureIndex = _data->size;
|
||||
}
|
||||
|
||||
int sentSize = futureIndex - _data->index ;
|
||||
|
||||
_data->comm.send( wrkRank, eo::mpi::Channel::Messages, sentSize );
|
||||
|
||||
eo::log << eo::debug << "Evaluating individual " << _data->index << std::endl;
|
||||
|
||||
_data->assignedTasks[ wrkRank ].index = _data->index;
|
||||
_data->assignedTasks[ wrkRank ].size = sentSize;
|
||||
|
||||
_data->comm.send( wrkRank, eo::mpi::Channel::Messages, & ( (_data->table())[ _data->index ] ) , sentSize );
|
||||
_data->index = futureIndex;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Handle response functor implementation for the parallel apply (map) job.
|
||||
*
|
||||
* Master side: Replaces the slice of data attributed to the worker in the table.
|
||||
*/
|
||||
template< class EOT >
|
||||
class HandleResponseParallelApply : public HandleResponseFunction< ParallelApplyData<EOT> >
|
||||
{
|
||||
public:
|
||||
using HandleResponseFunction< ParallelApplyData<EOT> >::_data;
|
||||
|
||||
HandleResponseParallelApply( HandleResponseParallelApply<EOT> * w = 0 ) : HandleResponseFunction< ParallelApplyData<EOT> >( w )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
void operator()(int wrkRank)
|
||||
{
|
||||
_data->comm.recv( wrkRank, eo::mpi::Channel::Messages, & (_data->table()[ _data->assignedTasks[wrkRank].index ] ), _data->assignedTasks[wrkRank].size );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Process task functor implementation for the parallel apply (map) job.
|
||||
*
|
||||
* Worker side: apply the function to the given slice of data.
|
||||
*
|
||||
* Implementation details: retrieves the number of elements to evaluate, retrieves them, applies the function
|
||||
* and then returns the results.
|
||||
*/
|
||||
template< class EOT >
|
||||
class ProcessTaskParallelApply : public ProcessTaskFunction< ParallelApplyData<EOT> >
|
||||
{
|
||||
public:
|
||||
using ProcessTaskFunction< ParallelApplyData<EOT> >::_data;
|
||||
|
||||
ProcessTaskParallelApply( ProcessTaskParallelApply<EOT> * w = 0 ) : ProcessTaskFunction< ParallelApplyData<EOT> >( w )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
int recvSize;
|
||||
|
||||
_data->comm.recv( _data->masterRank, eo::mpi::Channel::Messages, recvSize );
|
||||
_data->tempArray.resize( recvSize );
|
||||
_data->comm.recv( _data->masterRank, eo::mpi::Channel::Messages, & _data->tempArray[0] , recvSize );
|
||||
timerStat.start("worker_processes");
|
||||
for( int i = 0; i < recvSize ; ++i )
|
||||
{
|
||||
_data->func( _data->tempArray[ i ] );
|
||||
}
|
||||
timerStat.stop("worker_processes");
|
||||
_data->comm.send( _data->masterRank, eo::mpi::Channel::Messages, & _data->tempArray[0], recvSize );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Is finished functor implementation for the parallel apply (map) job.
|
||||
*
|
||||
* Master side: returns true if and only if the whole table has been evaluated. The job is also terminated only
|
||||
* when the whole table has been evaluated.
|
||||
*/
|
||||
template< class EOT >
|
||||
class IsFinishedParallelApply : public IsFinishedFunction< ParallelApplyData<EOT> >
|
||||
{
|
||||
public:
|
||||
using IsFinishedFunction< ParallelApplyData<EOT> >::_data;
|
||||
|
||||
IsFinishedParallelApply( IsFinishedParallelApply<EOT> * w = 0 ) : IsFinishedFunction< ParallelApplyData<EOT> >( w )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
bool operator()()
|
||||
{
|
||||
return _data->index == _data->size;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Store containing all the datas and the functors for the parallel apply (map) job.
|
||||
*
|
||||
* User can tune functors when constructing the object. For each functor which is not given, a default one is
|
||||
* generated.
|
||||
*
|
||||
* @ingroup MPI
|
||||
*/
|
||||
template< class EOT >
|
||||
struct ParallelApplyStore : public JobStore< ParallelApplyData<EOT> >
|
||||
{
|
||||
using JobStore< ParallelApplyData<EOT> >::_stf;
|
||||
using JobStore< ParallelApplyData<EOT> >::_hrf;
|
||||
using JobStore< ParallelApplyData<EOT> >::_ptf;
|
||||
using JobStore< ParallelApplyData<EOT> >::_iff;
|
||||
|
||||
/**
|
||||
* @brief Main constructor for the parallel apply (map) job.
|
||||
*
|
||||
* @param _proc The procedure to apply to each element of the table.
|
||||
* @param _masterRank The rank of the master process.
|
||||
* @param _packetSize The number of elements of the table to be evaluated at a time, by the worker.
|
||||
* @param stpa Pointer to Send Task parallel apply functor descendant. If null, a default one is used.
|
||||
* @param hrpa Pointer to Handle Response parallel apply functor descendant. If null, a default one is used.
|
||||
* @param ptpa Pointer to Process Task parallel apply functor descendant. If null, a default one is used.
|
||||
* @param ifpa Pointer to Is Finished parallel apply functor descendant. If null, a default one is used.
|
||||
*/
|
||||
ParallelApplyStore(
|
||||
eoUF<EOT&, void> & _proc,
|
||||
int _masterRank,
|
||||
int _packetSize = 1,
|
||||
// JobStore functors
|
||||
SendTaskParallelApply<EOT> * stpa = 0,
|
||||
HandleResponseParallelApply<EOT>* hrpa = 0,
|
||||
ProcessTaskParallelApply<EOT>* ptpa = 0,
|
||||
IsFinishedParallelApply<EOT>* ifpa = 0
|
||||
) :
|
||||
_data( _proc, _masterRank, _packetSize )
|
||||
{
|
||||
if( stpa == 0 ) {
|
||||
stpa = new SendTaskParallelApply<EOT>;
|
||||
stpa->needDelete( true );
|
||||
}
|
||||
|
||||
if( hrpa == 0 ) {
|
||||
hrpa = new HandleResponseParallelApply<EOT>;
|
||||
hrpa->needDelete( true );
|
||||
}
|
||||
|
||||
if( ptpa == 0 ) {
|
||||
ptpa = new ProcessTaskParallelApply<EOT>;
|
||||
ptpa->needDelete( true );
|
||||
}
|
||||
|
||||
if( ifpa == 0 ) {
|
||||
ifpa = new IsFinishedParallelApply<EOT>;
|
||||
ifpa->needDelete( true );
|
||||
}
|
||||
|
||||
_stf = stpa;
|
||||
_hrf = hrpa;
|
||||
_ptf = ptpa;
|
||||
_iff = ifpa;
|
||||
}
|
||||
|
||||
ParallelApplyData<EOT>* data() { return &_data; }
|
||||
|
||||
/**
|
||||
* @brief Reinits the store with a new table to evaluate.
|
||||
*
|
||||
* @param _pop The table of elements to be evaluated.
|
||||
*/
|
||||
void data( std::vector<EOT>& _pop )
|
||||
{
|
||||
_data.init( _pop );
|
||||
}
|
||||
|
||||
virtual ~ParallelApplyStore() // for inheritance purposes only
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
ParallelApplyData<EOT> _data;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Parallel apply job. Present for convenience only.
|
||||
*
|
||||
* A typedef wouldn't have been working, as typedef on templates don't work in C++. Traits would be a
|
||||
* disgraceful overload for the user.
|
||||
*
|
||||
* @ingroup MPI
|
||||
* @see eoParallelApply.h
|
||||
*/
|
||||
template< typename EOT >
|
||||
class ParallelApply : public MultiJob< ParallelApplyData<EOT> >
|
||||
{
|
||||
public:
|
||||
|
||||
ParallelApply(
|
||||
AssignmentAlgorithm & algo,
|
||||
int _masterRank,
|
||||
ParallelApplyStore<EOT> & store
|
||||
) :
|
||||
MultiJob< ParallelApplyData<EOT> >( algo, _masterRank, store )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @example t-mpi-parallelApply.cpp
|
||||
* @example t-mpi-multipleRoles.cpp
|
||||
*/
|
||||
}
|
||||
}
|
||||
# endif // __EO_PARALLEL_APPLY_H__
|
||||
|
||||
|
||||
140
eo/src/mpi/eoTerminateJob.h
Normal file
140
eo/src/mpi/eoTerminateJob.h
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EO_TERMINATE_H__
|
||||
# define __EO_TERMINATE_H__
|
||||
|
||||
# include "eoMpi.h"
|
||||
|
||||
namespace eo
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
/**
|
||||
* @ingroup MPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Send task functor which does nothing.
|
||||
*/
|
||||
struct DummySendTaskFunction : public SendTaskFunction<void>
|
||||
{
|
||||
void operator()( int _ )
|
||||
{
|
||||
++_;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Handle response functor which does nothing.
|
||||
*/
|
||||
struct DummyHandleResponseFunction : public HandleResponseFunction<void>
|
||||
{
|
||||
void operator()( int _ )
|
||||
{
|
||||
++_;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Process task functor which does nothing.
|
||||
*/
|
||||
struct DummyProcessTaskFunction : public ProcessTaskFunction<void>
|
||||
{
|
||||
void operator()()
|
||||
{
|
||||
// nothing!
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Is finished functor which returns true everytime.
|
||||
*/
|
||||
struct DummyIsFinishedFunction : public IsFinishedFunction<void>
|
||||
{
|
||||
bool operator()()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Job store containing all dummy functors and containing no data.
|
||||
*/
|
||||
struct DummyJobStore : public JobStore<void>
|
||||
{
|
||||
using JobStore<void>::_stf;
|
||||
using JobStore<void>::_hrf;
|
||||
using JobStore<void>::_ptf;
|
||||
using JobStore<void>::_iff;
|
||||
|
||||
DummyJobStore()
|
||||
{
|
||||
_stf = new DummySendTaskFunction;
|
||||
_stf->needDelete( true );
|
||||
_hrf = new DummyHandleResponseFunction;
|
||||
_hrf->needDelete( true );
|
||||
_ptf = new DummyProcessTaskFunction;
|
||||
_ptf->needDelete( true );
|
||||
_iff = new DummyIsFinishedFunction;
|
||||
_iff->needDelete( true );
|
||||
}
|
||||
|
||||
void* data() { return 0; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Job to run after a Multi Job, so as to indicate that every workers should terminate.
|
||||
*/
|
||||
struct EmptyJob : public OneShotJob<void>
|
||||
{
|
||||
/**
|
||||
* @brief Main EmptyJob ctor
|
||||
*
|
||||
* @param algo Assignment (scheduling) algorithm used.
|
||||
* @param masterRank The rank of the master process.
|
||||
*/
|
||||
EmptyJob( AssignmentAlgorithm& algo, int masterRank ) :
|
||||
OneShotJob<void>( algo, masterRank, *(new DummyJobStore) )
|
||||
// the job store is deleted on destructor
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
~EmptyJob()
|
||||
{
|
||||
std::vector< int > idles = assignmentAlgo.idles();
|
||||
for(unsigned i = 0, size = idles.size(); i < size; ++i)
|
||||
{
|
||||
comm.send( idles[i], Channel::Commands, Message::Kill );
|
||||
}
|
||||
delete & this->store;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
# endif // __EO_TERMINATE_H__
|
||||
166
eo/src/mpi/implMpi.cpp
Normal file
166
eo/src/mpi/implMpi.cpp
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# include "implMpi.h"
|
||||
|
||||
namespace mpi
|
||||
{
|
||||
const int any_source = MPI_ANY_SOURCE;
|
||||
const int any_tag = MPI_ANY_TAG;
|
||||
|
||||
environment::environment(int argc, char**argv)
|
||||
{
|
||||
MPI_Init(&argc, &argv);
|
||||
}
|
||||
|
||||
environment::~environment()
|
||||
{
|
||||
MPI_Finalize();
|
||||
}
|
||||
|
||||
status::status( const MPI_Status & s )
|
||||
{
|
||||
_source = s.MPI_SOURCE;
|
||||
_tag = s.MPI_TAG;
|
||||
_error = s.MPI_ERROR;
|
||||
}
|
||||
|
||||
communicator::communicator( )
|
||||
{
|
||||
_rank = -1;
|
||||
_size = -1;
|
||||
|
||||
_buf = 0;
|
||||
_bufsize = -1;
|
||||
}
|
||||
|
||||
communicator::~communicator()
|
||||
{
|
||||
if( _buf )
|
||||
{
|
||||
delete _buf;
|
||||
_buf = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int communicator::rank()
|
||||
{
|
||||
if ( _rank == -1 )
|
||||
{
|
||||
MPI_Comm_rank( MPI_COMM_WORLD, &_rank );
|
||||
}
|
||||
return _rank;
|
||||
}
|
||||
|
||||
int communicator::size()
|
||||
{
|
||||
if ( _size == -1 )
|
||||
{
|
||||
MPI_Comm_size( MPI_COMM_WORLD, &_size );
|
||||
}
|
||||
return _size;
|
||||
}
|
||||
|
||||
/*
|
||||
* SEND / RECV INT
|
||||
*/
|
||||
void communicator::send( int dest, int tag, int n )
|
||||
{
|
||||
MPI_Send( &n, 1, MPI_INT, dest, tag, MPI_COMM_WORLD );
|
||||
}
|
||||
|
||||
void communicator::recv( int src, int tag, int& n )
|
||||
{
|
||||
MPI_Status stat;
|
||||
MPI_Recv( &n, 1, MPI_INT, src, tag, MPI_COMM_WORLD , &stat );
|
||||
}
|
||||
|
||||
/*
|
||||
* SEND / RECV STRING
|
||||
*/
|
||||
void communicator::send( int dest, int tag, const std::string& str )
|
||||
{
|
||||
int size = str.size() + 1;
|
||||
send( dest, tag, size );
|
||||
MPI_Send( (char*)str.c_str(), size, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
|
||||
}
|
||||
|
||||
void communicator::recv( int src, int tag, std::string& str )
|
||||
{
|
||||
int size = -1;
|
||||
MPI_Status stat;
|
||||
recv( src, tag, size );
|
||||
|
||||
if( _buf == 0 )
|
||||
{
|
||||
_buf = new char[ size ];
|
||||
_bufsize = size;
|
||||
} else if( _bufsize < size )
|
||||
{
|
||||
delete [] _buf;
|
||||
_buf = new char[ size ];
|
||||
_bufsize = size;
|
||||
}
|
||||
MPI_Recv( _buf, size, MPI_CHAR, src, tag, MPI_COMM_WORLD, &stat );
|
||||
str.assign( _buf );
|
||||
}
|
||||
|
||||
/*
|
||||
* SEND / RECV Objects
|
||||
*/
|
||||
void communicator::send( int dest, int tag, const eoserial::Persistent & persistent )
|
||||
{
|
||||
eoserial::Object* obj = persistent.pack();
|
||||
std::stringstream ss;
|
||||
obj->print( ss );
|
||||
delete obj;
|
||||
send( dest, tag, ss.str() );
|
||||
}
|
||||
|
||||
void communicator::recv( int src, int tag, eoserial::Persistent & persistent )
|
||||
{
|
||||
std::string asText;
|
||||
recv( src, tag, asText );
|
||||
eoserial::Object* obj = eoserial::Parser::parse( asText );
|
||||
persistent.unpack( obj );
|
||||
delete obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* Other methods
|
||||
*/
|
||||
status communicator::probe( int src, int tag )
|
||||
{
|
||||
MPI_Status stat;
|
||||
MPI_Probe( src, tag, MPI_COMM_WORLD , &stat );
|
||||
return status( stat );
|
||||
}
|
||||
|
||||
void communicator::barrier()
|
||||
{
|
||||
MPI_Barrier( MPI_COMM_WORLD );
|
||||
}
|
||||
|
||||
void broadcast( communicator & comm, int value, int root )
|
||||
{
|
||||
MPI_Bcast( &value, 1, MPI_INT, root, MPI_COMM_WORLD );
|
||||
}
|
||||
}
|
||||
322
eo/src/mpi/implMpi.h
Normal file
322
eo/src/mpi/implMpi.h
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EO_IMPL_MPI_HPP__
|
||||
# define __EO_IMPL_MPI_HPP__
|
||||
|
||||
# include <mpi.h>
|
||||
# include <serial/eoSerial.h>
|
||||
|
||||
/**
|
||||
* This namespace contains reimplementations of some parts of the Boost::MPI API in C++, so as to be used in
|
||||
* EO without any dependance to Boost. Historically, EO's parallelization module used the
|
||||
* boost library to add a layer over MPI. After having noticed that just some functions
|
||||
* were really used, we decided to reimplement our own C++-like implementation of MPI.
|
||||
*
|
||||
* Because the Boost::MPI API is really clean, we reused it in this module. However, all
|
||||
* the functions of Boost::MPI were not used, hence a subset of the API is reused. For
|
||||
* instance, users can just send integer, std::string or eoserial::Persistent objects;
|
||||
* furthermore, only eoserial::Persistent objects can sent in a table.
|
||||
*
|
||||
* The documentation of the functions is exactly the same as the official Boost::MPI
|
||||
* documentation. You can find it on www.boost.org/doc/libs/1_49_0/doc/html/mpi/
|
||||
* The entities are here shortly described, if you need further details, don't hesitate
|
||||
* to visit the boost URL.
|
||||
*/
|
||||
|
||||
namespace mpi
|
||||
{
|
||||
/**
|
||||
* @ingroup Parallel
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Constant indicating that a message can come from any process.
|
||||
*/
|
||||
extern const int any_source;
|
||||
|
||||
/**
|
||||
* @brief Constant indicating that a message can come from any tag (channel).
|
||||
*/
|
||||
extern const int any_tag;
|
||||
|
||||
/**
|
||||
* @brief Wrapper class to have a MPI environment.
|
||||
*
|
||||
* Instead of calling MPI_Init and MPI_Finalize, it is only necessary to instantiate
|
||||
* this class once, in the global context.
|
||||
*/
|
||||
class environment
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Inits MPI context.
|
||||
*
|
||||
* @param argc Number of params in command line (same as one in main)
|
||||
* @param argv Strings containing params (same as one in main)
|
||||
*/
|
||||
environment(int argc, char**argv);
|
||||
|
||||
/**
|
||||
* @brief Closes MPI context.
|
||||
*/
|
||||
~environment();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Wrapper class for MPI_Status
|
||||
*
|
||||
* Consists only in a C++ wrapper class, giving getters on status attributes.
|
||||
*/
|
||||
class status
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Converts a MPI_Status into a status.
|
||||
*/
|
||||
status( const MPI_Status & s );
|
||||
|
||||
/**
|
||||
* @brief Returns the tag of the associated communication.
|
||||
*/
|
||||
int tag() { return _tag; }
|
||||
|
||||
/**
|
||||
* @brief Indicates which error number we obtained in the associated communication.
|
||||
*/
|
||||
int error() { return _error; }
|
||||
|
||||
/**
|
||||
* @brief Returns the MPI rank of the source of the associated communication.
|
||||
*/
|
||||
int source() { return _source; }
|
||||
|
||||
private:
|
||||
int _source;
|
||||
int _tag;
|
||||
int _error;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Main object, used to send / receive messages, get informations about the rank and the size of the world,
|
||||
* etc.
|
||||
*/
|
||||
class communicator
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Creates the communicator, using the whole world as a MPI_Comm.
|
||||
*
|
||||
* @todo Allow the user to precise which MPI_Comm to use
|
||||
*/
|
||||
communicator( );
|
||||
|
||||
~communicator();
|
||||
|
||||
/**
|
||||
* @brief Returns the MPI rank of the current process.
|
||||
*/
|
||||
int rank();
|
||||
|
||||
/**
|
||||
* @brief Returns the size of the MPI cluster.
|
||||
*/
|
||||
int size();
|
||||
|
||||
/*
|
||||
* SEND / RECV INT
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sends an integer to dest on channel "tag".
|
||||
*
|
||||
* @param dest MPI rank of the receiver
|
||||
* @param tag MPI tag of message
|
||||
* @param n The integer to send
|
||||
*/
|
||||
void send( int dest, int tag, int n );
|
||||
|
||||
/*
|
||||
* @brief Receives an integer from src on channel "tag".
|
||||
*
|
||||
* @param src MPI rank of the sender
|
||||
* @param tag MPI tag of message
|
||||
* @param n Where to save the received integer
|
||||
*/
|
||||
void recv( int src, int tag, int& n );
|
||||
|
||||
/*
|
||||
* SEND / RECV STRING
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sends a string to dest on channel "tag".
|
||||
*
|
||||
* @param dest MPI rank of the receiver
|
||||
* @param tag MPI tag of message
|
||||
* @param str The std::string to send
|
||||
*/
|
||||
void send( int dest, int tag, const std::string& str );
|
||||
|
||||
/*
|
||||
* @brief Receives a string from src on channel "tag".
|
||||
*
|
||||
* @param src MPI rank of the sender
|
||||
* @param tag MPI tag of message
|
||||
* @param std::string Where to save the received string
|
||||
*/
|
||||
void recv( int src, int tag, std::string& str );
|
||||
|
||||
/*
|
||||
* SEND / RECV Objects
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sends an eoserial::Persistent to dest on channel "tag".
|
||||
*
|
||||
* @param dest MPI rank of the receiver
|
||||
* @param tag MPI tag of message
|
||||
* @param persistent The object to send (it must absolutely implement eoserial::Persistent)
|
||||
*/
|
||||
void send( int dest, int tag, const eoserial::Persistent & persistent );
|
||||
|
||||
/**
|
||||
* @brief Sends an array of eoserial::Persistent to dest on channel "tag".
|
||||
*
|
||||
* @param dest MPI rank of the receiver
|
||||
* @param tag MPI tag of message
|
||||
* @param table The array of eoserial::Persistent objects
|
||||
* @param size The number of elements to send (no check is done, the user has to be sure that the size won't
|
||||
* overflow!)
|
||||
*/
|
||||
template< class T >
|
||||
void send( int dest, int tag, T* table, int size )
|
||||
{
|
||||
// Puts all the values into an array
|
||||
eoserial::Array* array = new eoserial::Array;
|
||||
|
||||
for( int i = 0; i < size; ++i )
|
||||
{
|
||||
array->push_back( table[i].pack() );
|
||||
}
|
||||
|
||||
// Encapsulates the array into an object
|
||||
eoserial::Object* obj = new eoserial::Object;
|
||||
obj->add( "array", array );
|
||||
std::stringstream ss;
|
||||
obj->print( ss );
|
||||
delete obj;
|
||||
|
||||
// Sends the object as a string
|
||||
send( dest, tag, ss.str() );
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Receives an eoserial::Persistent object from src on channel "tag".
|
||||
*
|
||||
* @param src MPI rank of the sender
|
||||
* @param tag MPI tag of message
|
||||
* @param persistent Where to unpack the serialized object?
|
||||
*/
|
||||
void recv( int src, int tag, eoserial::Persistent & persistent );
|
||||
|
||||
/*
|
||||
* @brief Receives an array of eoserial::Persistent from src on channel "tag".
|
||||
*
|
||||
* @param src MPI rank of the sender
|
||||
* @param tag MPI tag of message
|
||||
* @param table The table in which we're saving the received objects. It must have been allocated by the user,
|
||||
* as no allocation is performed here.
|
||||
* @param size The number of elements to receive (no check is done, the user has to be sure that the size won't
|
||||
* overflow!)
|
||||
*/
|
||||
template< class T >
|
||||
void recv( int src, int tag, T* table, int size )
|
||||
{
|
||||
// Receives the string which contains the object
|
||||
std::string asText;
|
||||
recv( src, tag, asText );
|
||||
|
||||
// Parses the object and retrieves the table
|
||||
eoserial::Object* obj = eoserial::Parser::parse( asText );
|
||||
eoserial::Array* array = static_cast<eoserial::Array*>( (*obj)["array"] );
|
||||
|
||||
// Retrieves all the values from the array
|
||||
for( int i = 0; i < size; ++i )
|
||||
{
|
||||
eoserial::unpackObject( *array, i, table[i] );
|
||||
}
|
||||
delete obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* Other methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Wrapper for MPI_Probe
|
||||
*
|
||||
* Waits for a message to come from process having rank src, on the channel
|
||||
* tag.
|
||||
*
|
||||
* @param src MPI rank of the sender (any_source if it can be any sender)
|
||||
* @param tag MPI tag of the expected message (any_tag if it can be any tag)
|
||||
*/
|
||||
status probe( int src = any_source, int tag = any_tag );
|
||||
|
||||
/**
|
||||
* @brief Wrapper for MPI_Barrier
|
||||
*
|
||||
*
|
||||
*/
|
||||
void barrier();
|
||||
|
||||
private:
|
||||
int _rank;
|
||||
int _size;
|
||||
|
||||
char* _buf; // temporary buffer for sending and receiving strings. Avoids reallocations
|
||||
int _bufsize; // size of the above temporary buffer
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Wrapper for MPI_Bcast
|
||||
*
|
||||
* Broadcasts an integer value on the communicator comm, from the process having the MPI rank root.
|
||||
*
|
||||
* @param comm The communicator on which to broadcast
|
||||
* @param value The integer value to send
|
||||
* @param root The MPI rank of the broadcaster
|
||||
*
|
||||
* @todo Actually comm isn't used and broadcast is performed on the whole MPI_COMM_WORLD. TODO: Use comm instead
|
||||
*/
|
||||
void broadcast( communicator & comm, int value, int root );
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
} // namespace mpi
|
||||
|
||||
# endif //__EO_IMPL_MPI_HPP__
|
||||
|
|
@ -15,49 +15,49 @@
|
|||
#
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
PROJECT(PyEO)
|
||||
project(PyEO)
|
||||
|
||||
FIND_PACKAGE(Boost 1.42 COMPONENTS python)
|
||||
FIND_PACKAGE(PythonLibs)
|
||||
find_package(Boost 1.42 COMPONENTS python)
|
||||
find_package(PythonLibs)
|
||||
|
||||
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
|
||||
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
include_directories(${PYTHON_INCLUDE_PATH})
|
||||
|
||||
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
|
||||
link_directories(${Boost_LIBRARY_DIRS})
|
||||
|
||||
IF(APPLE)
|
||||
if(APPLE)
|
||||
# osx internal
|
||||
FIND_LIBRARY(APPLE_CARBON Carbon)
|
||||
ENDIF(APPLE)
|
||||
find_library(APPLE_CARBON Carbon)
|
||||
endif(APPLE)
|
||||
|
||||
# includes
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
#INCLUDE_DIRECTORIES(../)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
#include_directories(../)
|
||||
|
||||
# source
|
||||
FILE(GLOB SOURCES *.cpp)
|
||||
file(GLOB SOURCES *.cpp)
|
||||
|
||||
# EO dependencies
|
||||
SET(EO_SOURCES
|
||||
${EO_SOURCE_DIR}/src/eoFunctorStore.cpp
|
||||
${EO_SOURCE_DIR}/src/utils/eoLogger.cpp
|
||||
${EO_SOURCE_DIR}/src/utils/eoParallel.cpp
|
||||
set(EO_SOURCES
|
||||
${EO_SRC_DIR}/src/eoFunctorStore.cpp
|
||||
${EO_SRC_DIR}/src/utils/eoLogger.cpp
|
||||
${EO_SRC_DIR}/src/utils/eoParallel.cpp
|
||||
)
|
||||
|
||||
# shared library
|
||||
ADD_LIBRARY(PyEO MODULE ${SOURCES} ${EO_SOURCES})
|
||||
INSTALL(TARGETS PyEO LIBRARY DESTINATION ${LIB} COMPONENT libraries)
|
||||
add_library(PyEO MODULE ${SOURCES} ${EO_SOURCES})
|
||||
install(TARGETS PyEO LIBRARY DESTINATION local/${LIB} COMPONENT libraries)
|
||||
|
||||
# python 2.5 must have pyd
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
SET_TARGET_PROPERTIES(PyEO PROPERTIES SUFFIX ".pyd")
|
||||
ENDIF(WIN32 AND NOT CYGWIN)
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
set_target_properties(PyEO PROPERTIES SUFFIX ".pyd")
|
||||
endif(WIN32 AND NOT CYGWIN)
|
||||
|
||||
# add the libs
|
||||
IF(APPLE)
|
||||
TARGET_LINK_LIBRARIES(PyEO ${APPLE_CARBON} ${PYTHON_LIBRARY} ${Boost_LIBRARIES})
|
||||
ELSE(APPLE)
|
||||
TARGET_LINK_LIBRARIES(PyEO ${PYTHON_LIBRARY} ${Boost_LIBRARIES})
|
||||
ENDIF(APPLE)
|
||||
if(APPLE)
|
||||
target_link_libraries(PyEO ${APPLE_CARBON} ${PYTHON_LIBRARY} ${Boost_LIBRARIES})
|
||||
else(APPLE)
|
||||
target_link_libraries(PyEO ${PYTHON_LIBRARY} ${Boost_LIBRARIES})
|
||||
endif(APPLE)
|
||||
|
|
|
|||
58
eo/src/serial/Array.cpp
Normal file
58
eo/src/serial/Array.cpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# include "Array.h"
|
||||
|
||||
namespace eoserial
|
||||
{
|
||||
std::ostream& Array::print( std::ostream& out ) const
|
||||
{
|
||||
out << "[";
|
||||
bool first = true;
|
||||
for (ArrayChildren::const_iterator it = begin(),
|
||||
end = this->end();
|
||||
it != end;
|
||||
++it)
|
||||
{
|
||||
if ( first )
|
||||
{
|
||||
first = false;
|
||||
} else {
|
||||
out << ", ";
|
||||
}
|
||||
(*it)->print( out );
|
||||
}
|
||||
out << "]\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
Array::~Array()
|
||||
{
|
||||
for (ArrayChildren::iterator it = begin(),
|
||||
end = this->end();
|
||||
it != end;
|
||||
++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace eoserial
|
||||
170
eo/src/serial/Array.h
Normal file
170
eo/src/serial/Array.h
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EOSERIAL_ARRAY_H__
|
||||
# define __EOSERIAL_ARRAY_H__
|
||||
|
||||
# include <vector>
|
||||
|
||||
# include "Entity.h"
|
||||
# include "Serializable.h"
|
||||
# include "Object.h"
|
||||
|
||||
namespace eoserial
|
||||
{
|
||||
|
||||
// Forward declaration for below declarations.
|
||||
class Array;
|
||||
|
||||
/*
|
||||
* Declarations of functions present in Utils.h
|
||||
* These are put here to avoid instead of including the file Utils.h, which would
|
||||
* cause a circular inclusion.
|
||||
*/
|
||||
|
||||
template< class T >
|
||||
void unpack( const Array & array, unsigned int index, T & value );
|
||||
|
||||
void unpackObject( const Array & array, unsigned int index, Persistent & value );
|
||||
|
||||
template< class Container, template<class> class UnpackAlgorithm >
|
||||
void unpackArray( const Array & array, unsigned int index, Container & container );
|
||||
|
||||
/**
|
||||
* @brief Represents a JSON array.
|
||||
*
|
||||
* Wrapper for an array, so as to be used as a JSON object.
|
||||
*
|
||||
* @ingroup Serialization
|
||||
*/
|
||||
class Array : public eoserial::Entity, public std::vector< eoserial::Entity* >
|
||||
{
|
||||
protected:
|
||||
typedef std::vector< eoserial::Entity* > ArrayChildren;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Adds the serializable object as a JSON object.
|
||||
* @param obj Object which implemnets JsonSerializable.
|
||||
*/
|
||||
void push_back( const eoserial::Printable* obj )
|
||||
{
|
||||
ArrayChildren::push_back( obj->pack() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Proxy for vector::push_back.
|
||||
*/
|
||||
void push_back( eoserial::Entity* json )
|
||||
{
|
||||
ArrayChildren::push_back( json );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prints the JSON array into the given stream.
|
||||
* @param out The stream
|
||||
*/
|
||||
virtual std::ostream& print( std::ostream& out ) const;
|
||||
|
||||
/**
|
||||
* @brief Dtor
|
||||
*/
|
||||
~Array();
|
||||
|
||||
/*
|
||||
* The following parts allows the user to automatically deserialize an eoserial::Array into a
|
||||
* standard container, by giving the algorithm which will be used to deserialize contained entities.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Functor which determines how to retrieve the real value contained in a eoserial::Entity at
|
||||
* a given place.
|
||||
*
|
||||
* It will be applied for each contained variable in the array.
|
||||
*/
|
||||
template<class Container>
|
||||
struct BaseAlgorithm
|
||||
{
|
||||
/**
|
||||
* @brief Main operator.
|
||||
*
|
||||
* @param array The eoserial::Array from which we're reading.
|
||||
* @param i The index of the contained value.
|
||||
* @param container The standard (STL) container in which we'll push back the read value.
|
||||
*/
|
||||
virtual void operator()( const eoserial::Array& array, unsigned int i, Container & container ) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief BaseAlgorithm for retrieving primitive variables.
|
||||
*
|
||||
* This one should be used to retrieve primitive (and types which implement operator>>) variables, for instance
|
||||
* int, double, std::string, etc...
|
||||
*/
|
||||
template<typename C>
|
||||
struct UnpackAlgorithm : public BaseAlgorithm<C>
|
||||
{
|
||||
void operator()( const eoserial::Array& array, unsigned int i, C & container ) const
|
||||
{
|
||||
typename C::value_type t;
|
||||
unpack( array, i, t );
|
||||
container.push_back( t );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief BaseAlgorithm for retrieving eoserial::Persistent objects.
|
||||
*
|
||||
* This one should be used to retrieve objects which implement eoserial::Persistent.
|
||||
*/
|
||||
template<typename C>
|
||||
struct UnpackObjectAlgorithm : public BaseAlgorithm<C>
|
||||
{
|
||||
void operator()( const eoserial::Array& array, unsigned int i, C & container ) const
|
||||
{
|
||||
typename C::value_type t;
|
||||
unpackObject( array, i, t );
|
||||
container.push_back( t );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief General algorithm for array deserialization.
|
||||
*
|
||||
* Applies the BaseAlgorithm to each contained variable in the eoserial::Array.
|
||||
*/
|
||||
template<class Container, template<class T> class UnpackAlgorithm>
|
||||
inline void deserialize( Container & array )
|
||||
{
|
||||
UnpackAlgorithm< Container > algo;
|
||||
for( unsigned int i = 0, size = this->size();
|
||||
i < size;
|
||||
++i)
|
||||
{
|
||||
algo( *this, i, array );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace eoserial
|
||||
|
||||
# endif // __EOSERIAL_ARRAY_H__
|
||||
|
||||
35
eo/src/serial/CMakeLists.txt
Normal file
35
eo/src/serial/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
######################################################################################
|
||||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Define the eoserial target
|
||||
######################################################################################
|
||||
|
||||
set(EOSERIAL_LIB_OUTPUT_PATH ${EO_BIN_DIR}/lib)
|
||||
set(LIBRARY_OUTPUT_PATH ${EOSERIAL_LIB_OUTPUT_PATH})
|
||||
|
||||
set(EOSERIAL_SOURCES
|
||||
Array.cpp
|
||||
Object.cpp
|
||||
Parser.cpp
|
||||
String.cpp
|
||||
)
|
||||
|
||||
add_library(eoserial STATIC ${EOSERIAL_SOURCES})
|
||||
install(TARGETS eoserial ARCHIVE DESTINATION lib COMPONENT libraries)
|
||||
|
||||
file(GLOB HDRS *.h)
|
||||
install(FILES ${HDRS} DESTINATION include/eo/serial COMPONENT headers)
|
||||
|
||||
######################################################################################
|
||||
### 3) Optionnal
|
||||
######################################################################################
|
||||
|
||||
set(EOSERIAL_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(eoserial PROPERTIES VERSION "${EOSERIAL_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
70
eo/src/serial/Entity.h
Normal file
70
eo/src/serial/Entity.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EOSERIAL_ENTITY_H__
|
||||
# define __EOSERIAL_ENTITY_H__
|
||||
|
||||
# include <iostream> // ostream
|
||||
|
||||
|
||||
/**
|
||||
* @brief Contains all the necessary entities to serialize eo objects into JSON objects.
|
||||
*
|
||||
* Allows serialization from user objects into JSON objects, if they implement the interface
|
||||
* eoserial::Serializable or eoserial::Persistent. The following user objects can be serialized:
|
||||
* - primitive types (int, std::string, ...), in particular every type that can be written into a
|
||||
* std::stringstream.
|
||||
* - objects which implement eoserial::Serializable.
|
||||
* - array of serializable things (primitive or serializable objects).
|
||||
*
|
||||
* @ingroup Utilities
|
||||
* @defgroup Serialization Serialization helpers
|
||||
**/
|
||||
namespace eoserial
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief JSON entity
|
||||
*
|
||||
* This class represents a JSON entity, which can be JSON objects,
|
||||
* strings or arrays. It is the base class for the JSON hierarchy.
|
||||
*
|
||||
* @ingroup Serialization
|
||||
*/
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Virtual dtor (base class).
|
||||
*/
|
||||
virtual ~Entity() { /* empty */ }
|
||||
|
||||
/**
|
||||
* @brief Prints the content of a JSON object into a stream.
|
||||
* @param out The stream in which we're printing.
|
||||
*/
|
||||
virtual std::ostream& print( std::ostream& out ) const = 0;
|
||||
};
|
||||
|
||||
} // namespace eoserial
|
||||
|
||||
# endif // __ENTITY_H__
|
||||
60
eo/src/serial/Object.cpp
Normal file
60
eo/src/serial/Object.cpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# include "Object.h"
|
||||
|
||||
using namespace eoserial;
|
||||
|
||||
namespace eoserial
|
||||
{
|
||||
std::ostream& Object::print( std::ostream& out ) const
|
||||
{
|
||||
out << '{';
|
||||
bool first = true;
|
||||
for(JsonValues::const_iterator it = begin(), end = this->end();
|
||||
it != end;
|
||||
++it)
|
||||
{
|
||||
if ( first )
|
||||
{
|
||||
first = false;
|
||||
} else {
|
||||
out << ", ";
|
||||
}
|
||||
|
||||
out << '"' << it->first << "\":"; // key
|
||||
it->second->print( out ); // value
|
||||
}
|
||||
out << "}\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
Object::~Object()
|
||||
{
|
||||
for(JsonValues::iterator it = begin(), end = this->end();
|
||||
it != end;
|
||||
++it)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace eoserial
|
||||
88
eo/src/serial/Object.h
Normal file
88
eo/src/serial/Object.h
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EOSERIAL_OBJECT_H__
|
||||
# define __EOSERIAL_OBJECT_H__
|
||||
|
||||
# include <map>
|
||||
# include <string>
|
||||
|
||||
# include "Entity.h"
|
||||
# include "Serializable.h"
|
||||
|
||||
namespace eoserial
|
||||
{
|
||||
/**
|
||||
* @brief JSON Object
|
||||
*
|
||||
* This class represents a JSON object, which is basically a dictionnary
|
||||
* of keys (strings) and values (JSON entities).
|
||||
*
|
||||
* @ingroup Serialization
|
||||
*/
|
||||
class Object : public eoserial::Entity, public std::map< std::string, eoserial::Entity* >
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, eoserial::Entity*> JsonValues;
|
||||
|
||||
/**
|
||||
* @brief Adds a pair into the JSON object.
|
||||
* @param key The key associated with the eoserial object
|
||||
* @param json The JSON object as created with framework.
|
||||
*/
|
||||
void add( const std::string& key, eoserial::Entity* json )
|
||||
{
|
||||
(*this)[ key ] = json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a pair into the JSON object.
|
||||
* @param key The key associated with the eoserial object
|
||||
* @param obj A JSON-serializable object
|
||||
*/
|
||||
void add( const std::string& key, const eoserial::Printable* obj )
|
||||
{
|
||||
(*this)[ key ] = obj->pack();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deserializes a Serializable class instance from this JSON object.
|
||||
* @param obj The object we want to rebuild.
|
||||
*/
|
||||
void deserialize( eoserial::Persistent & obj )
|
||||
{
|
||||
obj.unpack( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dtor
|
||||
*/
|
||||
~Object();
|
||||
|
||||
/**
|
||||
* @brief Prints the content of a JSON object into a stream.
|
||||
*/
|
||||
virtual std::ostream& print( std::ostream& out ) const;
|
||||
};
|
||||
|
||||
} // namespace eoserial
|
||||
# endif // __EOSERIAL_OBJECT_H__
|
||||
|
||||
171
eo/src/serial/Parser.cpp
Normal file
171
eo/src/serial/Parser.cpp
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# include <string>
|
||||
|
||||
# include "Parser.h"
|
||||
|
||||
# include "Array.h"
|
||||
# include "Object.h"
|
||||
# include "String.h"
|
||||
|
||||
// in debug mode only
|
||||
// # define DEBUG(x) std::cout << x << std::endl;
|
||||
# define DEBUG(x)
|
||||
|
||||
using namespace eoserial;
|
||||
|
||||
namespace eoserial
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Parses a string contained between double quotes.
|
||||
*
|
||||
* Strings can contain escaped double quotes.
|
||||
* @param str The string we're parsing.
|
||||
* @param pos The index of current position in parsed string.
|
||||
* This index will be updated so as to allow the parser to
|
||||
* continue.
|
||||
*/
|
||||
static std::string parseString(const std::string& str, size_t & pos)
|
||||
{
|
||||
// example : "hello"
|
||||
// example 2 : "\"world\""
|
||||
// for hello:
|
||||
// firstQuote == 0, secondQuote == 6
|
||||
// sub string should be from firstQuote+1 to secondQuote-1
|
||||
// so its size should be (secondQuote-1 -(firstQuote+1) + 1)
|
||||
std::string value;
|
||||
size_t firstQuote = str.find( '"', pos );
|
||||
size_t secondQuote;
|
||||
|
||||
/* instead of just seeking the second quote, we need to ensure
|
||||
// that there is no escaped quote before this one.
|
||||
// actually this is harder than that. Using backslashes
|
||||
// to escape double quotes mean that backslashes have to be
|
||||
// escaped to.
|
||||
// example : "text\\" to symbolize : text\
|
||||
// example : "text\\\" to symbolize : text\"
|
||||
// In fact, we should find if number of backslashes is odd; in this case,
|
||||
// the double quotes are escaped and we should find the next one.
|
||||
*/
|
||||
int backslashesCount;
|
||||
do {
|
||||
++pos;
|
||||
secondQuote = str.find( '"', pos );
|
||||
size_t i = secondQuote - 1;
|
||||
|
||||
// Find the backslashes
|
||||
backslashesCount = 0;
|
||||
while ( str[ i ] == '\\' )
|
||||
{
|
||||
--i;
|
||||
++backslashesCount;
|
||||
}
|
||||
pos = secondQuote;
|
||||
} while( backslashesCount % 2 == 1 );
|
||||
|
||||
value = str.substr( firstQuote+1, secondQuote-firstQuote-1 );
|
||||
pos = secondQuote + 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Moves the given index pos to the next character which is
|
||||
* neither a coma, a space nor a new line.
|
||||
*
|
||||
* @param str The string in which we want to ignores those characters.
|
||||
* @param pos The index of current position in parsed string.
|
||||
*/
|
||||
static void ignoreChars(const std::string& str, size_t & pos)
|
||||
{
|
||||
// ignore white spaces and comas
|
||||
for (char current = str[ pos ];
|
||||
current == ',' || current == ' ' || current == '\n';
|
||||
current = str[ ++pos ]);
|
||||
}
|
||||
|
||||
String* Parser::parseJsonString(const std::string & str, size_t & pos)
|
||||
{
|
||||
return new String( parseString( str, pos ) );
|
||||
}
|
||||
|
||||
Object* Parser::parse(const std::string & str)
|
||||
{
|
||||
size_t initial(0); // we begin at position 0
|
||||
return static_cast<Object*>( parseRight(str, initial) );
|
||||
}
|
||||
|
||||
Entity* Parser::parseRight(const std::string & str, size_t & pos)
|
||||
{
|
||||
Entity* value = 0;
|
||||
|
||||
if ( str[ pos ] == '{' )
|
||||
{
|
||||
// next one is an object
|
||||
DEBUG("We read an object.")
|
||||
Object* obj = new Object;
|
||||
pos += 1;
|
||||
while( pos < str.size() && str[ pos ] != '}' )
|
||||
{
|
||||
parseLeft( str, pos, obj );
|
||||
ignoreChars( str, pos );
|
||||
}
|
||||
DEBUG("We just finished to read an object ! ")
|
||||
pos += 1; // we're on the }, go to the next char
|
||||
value = obj;
|
||||
}
|
||||
else if ( str[ pos ] == '"' )
|
||||
{
|
||||
// next one is a string
|
||||
DEBUG("We read a string")
|
||||
value = parseJsonString( str, pos );
|
||||
}
|
||||
else if ( str[ pos ] == '[' )
|
||||
{
|
||||
// next one is an array
|
||||
DEBUG("We read an array")
|
||||
Array* array = new Array;
|
||||
pos += 1;
|
||||
while( pos < str.size() && str[ pos ] != ']' )
|
||||
{
|
||||
Entity* child = parseRight( str, pos );
|
||||
if ( child )
|
||||
array->push_back( child );
|
||||
}
|
||||
DEBUG("We've finished to read our array.")
|
||||
pos += 1; // we're on the ], go to the next char
|
||||
value = array;
|
||||
}
|
||||
ignoreChars( str, pos );
|
||||
return value;
|
||||
}
|
||||
|
||||
void Parser::parseLeft(const std::string & str, size_t & pos, Object* eoserial)
|
||||
{
|
||||
std::string key = parseString(str, pos);
|
||||
++pos; // the colon
|
||||
DEBUG("We've read the key ")
|
||||
(*eoserial)[ key ] = parseRight( str, pos );
|
||||
}
|
||||
|
||||
} // namespace eoserial
|
||||
|
||||
103
eo/src/serial/Parser.h
Normal file
103
eo/src/serial/Parser.h
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EOSERIAL_PARSER_H__
|
||||
# define __EOSERIAL_PARSER_H__
|
||||
|
||||
# include "Entity.h"
|
||||
# include "String.h"
|
||||
# include "Object.h"
|
||||
|
||||
/**
|
||||
* @file Parser.h
|
||||
*
|
||||
* This file contains a tiny JSON parser used in DAE. This parser just handles
|
||||
* a subset of JSON grammar, with the following restrictions :
|
||||
* - all strings must be surrounded by double quotes.
|
||||
* - everything which is not an object or an array is considered to be a string
|
||||
* (even integers, booleans,...).
|
||||
* - no syntax check is done. We trust the programmer and he has to ensure that
|
||||
* every JSON string he produces is valid.
|
||||
*
|
||||
* @author Benjamin BOUVIER
|
||||
*/
|
||||
|
||||
namespace eoserial
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Parser from a JSON source.
|
||||
*
|
||||
* This parser does just retrieve values and does NOT check the structure of
|
||||
* the input. This implies that if the input is not correct, the result is undefined
|
||||
* and can result to a failure on execution.
|
||||
*
|
||||
* @ingroup Serialization
|
||||
*/
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Parses the given string and returns the JSON object read.
|
||||
*/
|
||||
static eoserial::Object* parse(const std::string & str);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief Parses the right part of a JSON object as a string.
|
||||
*
|
||||
* The right part of an object can be a string (for instance :
|
||||
* "key":"value"), a JSON array (for instance: "key":["1"]) or
|
||||
* another JSON object (for instance: "key":{"another_key":"value"}).
|
||||
*
|
||||
* The right parts are found after keys (which are parsed by parseLeft)
|
||||
* and in arrays.
|
||||
*
|
||||
* @param str The string we're parsing.
|
||||
* @param pos The index of the current position in the string.
|
||||
* @return The JSON object matching the right part.
|
||||
*/
|
||||
static eoserial::Entity* parseRight(const std::string & str, size_t & pos);
|
||||
|
||||
/**
|
||||
* @brief Parses the left value of a key-value pair, which is the key.
|
||||
*
|
||||
* @param str The string we're parsing.
|
||||
* @param pos The index of the current position in the string.
|
||||
* @param json The current JSON object for which we're adding a key-value pair.
|
||||
*/
|
||||
static void parseLeft(const std::string & str, size_t & pos, eoserial::Object* json);
|
||||
|
||||
/**
|
||||
* @brief Retrieves a string in a JSON content.
|
||||
*
|
||||
* @param str The string we're parsing.
|
||||
* @param pos The index of the current position of parsing,
|
||||
* which will be updated.
|
||||
*/
|
||||
static eoserial::String* parseJsonString(const std::string & str, size_t & pos);
|
||||
};
|
||||
|
||||
} // namespace eoserial
|
||||
|
||||
# endif // __EOSERIAL_PARSER_H__
|
||||
66
eo/src/serial/Serializable.h
Normal file
66
eo/src/serial/Serializable.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EOSERIAL_SERIALIZABLE_H__
|
||||
# define __EOSERIAL_SERIALIZABLE_H__
|
||||
|
||||
namespace eoserial
|
||||
{
|
||||
class Object; // to avoid recursive inclusion with JsonObject
|
||||
|
||||
/**
|
||||
* @brief Interface showing that object can be written to a eoserial type
|
||||
* (currently JSON).
|
||||
*
|
||||
* @ingroup Serialization
|
||||
*/
|
||||
class Printable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Serializes the object to JSON format.
|
||||
* @return A JSON object created with new.
|
||||
*/
|
||||
virtual eoserial::Object* pack() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface showing that object can be eoserialized (written and read
|
||||
* from an input).
|
||||
*
|
||||
* Note : Persistent objects should have a default non-arguments constructor.
|
||||
*
|
||||
* @ingroup Serialization
|
||||
*/
|
||||
class Persistent : public Printable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Loads class fields from a JSON object.
|
||||
* @param json A JSON object. Programmer doesn't have to delete it, it
|
||||
* is automatically done.
|
||||
*/
|
||||
virtual void unpack(const eoserial::Object* json) = 0;
|
||||
};
|
||||
|
||||
} // namespace eoserial
|
||||
|
||||
# endif // __EOSERIAL_SERIALIZABLE_H__
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
|
||||
|
||||
/*
|
||||
(c) Thales group, 2010
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -16,21 +14,19 @@
|
|||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Caner Candan <caner.candan@thalesgroup.com>
|
||||
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# include "String.h"
|
||||
|
||||
#ifndef EO_PARSER_LOGGER_H
|
||||
#define EO_PARSER_LOGGER_H
|
||||
namespace eoserial
|
||||
{
|
||||
std::ostream& String::print( std::ostream& out ) const
|
||||
{
|
||||
out << '"' << *this << '"';
|
||||
return out;
|
||||
}
|
||||
} // namespace eoserial
|
||||
|
||||
#include "eoParser.h"
|
||||
|
||||
#warning "[eoParserLogger] is deprecated"
|
||||
|
||||
typedef eoParser eoParserLogger;
|
||||
|
||||
#endif // !EO_PARSER_LOGGER_H
|
||||
103
eo/src/serial/String.h
Normal file
103
eo/src/serial/String.h
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EOSERIAL_STRING_H__
|
||||
# define __EOSERIAL_STRING_H__
|
||||
|
||||
# include <string>
|
||||
# include <sstream>
|
||||
# include <limits>
|
||||
|
||||
# include "Entity.h"
|
||||
|
||||
namespace eoserial
|
||||
{
|
||||
/**
|
||||
* @brief JSON String
|
||||
*
|
||||
* Wrapper for string, so as to be used as a JSON object.
|
||||
*
|
||||
* @ingroup Serialization
|
||||
*/
|
||||
class String : public eoserial::Entity, public std::string
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Default ctor.
|
||||
* @param str The string we want to wrap.
|
||||
*/
|
||||
String( const std::string& str ) : std::string( str ) {}
|
||||
|
||||
/**
|
||||
* @brief Ctor used only when parsing.
|
||||
*/
|
||||
String( ) {}
|
||||
|
||||
/**
|
||||
* @brief Prints out the string.
|
||||
*/
|
||||
virtual std::ostream& print( std::ostream& out ) const;
|
||||
|
||||
/**
|
||||
* @brief Deserializes the current String into a given primitive type value.
|
||||
* @param value The value in which we're writing.
|
||||
*/
|
||||
template<class T>
|
||||
inline void deserialize( T & value );
|
||||
|
||||
protected:
|
||||
// Copy and reaffectation are forbidden
|
||||
explicit String( const String& _ );
|
||||
String& operator=( const String& _ );
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Casts a eoserial::String into a primitive value, or in a type which at
|
||||
* least overload operator>>.
|
||||
*
|
||||
* @param value A reference to the variable we're writing into.
|
||||
*
|
||||
* It's not necessary to specify the variable type, which can be infered by compiler when
|
||||
* invoking.
|
||||
*/
|
||||
template<class T>
|
||||
inline void String::deserialize( T & value )
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.precision(std::numeric_limits<double>::digits10 + 1);
|
||||
ss << *this;
|
||||
ss >> value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialization for strings, which don't need to be converted through
|
||||
* a stringstream.
|
||||
*/
|
||||
template<>
|
||||
inline void String::deserialize( std::string & value )
|
||||
{
|
||||
value = *this;
|
||||
}
|
||||
|
||||
} // namespace eoserial
|
||||
|
||||
# endif // __EOSERIAL_STRING_H__
|
||||
189
eo/src/serial/Utils.h
Normal file
189
eo/src/serial/Utils.h
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EOSERIAL_UTILS_H__
|
||||
# define __EOSERIAL_UTILS_H__
|
||||
|
||||
# include "Array.h"
|
||||
# include "Object.h"
|
||||
# include "String.h"
|
||||
|
||||
namespace eoserial
|
||||
{
|
||||
/* ***************************
|
||||
* DESERIALIZATION FUNCTIONS *
|
||||
*****************************
|
||||
These functions are useful for casting eoserial::objects into simple, primitive
|
||||
variables or into class instance which implement eoserial::Persistent.
|
||||
|
||||
The model is always quite the same :
|
||||
- the first argument is the containing object (which is a eoserial::Entity,
|
||||
an object or an array)
|
||||
- the second argument is the key or index,
|
||||
- the last argument is the value in which we're writing.
|
||||
*/
|
||||
|
||||
template< class T >
|
||||
inline void unpack( const Object & obj, const std::string & key, T & value )
|
||||
{
|
||||
static_cast<String*>( obj.find( key )->second )->deserialize( value );
|
||||
}
|
||||
|
||||
inline void unpackObject( const Object & obj, const std::string & key, Persistent & value )
|
||||
{
|
||||
static_cast<Object*>( obj.find( key )->second )->deserialize( value );
|
||||
}
|
||||
|
||||
template< class Container, template<class> class UnpackAlgorithm >
|
||||
inline void unpackArray( const Object & obj, const std::string & key, Container & array )
|
||||
{
|
||||
static_cast<Array*>( obj.find( key )->second )->deserialize< Container, UnpackAlgorithm >( array );
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline void unpack( const Array & array, unsigned int index, T & value )
|
||||
{
|
||||
static_cast<String*>( array[ index ] )->deserialize( value );
|
||||
}
|
||||
|
||||
inline void unpackObject( const Array & array, unsigned int index, Persistent & value )
|
||||
{
|
||||
static_cast<Object*>( array[ index ] )->deserialize( value );
|
||||
}
|
||||
|
||||
template< class Container, template<class> class UnpackAlgorithm >
|
||||
inline void unpackArray( const Array & array, unsigned int index, Container & container )
|
||||
{
|
||||
static_cast<Array*>( array[ index ] )->deserialize< Container, UnpackAlgorithm >( container );
|
||||
}
|
||||
|
||||
/* *****************************
|
||||
*** SERIALIZATION FUNCTIONS ***
|
||||
*******************************
|
||||
These functions are useful for casting classic objects and
|
||||
eoserial::Persistent objects into eoserial entities which
|
||||
can be manipulated by the framework.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Casts a value of a stream-serializable type (i.e, which implements
|
||||
* operator <<) into a JsonString.
|
||||
*
|
||||
* This is used when serializing the objects : all primitives types should be
|
||||
* converted into strings to get more easily manipulated.
|
||||
*
|
||||
* @param value The value we're converting.
|
||||
* @return JsonString wrapper for the value.
|
||||
*/
|
||||
template <typename T>
|
||||
String* make( const T & value )
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.precision(std::numeric_limits<double>::digits10 + 1);
|
||||
ss << value;
|
||||
return new String( ss.str() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specialization for strings : no need to convert as they're still
|
||||
* usable as strings.
|
||||
*/
|
||||
template<>
|
||||
inline String* make( const std::string & value )
|
||||
{
|
||||
return new String( value );
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions are useful for automatically serializing STL containers into
|
||||
* eoserial arrays which could be used by the framework.
|
||||
**/
|
||||
|
||||
/**
|
||||
* @brief Functor which explains how to push the value into the eoserial::Array.
|
||||
*/
|
||||
template< class T >
|
||||
struct PushAlgorithm
|
||||
{
|
||||
/**
|
||||
* @brief Main operator.
|
||||
*
|
||||
* @param array The eoserial::array in which we're writing.
|
||||
* @param value The variable we are writing.
|
||||
*/
|
||||
virtual void operator()( Array & array, const T & value ) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Push algorithm for primitive variables.
|
||||
*
|
||||
* This one should be used when inserting primitive (and types which implement
|
||||
* operator<<) variables.
|
||||
*/
|
||||
template< class T >
|
||||
struct MakeAlgorithm : public PushAlgorithm<T>
|
||||
{
|
||||
void operator()( Array & array, const T & value )
|
||||
{
|
||||
array.push_back( make( value ) );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Push algorithm for eoserial::Persistent variables.
|
||||
*/
|
||||
template< class T >
|
||||
struct SerializablePushAlgorithm : public PushAlgorithm<T>
|
||||
{
|
||||
void operator()( Array & array, const T & obj )
|
||||
{
|
||||
// obj address is not saved into array.push_back.
|
||||
array.push_back( &obj );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Casts a STL container (vector<int> or list<std::string>, for instance)
|
||||
* into a eoserial::Array.
|
||||
*
|
||||
* @þaram PushAlgorithm The algorithm used for inserting new element in the eoserial::Array.
|
||||
* This algorithm is directly called, so it is its own charge to invoke push_back on the
|
||||
* eoserial::Array.
|
||||
*/
|
||||
template< class Container, template<class> class PushAlgorithm >
|
||||
Array* makeArray( const Container & array )
|
||||
{
|
||||
Array* returned_array = new Array;
|
||||
typedef typename Container::const_iterator iterator;
|
||||
typedef typename Container::value_type Type;
|
||||
PushAlgorithm< Type > algo;
|
||||
for (
|
||||
iterator it = array.begin(), end = array.end();
|
||||
it != end;
|
||||
++it)
|
||||
{
|
||||
algo( *returned_array, *it );
|
||||
}
|
||||
return returned_array;
|
||||
}
|
||||
} // namespace eoserial
|
||||
|
||||
# endif //__EOSERIAL_UTILS_H__
|
||||
33
eo/src/serial/eoSerial.h
Normal file
33
eo/src/serial/eoSerial.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EOSERIAL_HEADERS__
|
||||
# define __EOSERIAL_HEADERS__
|
||||
|
||||
# include "Object.h"
|
||||
# include "Serializable.h"
|
||||
# include "Array.h"
|
||||
# include "Object.h"
|
||||
# include "String.h"
|
||||
# include "Parser.h"
|
||||
# include "Utils.h"
|
||||
|
||||
# endif // __EOSERIAL_HEADERS__
|
||||
8
eo/src/serial/json_example
Normal file
8
eo/src/serial/json_example
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{"a":"b",
|
||||
"obj":
|
||||
{"obj_a":"obj_}b","subobj_a":
|
||||
{"subk":"subv"}
|
||||
},
|
||||
"c":"d",
|
||||
"array":["1","2",{"\"array\"_obj\"":"array_ov]"}, ["3"], "4"]
|
||||
}
|
||||
|
|
@ -2,17 +2,17 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Define the ga target
|
||||
######################################################################################
|
||||
|
||||
SET(EOUTILS_LIB_OUTPUT_PATH ${EO_BINARY_DIR}/lib)
|
||||
SET(LIBRARY_OUTPUT_PATH ${EOUTILS_LIB_OUTPUT_PATH})
|
||||
set(EOUTILS_LIB_OUTPUT_PATH ${EO_BIN_DIR}/lib)
|
||||
set(LIBRARY_OUTPUT_PATH ${EOUTILS_LIB_OUTPUT_PATH})
|
||||
|
||||
SET(EOUTILS_SOURCES
|
||||
set(EOUTILS_SOURCES
|
||||
eoData.cpp
|
||||
eoFileMonitor.cpp
|
||||
eoGnuplot.cpp
|
||||
|
|
@ -32,15 +32,15 @@ SET(EOUTILS_SOURCES
|
|||
eoSignal.cpp
|
||||
)
|
||||
|
||||
ADD_LIBRARY(eoutils STATIC ${EOUTILS_SOURCES})
|
||||
INSTALL(TARGETS eoutils ARCHIVE DESTINATION ${LIB} COMPONENT libraries)
|
||||
add_library(eoutils STATIC ${EOUTILS_SOURCES})
|
||||
install(TARGETS eoutils ARCHIVE DESTINATION local/${LIB} COMPONENT libraries)
|
||||
|
||||
|
||||
######################################################################################
|
||||
### 3) Optionnal
|
||||
######################################################################################
|
||||
|
||||
SET(EOUTILS_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(eoutils PROPERTIES VERSION "${EOUTILS_VERSION}")
|
||||
set(EOUTILS_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(eoutils PROPERTIES VERSION "${EOUTILS_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ namespace eo
|
|||
*/
|
||||
struct file
|
||||
{
|
||||
file(const std::string f);
|
||||
explicit file(const std::string f);
|
||||
const std::string _f;
|
||||
};
|
||||
|
||||
|
|
@ -126,8 +126,8 @@ namespace eo
|
|||
*/
|
||||
struct setlevel
|
||||
{
|
||||
setlevel(const std::string v);
|
||||
setlevel(const Levels lvl);
|
||||
explicit setlevel(const std::string v);
|
||||
explicit setlevel(const Levels lvl);
|
||||
const std::string _v;
|
||||
const Levels _lvl;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ eoMonitor& eoOStreamMonitor::operator()(void)
|
|||
} // if firstime
|
||||
|
||||
// ok, now the real saving. write out
|
||||
// FIXME deprecated, remove in next release
|
||||
//! @todo old verbose formatting, do we still need it?
|
||||
/*
|
||||
for (iterator it = vec.begin (); it != vec.end (); ++it) {
|
||||
|
|
|
|||
|
|
@ -44,14 +44,17 @@ Authors:
|
|||
class eoOStreamMonitor : public eoMonitor
|
||||
{
|
||||
public :
|
||||
eoOStreamMonitor( std::ostream & _out, bool /*_verbose*/=true, std::string _delim = "\t", unsigned int _width=20, char _fill=' ' ) :
|
||||
/* FIXME remove in next release
|
||||
eoOStreamMonitor( std::ostream & _out, bool _verbose=true, std::string _delim = "\t", unsigned int _width=20, char _fill=' ' ) :
|
||||
out(_out), delim(_delim), width(_width), fill(_fill), firsttime(true)
|
||||
{
|
||||
#ifndef DEPRECATED_MESSAGES
|
||||
eo::log << eo::warnings << "WARNING: the use of the verbose parameter in eoOStreamMonitor constructor is deprecated and will be removed in the next release" << std::endl;
|
||||
#pragma message "WARNING: the use of the verbose parameter in eoOStreamMonitor constructor is deprecated and will be removed in the next release"
|
||||
#endif // !DEPRECATED_MESSAGES
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
eoOStreamMonitor( std::ostream & _out, std::string _delim = "\t", unsigned int _width=20, char _fill=' ' ) :
|
||||
out(_out), delim(_delim), width(_width), fill(_fill), firsttime(true)
|
||||
|
|
|
|||
|
|
@ -21,22 +21,25 @@
|
|||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Caner Candan <caner.candan@thalesgroup.com>
|
||||
Caner Candan <caner.candan@thalesgroup.com>
|
||||
|
||||
*/
|
||||
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
#include "eoParallel.h"
|
||||
#include "eoLogger.h"
|
||||
|
||||
eoParallel::eoParallel() :
|
||||
_isEnabled( false, "parallelize-loop", "Enable memory shared parallelization into evaluation's loops", '\0' ),
|
||||
_isDynamic( false, "parallelize-dynamic", "Enable dynamic memory shared parallelization", '\0' ),
|
||||
_isDynamic( true, "parallelize-dynamic", "Enable dynamic memory shared parallelization", '\0' ),
|
||||
_prefix( "results", "parallelize-prefix", "Here's the prefix filename where the results are going to be stored", '\0' ),
|
||||
_nthreads( 0, "parallelize-nthreads", "Define the number of threads you want to use, nthreads = 0 means you want to use all threads available", '\0' ),
|
||||
_enableResults( false, "parallelize-enable-results", "Enable the generation of results", '\0' ),
|
||||
_doMeasure( false, "parallelize-do-measure", "Do some measures during execution", '\0' ),
|
||||
_packetSize( 1U, "parallelize-packet-size", "Number of elements which should be sent in a single message during a parallel evaluation based on message passing.", '\0'),
|
||||
_t_start(0)
|
||||
{
|
||||
}
|
||||
|
|
@ -90,6 +93,7 @@ void eoParallel::_createParameters( eoParser& parser )
|
|||
parser.processParam( _nthreads, section );
|
||||
parser.processParam( _enableResults, section );
|
||||
parser.processParam( _doMeasure, section );
|
||||
parser.processParam( _packetSize, section );
|
||||
}
|
||||
|
||||
void make_parallel(eoParser& parser)
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@
|
|||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Caner Candan <caner.candan@thalesgroup.com>
|
||||
|
||||
Caner Candan <caner.candan@thalesgroup.com>
|
||||
*/
|
||||
|
||||
/** @defgroup Parallel Parallel
|
||||
|
|
@ -54,6 +53,7 @@ public:
|
|||
std::string prefix() const;
|
||||
|
||||
inline unsigned int nthreads() const { return _nthreads.value(); }
|
||||
inline unsigned int packetSize() const { return _packetSize.value(); }
|
||||
|
||||
inline bool enableResults() const { return _enableResults.value(); }
|
||||
inline bool doMeasure() const { return _doMeasure.value(); }
|
||||
|
|
@ -70,6 +70,7 @@ private:
|
|||
eoValueParam<unsigned int> _nthreads;
|
||||
eoValueParam<bool> _enableResults;
|
||||
eoValueParam<bool> _doMeasure;
|
||||
eoValueParam<unsigned int> _packetSize;
|
||||
double _t_start;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -150,7 +150,8 @@ public :
|
|||
initialize(2*s);
|
||||
}
|
||||
|
||||
/** Re-initializes the Random Number Generator
|
||||
/* FIXME remove in next release
|
||||
** Re-initializes the Random Number Generator
|
||||
|
||||
This is the traditional seeding procedure. This version is deprecated and
|
||||
only provided for compatibility with old code. In new projects you should
|
||||
|
|
@ -159,11 +160,12 @@ public :
|
|||
@see reseed for details on usage of the seeding value.
|
||||
|
||||
@version old version (deprecated)
|
||||
*/
|
||||
*
|
||||
void oldReseed(uint32_t s)
|
||||
{
|
||||
initialize(s);
|
||||
}
|
||||
*/
|
||||
|
||||
/** Random number from unifom distribution
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ Contact: http://eodev.sourceforge.net
|
|||
#ifndef _eoStat_h
|
||||
#define _eoStat_h
|
||||
|
||||
#include <iostream>
|
||||
#include <numeric> // accumulate
|
||||
|
||||
#include <eoFunctor.h>
|
||||
|
|
@ -176,18 +177,27 @@ private :
|
|||
};
|
||||
|
||||
/**
|
||||
Average fitness + Std. dev. of a population, fitness needs to be scalar.
|
||||
Average fitness + Std. dev. of a population, fitness HAVE TO BE to be scalar.
|
||||
*/
|
||||
template <class EOT>
|
||||
class eoSecondMomentStats : public eoStat<EOT, std::pair<double, double> >
|
||||
// FIXME find a way to use generic Fitness types instead of scala fitness here :
|
||||
// class eoSecondMomentStats : public eoStat<EOT, std::pair<typename EOT::Fitness, typename EOT::Fitness> >
|
||||
// Here, I failed to find a way to overload eoValueParam::getValue and setValue,
|
||||
// because there is no way to use the partial specializations located in eoParam.h
|
||||
// Indeed, eoValueParam is templatized on a ValueType, but the getValue signature does not
|
||||
// contain this type.
|
||||
// Thus, in order to use partial specializations the user would have to specify getValue<ValueType>(),
|
||||
// which is not the case in most of the existing code.
|
||||
// Overloading getValue in this class does not seems to work, the call falls to eoValueParam::getValue
|
||||
// and fails on the output stream.
|
||||
class eoSecondMomentStats : public eoStat<EOT, std::pair<double,double> >
|
||||
{
|
||||
public :
|
||||
// typedef typename EOT::Fitness FitT;
|
||||
typedef double FitT;
|
||||
|
||||
using eoStat<EOT, std::pair<double, double> >::value;
|
||||
|
||||
typedef typename EOT::Fitness fitness_type;
|
||||
|
||||
typedef std::pair<double, double> SquarePair;
|
||||
using eoStat<EOT, std::pair<FitT, FitT> >::value;
|
||||
typedef std::pair<FitT, FitT> SquarePair;
|
||||
|
||||
eoSecondMomentStats(std::string _description = "Average & Stdev")
|
||||
: eoStat<EOT, SquarePair>(std::make_pair(0.0,0.0), _description)
|
||||
|
|
@ -195,7 +205,7 @@ public :
|
|||
|
||||
static SquarePair sumOfSquares(SquarePair _sq, const EOT& _eo)
|
||||
{
|
||||
double fitness = _eo.fitness();
|
||||
FitT fitness = _eo.fitness();
|
||||
|
||||
_sq.first += fitness;
|
||||
_sq.second += fitness * fitness;
|
||||
|
|
@ -211,9 +221,11 @@ public :
|
|||
value().second = sqrt( (result.second - n * value().first * value().first) / (n - 1.0)); // stdev
|
||||
}
|
||||
|
||||
virtual std::string className(void) const { return "eoSecondMomentStats"; }
|
||||
virtual std::string className(void) const { return "eoSecondMomentStats"; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
The n_th element fitness in the population (see eoBestFitnessStat)
|
||||
*/
|
||||
|
|
@ -244,6 +256,7 @@ public :
|
|||
virtual std::string className(void) const { return "eoNthElementFitnessStat"; }
|
||||
private :
|
||||
|
||||
/* Very old code...
|
||||
struct CmpFitness
|
||||
{
|
||||
CmpFitness(unsigned _whichElement, bool _maxim) : whichElement(_whichElement), maxim(_maxim) {}
|
||||
|
|
@ -259,6 +272,7 @@ private :
|
|||
unsigned whichElement;
|
||||
bool maxim;
|
||||
};
|
||||
*/
|
||||
|
||||
// for everything else
|
||||
template <class T>
|
||||
|
|
@ -329,6 +343,7 @@ public:
|
|||
|
||||
private :
|
||||
|
||||
/* Very old code...
|
||||
struct CmpFitness
|
||||
{
|
||||
CmpFitness(unsigned _which, bool _maxim) : which(_which), maxim(_maxim) {}
|
||||
|
|
@ -344,6 +359,7 @@ private :
|
|||
unsigned which;
|
||||
bool maxim;
|
||||
};
|
||||
*/
|
||||
|
||||
// default
|
||||
template<class T>
|
||||
|
|
@ -356,6 +372,39 @@ private :
|
|||
/** @example t-eoSSGA.cpp
|
||||
*/
|
||||
|
||||
|
||||
/** Keep the best individual found so far
|
||||
*/
|
||||
template <class EOT>
|
||||
class eoBestIndividualStat : public eoStat<EOT, EOT>
|
||||
{
|
||||
public:
|
||||
using eoStat<EOT, EOT>::value;
|
||||
|
||||
eoBestIndividualStat(std::string _description = "BestIndiv ")
|
||||
: eoStat<EOT, EOT>( EOT(), _description )
|
||||
{}
|
||||
|
||||
void operator()(const eoPop<EOT>& pop)
|
||||
{
|
||||
EOT best = pop.best_element();
|
||||
// on the first call, value() is invalid
|
||||
if( value().invalid() ) {
|
||||
// thus we cannot compare it to something else
|
||||
value() = best;
|
||||
} else {
|
||||
// keep the best individual found so far
|
||||
if( best.fitness() > value().fitness() ) {
|
||||
value() = best;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string className(void) const { return "eoBestIndividualStat"; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <class EOT>
|
||||
class eoDistanceStat : public eoStat<EOT, double>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ using namespace std;
|
|||
|
||||
|
||||
|
||||
void removeComment(string& str, string comment)
|
||||
void eoState::removeComment(string& str, string comment)
|
||||
{
|
||||
string::size_type pos = str.find(comment);
|
||||
|
||||
|
|
@ -28,21 +28,23 @@ void removeComment(string& str, string comment)
|
|||
}
|
||||
}
|
||||
|
||||
bool is_section(const string& str, string& name)
|
||||
bool eoState::is_section(const string& str, string& name)
|
||||
{
|
||||
string::size_type pos = str.find("\\section{");
|
||||
string::size_type pos = str.find(_tag_section_so);
|
||||
|
||||
if (pos == string::npos)
|
||||
return false;
|
||||
//else
|
||||
|
||||
string::size_type end = str.find("}");
|
||||
string::size_type end = str.find(_tag_section_sc);
|
||||
|
||||
if (end == string::npos)
|
||||
return false;
|
||||
// else
|
||||
|
||||
name = str.substr(pos + 9, end-9);
|
||||
// affect name, passed by reference
|
||||
// Note: substr( start, count )
|
||||
name = str.substr( pos + _tag_section_so.size(), end - _tag_section_so.size() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -84,6 +86,7 @@ void eoState::load(const string& _filename)
|
|||
load(is);
|
||||
}
|
||||
|
||||
// FIXME implement parsing and loading of other formats
|
||||
void eoState::load(std::istream& is)
|
||||
{
|
||||
string str;
|
||||
|
|
@ -158,16 +161,49 @@ void eoState::save(const string& filename) const
|
|||
save(os);
|
||||
}
|
||||
|
||||
void eoState::save(std::ostream& os) const
|
||||
{ // saves in order of insertion
|
||||
for (vector<ObjectMap::iterator>::const_iterator it = creationOrder.begin(); it != creationOrder.end(); ++it)
|
||||
{
|
||||
os << "\\section{" << (*it)->first << "}\n";
|
||||
(*it)->second->printOn(os);
|
||||
os << '\n';
|
||||
}
|
||||
//void eoState::save(std::ostream& os) const
|
||||
//{ // saves in order of insertion
|
||||
// for (vector<ObjectMap::iterator>::const_iterator it = creationOrder.begin(); it != creationOrder.end(); ++it)
|
||||
// {
|
||||
// os << "\\section{" << (*it)->first << "}\n";
|
||||
// (*it)->second->printOn(os);
|
||||
// os << '\n';
|
||||
// }
|
||||
//}
|
||||
|
||||
void eoState::saveSection( std::ostream& os, vector<ObjectMap::iterator>::const_iterator it) const
|
||||
{
|
||||
os << _tag_section_so << (*it)->first << _tag_section_sc;
|
||||
|
||||
os << _tag_content_s;
|
||||
(*it)->second->printOn(os);
|
||||
os << _tag_content_e;
|
||||
|
||||
os << _tag_section_e;
|
||||
}
|
||||
|
||||
|
||||
void eoState::save(std::ostream& os) const
|
||||
{
|
||||
os << _tag_state_so << _tag_state_name << _tag_state_sc;
|
||||
|
||||
// save the first section
|
||||
assert( creationOrder.size() > 0 );
|
||||
// saves in order of insertion
|
||||
vector<ObjectMap::iterator>::const_iterator it = creationOrder.begin();
|
||||
saveSection(os,it);
|
||||
it++;
|
||||
|
||||
while( it != creationOrder.end() ) {
|
||||
// add a separator only before [1,n] elements
|
||||
os << _tag_section_sep;
|
||||
saveSection(os, it);
|
||||
it++;
|
||||
}
|
||||
os << _tag_state_e;
|
||||
}
|
||||
|
||||
|
||||
string eoState::createObjectName(eoObject* obj)
|
||||
{
|
||||
if (obj == 0)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
|
||||
#include <eoFunctorStore.h>
|
||||
|
||||
|
|
@ -56,10 +57,50 @@ class eoState : public eoFunctorStore
|
|||
{
|
||||
public :
|
||||
|
||||
eoState(void) {}
|
||||
eoState(std::string name="") :
|
||||
_tag_state_so(""),
|
||||
_tag_state_name(name),
|
||||
_tag_state_sc(""),
|
||||
_tag_section_so("\\section{"),
|
||||
_tag_section_sc("}\n"),
|
||||
_tag_content_s(""),
|
||||
_tag_content_e(""),
|
||||
_tag_section_sep(""),
|
||||
_tag_section_e("\n"),
|
||||
_tag_state_e("")
|
||||
{}
|
||||
|
||||
~eoState(void);
|
||||
|
||||
void formatLatex(std::string name)
|
||||
{
|
||||
_tag_state_so = "";
|
||||
_tag_state_name = name;
|
||||
_tag_state_sc = "";
|
||||
_tag_section_so = "\\section{";
|
||||
_tag_section_sc = "}\n";
|
||||
_tag_content_s = "";
|
||||
_tag_content_e = "";
|
||||
_tag_section_sep = "";
|
||||
_tag_section_e = "\n";
|
||||
_tag_state_e = "";
|
||||
}
|
||||
|
||||
void formatJSON(std::string name)
|
||||
{
|
||||
_tag_state_so = "{ \"";
|
||||
_tag_state_name = name;
|
||||
_tag_state_sc = "\":\n";
|
||||
_tag_section_so = "\t{ \"";
|
||||
_tag_section_sc = "\":\n";
|
||||
_tag_content_s = "\"";
|
||||
_tag_content_e = "\"";
|
||||
_tag_section_sep = ",\n";
|
||||
_tag_section_e = "\t}\n";
|
||||
_tag_state_e = "}\n";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Object registration function, note that it does not take ownership!
|
||||
*/
|
||||
|
|
@ -131,6 +172,43 @@ private :
|
|||
eoState(const eoState&);
|
||||
eoState& operator=(const eoState&);
|
||||
|
||||
/* \@{
|
||||
* s=start, e=end
|
||||
* o=open, c=close
|
||||
*
|
||||
* { "my_state":
|
||||
* {
|
||||
* "section_pop":"…",
|
||||
* "section_rng":"…"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // JSON LATEX (default)
|
||||
*/
|
||||
std::string _tag_state_so; // { "
|
||||
std::string _tag_state_name; // my_state
|
||||
std::string _tag_state_sc; // ":
|
||||
|
||||
std::string _tag_section_so; // { " \\section{
|
||||
std::string _tag_section_sc; // ": }\n
|
||||
|
||||
std::string _tag_content_s; // "
|
||||
std::string _tag_content_e; // "
|
||||
|
||||
std::string _tag_section_sep;// ,
|
||||
|
||||
std::string _tag_section_e; // } \n
|
||||
|
||||
std::string _tag_state_e; // }
|
||||
/** \@} */
|
||||
|
||||
void removeComment( std::string& str, std::string comment);
|
||||
|
||||
bool is_section(const std::string& str, std::string& name);
|
||||
|
||||
protected:
|
||||
void saveSection( std::ostream& os, std::vector<ObjectMap::iterator>::const_iterator it) const;
|
||||
|
||||
};
|
||||
/** @example t-eoStateAndParser.cpp
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ Authors:
|
|||
class eoStdoutMonitor : public eoOStreamMonitor
|
||||
{
|
||||
public :
|
||||
/* FIXME remove in next release
|
||||
eoStdoutMonitor(bool _verbose, std::string _delim = "\t", unsigned int _width=20, char _fill=' ' ) :
|
||||
eoOStreamMonitor( std::cout, _verbose, _delim, _width, _fill)
|
||||
{
|
||||
|
|
@ -50,6 +51,7 @@ public :
|
|||
eo::log << eo::warnings << "WARNING: the use of the verbose parameter in eoStdoutMonitor constructor is deprecated and will be removed in the next release" << std::endl;
|
||||
#endif // !DEPRECATED_MESSAGES
|
||||
}
|
||||
*/
|
||||
|
||||
eoStdoutMonitor(std::string _delim = "\t", unsigned int _width=20, char _fill=' ' ) :
|
||||
eoOStreamMonitor( std::cout, _delim, _width, _fill)
|
||||
|
|
|
|||
329
eo/src/utils/eoTimer.h
Normal file
329
eo/src/utils/eoTimer.h
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
# ifndef __EO_TIMER_H__
|
||||
# define __EO_TIMER_H__
|
||||
|
||||
# include <sys/time.h> // time()
|
||||
# include <sys/resource.h> // rusage()
|
||||
|
||||
# include <vector> // std::vector
|
||||
# include <map> // std::map
|
||||
|
||||
# include "utils/eoParallel.h" // eo::parallel
|
||||
|
||||
# include "serial/eoSerial.h" // eo::Persistent
|
||||
|
||||
/**
|
||||
* @brief Timer allowing to measure time between a start point and a stop point.
|
||||
*
|
||||
* This timer allows the user to measure user time, system time and wallclock time
|
||||
* between two points. Basically, user time is time spent in developer code ; system
|
||||
* time is time spent during the IO wait and system calls ; wallclock is the difference
|
||||
* of time we could observe by measuring time with a watch.
|
||||
*
|
||||
* @ingroup Utilities
|
||||
*/
|
||||
class eoTimer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Default ctor. Begins all the timers.
|
||||
*/
|
||||
eoTimer()
|
||||
{
|
||||
uuremainder = 0;
|
||||
usremainder = 0;
|
||||
restart();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restarts all the timers and launch the measure.
|
||||
*/
|
||||
void restart()
|
||||
{
|
||||
wc_start = time(NULL);
|
||||
getrusage( RUSAGE_SELF, &_start );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Measures the user time spent since the last restart().
|
||||
*
|
||||
* If the number of elapsed seconds is zero, the spent milliseconds are
|
||||
* added to a remainder. If the remainder exceeds one second, it is
|
||||
* added to the number of elapsed seconds.
|
||||
*
|
||||
* @return Number of seconds elapsed in user space.
|
||||
*/
|
||||
long int usertime()
|
||||
{
|
||||
struct rusage _now;
|
||||
getrusage( RUSAGE_SELF, &_now );
|
||||
|
||||
long int result = _now.ru_utime.tv_sec - _start.ru_utime.tv_sec;
|
||||
long int remainder = _now.ru_utime.tv_usec - _start.ru_utime.tv_usec;
|
||||
if( remainder >= 0 )
|
||||
{
|
||||
uuremainder += remainder;
|
||||
} else
|
||||
{
|
||||
uuremainder += ( 1000000 - remainder );
|
||||
--result;
|
||||
}
|
||||
|
||||
if( uuremainder >= 1000000 )
|
||||
{
|
||||
uuremainder -= 1000000;
|
||||
++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Measures the system time spent since the last restart().
|
||||
*
|
||||
* If the number of elapsed seconds is zero, the spent milliseconds are
|
||||
* added to a remainder. If the remainder exceeds one second, it is
|
||||
* added to the number of elapsed seconds.
|
||||
*
|
||||
* @return Number of seconds elapsed in system (kernel) space.
|
||||
*/
|
||||
long int systime()
|
||||
{
|
||||
struct rusage _now;
|
||||
getrusage( RUSAGE_SELF, &_now );
|
||||
|
||||
long int result = _now.ru_stime.tv_sec - _start.ru_stime.tv_sec;
|
||||
long int remainder = _now.ru_stime.tv_usec - _start.ru_stime.tv_usec;
|
||||
if( remainder >= 0 )
|
||||
{
|
||||
usremainder += remainder;
|
||||
} else
|
||||
{
|
||||
usremainder += ( 1000000 - remainder );
|
||||
--result;
|
||||
}
|
||||
|
||||
if( usremainder >= 1000000 )
|
||||
{
|
||||
usremainder -= 1000000;
|
||||
++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Measures the wallclock time spent since the last restart().
|
||||
*
|
||||
* @return Number of seconds elapsed, as a double.
|
||||
*/
|
||||
double wallclock()
|
||||
{
|
||||
return std::difftime( std::time(NULL) , wc_start );
|
||||
}
|
||||
|
||||
protected:
|
||||
// Structure used to measure user and system time.
|
||||
struct rusage _start;
|
||||
// Remainder (in milliseconds) for user time.
|
||||
long int uuremainder;
|
||||
// Remainder (in milliseconds) for system time.
|
||||
long int usremainder;
|
||||
// Structure used to measure wallclock time.
|
||||
time_t wc_start;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Registers a group of statistics, each statistic corresponding to user, system and wallclock times distribution.
|
||||
*
|
||||
* This class helps the user to measure time in different parts of an application. A name is associated to a statistic,
|
||||
* on each call to start() and stop() for this name, a new number is added to the statistic, for each of the three
|
||||
* measured times.
|
||||
*
|
||||
* The statistics are only registered if the option "--parallelized-do-measure" is set to true, which can be checked
|
||||
* thanks to global object eo::parallel.
|
||||
*
|
||||
* This shows how the eoTimerStat can be used :
|
||||
* @code
|
||||
* eoTimerStat timerStat;
|
||||
* timerStat.start("first_point");
|
||||
* for( int i = 0; i < 1000; ++i )
|
||||
* {
|
||||
* timerStat.start("single_computation");
|
||||
* single_computation( i );
|
||||
* timerStat.stop("single_computation");
|
||||
* }
|
||||
* // After this loop, timerStat contains a statistic of key "single_computation" which contains 1000 measures for
|
||||
* // each type of time.
|
||||
* timerStat.stop("first_point");
|
||||
* // After this line, timerStat contains another statistic of key "first_point" which counted the duration of the
|
||||
* // whole loop.
|
||||
*
|
||||
* int singleComputationUsertimeMean = 0;
|
||||
* for( int i = 0; i < 1000; ++i )
|
||||
* {
|
||||
* singleComputationUsertimeMean += timerStat.stats()["single_computation"].utime[i];
|
||||
* }
|
||||
* std::cout << "Mean of user time spent in single computation: " << singleComputationUsertimeMean / 1000. << std::endl;
|
||||
* @endcode
|
||||
*
|
||||
* When using MPI, these statistics can be readily be serialized, so as to be sent over a network, for instance.
|
||||
*
|
||||
* Implementation details: this eoTimerStat is in fact a map of strings (key) / Stat (value). Stat is an internal
|
||||
* structure directly defined in the class, which contains three vectors modeling the distributions of the different
|
||||
* types of elapsed times. Another map of strings (key) / eoTimer (value) allows to effectively retrieve the different
|
||||
* times. The struct Stat will be exposed to client, which will use its members ; however,
|
||||
* the client doesn't have anything to do directly with the timer, that's why the two maps are splitted.
|
||||
*
|
||||
* @ingroup Utilities
|
||||
*/
|
||||
class eoTimerStat
|
||||
# ifdef WITH_MPI
|
||||
: public eoserial::Persistent
|
||||
# endif
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Statistic related to a key (name).
|
||||
*
|
||||
* This structure is the value in the map saved in the eoTimerStat. It contains the statistic bound to a key,
|
||||
* which are the user time distribution, the system time distribution and the wallclock time distribution, as
|
||||
* std::vector s.
|
||||
*
|
||||
* It can readily be serialized with boost when compiling with mpi.
|
||||
*/
|
||||
struct Stat
|
||||
# ifdef WITH_MPI
|
||||
: public eoserial::Persistent
|
||||
# endif
|
||||
{
|
||||
std::vector<long int> utime;
|
||||
std::vector<long int> stime;
|
||||
std::vector<double> wtime;
|
||||
#ifdef WITH_MPI
|
||||
void unpack( const eoserial::Object* obj )
|
||||
{
|
||||
utime.clear();
|
||||
static_cast< eoserial::Array* >(obj->find("utime")->second)
|
||||
->deserialize< std::vector<long int>, eoserial::Array::UnpackAlgorithm >( utime );
|
||||
|
||||
stime.clear();
|
||||
static_cast< eoserial::Array* >(obj->find("stime")->second)
|
||||
->deserialize< std::vector<long int>, eoserial::Array::UnpackAlgorithm >( stime );
|
||||
|
||||
wtime.clear();
|
||||
static_cast< eoserial::Array* >(obj->find("wtime")->second)
|
||||
->deserialize< std::vector<double>, eoserial::Array::UnpackAlgorithm >( wtime );
|
||||
}
|
||||
|
||||
eoserial::Object* pack( void ) const
|
||||
{
|
||||
eoserial::Object* obj = new eoserial::Object;
|
||||
obj->add("utime", eoserial::makeArray< std::vector<long int>, eoserial::MakeAlgorithm >( utime ) );
|
||||
obj->add("stime", eoserial::makeArray< std::vector<long int>, eoserial::MakeAlgorithm >( stime ) );
|
||||
obj->add("wtime", eoserial::makeArray< std::vector<double>, eoserial::MakeAlgorithm >( wtime ) );
|
||||
return obj;
|
||||
}
|
||||
# endif
|
||||
};
|
||||
|
||||
#ifdef WITH_MPI
|
||||
void unpack( const eoserial::Object* obj )
|
||||
{
|
||||
_stats.clear();
|
||||
for( eoserial::Object::const_iterator it = obj->begin(), final = obj->end();
|
||||
it != final;
|
||||
++it)
|
||||
{
|
||||
eoserial::unpackObject( *obj, it->first, _stats[ it->first ] );
|
||||
}
|
||||
}
|
||||
|
||||
eoserial::Object* pack( void ) const
|
||||
{
|
||||
eoserial::Object* obj = new eoserial::Object;
|
||||
for( std::map<std::string, Stat >::const_iterator it = _stats.begin(), final = _stats.end();
|
||||
it != final;
|
||||
++it)
|
||||
{
|
||||
obj->add( it->first, it->second.pack() );
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Starts a new measure for the given key.
|
||||
*
|
||||
* This is only performed if parallel.doMeasure() is true, which is equivalent to the fact that
|
||||
* parser found "--parallel-do-measure=1" in command line args.
|
||||
*
|
||||
* @param key The key of the statistic.
|
||||
*/
|
||||
void start( const std::string & key )
|
||||
{
|
||||
if( eo::parallel.doMeasure() )
|
||||
{
|
||||
_timers[ key ].restart();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the mesure for the given key and saves the elapsed times.
|
||||
*
|
||||
* Must follow a call of start with the same key.
|
||||
*
|
||||
* This is only performed if parallel.doMeasure() is true, which is equivalent to the fact that
|
||||
* parser found "--parallel-do-measure=1" in command line args.
|
||||
*
|
||||
* @param key The key of the statistic.
|
||||
*/
|
||||
void stop( const std::string& key )
|
||||
{
|
||||
if( eo::parallel.doMeasure() )
|
||||
{
|
||||
Stat & s = _stats[ key ];
|
||||
eoTimer & t = _timers[ key ];
|
||||
s.utime.push_back( t.usertime() );
|
||||
s.stime.push_back( t.systime() );
|
||||
s.wtime.push_back( t.wallclock() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Getter for the statistics map.
|
||||
*/
|
||||
std::map< std::string, Stat >& stats()
|
||||
{
|
||||
return _stats;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Statistics map: links a key (string) to a statistic.
|
||||
std::map< std::string, Stat > _stats;
|
||||
// Timers map: links a key to its timer.
|
||||
std::map< std::string, eoTimer > _timers;
|
||||
};
|
||||
|
||||
# endif // __TIMER_H__
|
||||
|
||||
|
|
@ -9,22 +9,22 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/contrib)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/contrib/MGE)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${EO_SRC_DIR}/contrib)
|
||||
include_directories(${EO_SRC_DIR}/contrib/MGE)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries
|
||||
######################################################################################
|
||||
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
link_directories(${EO_BIN_DIR}/lib)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your targets and link the librairies
|
||||
######################################################################################
|
||||
|
||||
SET (TEST_LIST
|
||||
set (TEST_LIST
|
||||
t-eofitness
|
||||
t-eoRandom
|
||||
t-eobin
|
||||
|
|
@ -72,45 +72,45 @@ SET (TEST_LIST
|
|||
)
|
||||
|
||||
|
||||
FOREACH (test ${TEST_LIST})
|
||||
SET ("T_${test}_SOURCES" "${test}.cpp")
|
||||
ENDFOREACH (test)
|
||||
foreach (test ${TEST_LIST})
|
||||
set ("T_${test}_SOURCES" "${test}.cpp")
|
||||
endforeach (test)
|
||||
|
||||
|
||||
IF(ENABLE_MINIMAL_CMAKE_TESTING)
|
||||
if(ENABLE_MINIMAL_CMAKE_TESTING)
|
||||
|
||||
SET (MIN_TEST_LIST t-eoEasyPSO)
|
||||
FOREACH (mintest ${MIN_TEST_LIST})
|
||||
SET ("T_${mintest}_SOURCES" "${mintest}.cpp")
|
||||
ADD_EXECUTABLE(${mintest} ${T_${mintest}_SOURCES})
|
||||
ADD_TEST(${mintest} ${mintest})
|
||||
TARGET_LINK_LIBRARIES(${mintest} ga es cma eoutils eo)
|
||||
ENDFOREACH (mintest)
|
||||
set (MIN_TEST_LIST t-eoEasyPSO)
|
||||
foreach (mintest ${MIN_TEST_LIST})
|
||||
set ("T_${mintest}_SOURCES" "${mintest}.cpp")
|
||||
add_executable(${mintest} ${T_${mintest}_SOURCES})
|
||||
add_test(${mintest} ${mintest})
|
||||
target_link_libraries(${mintest} ga es cma eoutils eo)
|
||||
endforeach (mintest)
|
||||
|
||||
ELSEIF(ENABLE_CMAKE_TESTING)
|
||||
elseif(ENABLE_CMAKE_TESTING)
|
||||
|
||||
FOREACH (test ${TEST_LIST})
|
||||
ADD_EXECUTABLE(${test} ${T_${test}_SOURCES})
|
||||
ADD_TEST(${test} ${test})
|
||||
TARGET_LINK_LIBRARIES(${test} ga es cma eoutils eo)
|
||||
INSTALL(TARGETS ${test} RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/test COMPONENT test)
|
||||
ENDFOREACH (test)
|
||||
foreach (test ${TEST_LIST})
|
||||
add_executable(${test} ${T_${test}_SOURCES})
|
||||
add_test(${test} ${test})
|
||||
target_link_libraries(${test} ga es cma eoutils eo)
|
||||
install(TARGETS ${test} RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/test COMPONENT test)
|
||||
endforeach (test)
|
||||
|
||||
SET(RESOURCES
|
||||
set(RESOURCES
|
||||
boxplot.py
|
||||
boxplot_to_png.py
|
||||
boxplot_to_pdf.py
|
||||
t-openmp.py
|
||||
)
|
||||
|
||||
FOREACH(file ${RESOURCES})
|
||||
EXECUTE_PROCESS(
|
||||
foreach(file ${RESOURCES})
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${file}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${file}
|
||||
)
|
||||
ENDFOREACH(file)
|
||||
endforeach(file)
|
||||
|
||||
ENDIF(ENABLE_MINIMAL_CMAKE_TESTING)
|
||||
endif(ENABLE_MINIMAL_CMAKE_TESTING)
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
54
eo/test/mpi/CMakeLists.txt
Normal file
54
eo/test/mpi/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
###############################################################################
|
||||
##
|
||||
## CMakeLists file for eo/test/mpi
|
||||
##
|
||||
###############################################################################
|
||||
|
||||
######################################################################################
|
||||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
message("EO SOURCE DIR: ${EO_SRC_DIR}")
|
||||
message("OMPI: ${MPI_DIR}")
|
||||
|
||||
include_directories(${MPI_DIR}/include)
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries
|
||||
######################################################################################
|
||||
|
||||
link_directories(${EO_BIN_DIR}/lib)
|
||||
link_directories(${MPI_DIR}/lib)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your targets and link the librairies
|
||||
######################################################################################
|
||||
|
||||
set (TEST_LIST
|
||||
t-mpi-parallelApply
|
||||
t-mpi-wrapper
|
||||
t-mpi-multipleRoles
|
||||
t-mpi-eval
|
||||
t-mpi-multistart
|
||||
t-mpi-distrib-exp
|
||||
)
|
||||
|
||||
foreach (test ${TEST_LIST})
|
||||
set ("T_${test}_SOURCES" "${test}.cpp")
|
||||
endforeach (test)
|
||||
|
||||
set(CMAKE_CXX_COMPILER "mpicxx")
|
||||
add_definitions(-DWITH_MPI)
|
||||
|
||||
if(ENABLE_CMAKE_TESTING)
|
||||
foreach (test ${TEST_LIST})
|
||||
add_executable(${test} ${T_${test}_SOURCES})
|
||||
add_test(${test} ${test})
|
||||
target_link_libraries(${test} eoutils eompi eoserial eo)
|
||||
install(TARGETS ${test} RUNTIME DESTINATION share/eo/test COMPONENT test)
|
||||
endforeach (test)
|
||||
endif()
|
||||
|
||||
######################################################################################
|
||||
51
eo/test/mpi/t-mpi-common.h
Normal file
51
eo/test/mpi/t-mpi-common.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# ifndef __T_MPI_COMMON_H__
|
||||
# define __T_MPI_COMMON_H__
|
||||
|
||||
#include <serial/eoSerial.h>
|
||||
|
||||
/**
|
||||
* @file t-mpi-common.h
|
||||
*
|
||||
* This file shows an example of serialization of a primitive type, so as to be used in a parallel algorithm.
|
||||
* It is fully compatible with the basic type, by implementing conversion operator and constructor based on type.
|
||||
* It can contain any simple type which can be written in a std::ostream.
|
||||
*/
|
||||
|
||||
template< class T >
|
||||
struct SerializableBase : public eoserial::Persistent
|
||||
{
|
||||
public:
|
||||
|
||||
operator T&()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
SerializableBase() : _value()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
SerializableBase( T base ) : _value( base )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
void unpack( const eoserial::Object* obj )
|
||||
{
|
||||
eoserial::unpack( *obj, "value", _value );
|
||||
}
|
||||
|
||||
eoserial::Object* pack(void) const
|
||||
{
|
||||
eoserial::Object* obj = new eoserial::Object;
|
||||
obj->add("value", eoserial::make( _value ) );
|
||||
return obj;
|
||||
}
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
|
||||
|
||||
# endif // __T_MPI_COMMON_H__
|
||||
135
eo/test/mpi/t-mpi-distrib-exp.cpp
Normal file
135
eo/test/mpi/t-mpi-distrib-exp.cpp
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
# include <unistd.h> // usleep
|
||||
|
||||
# include <iostream>
|
||||
# include <string>
|
||||
# include <vector>
|
||||
|
||||
# include <eo>
|
||||
|
||||
# include <mpi/eoParallelApply.h>
|
||||
# include "../test/mpi/t-mpi-common.h"
|
||||
|
||||
using namespace eo::mpi;
|
||||
|
||||
typedef SerializableBase<int> type;
|
||||
|
||||
struct Wait : public eoUF< type &, void >
|
||||
{
|
||||
void operator()( type & milliseconds )
|
||||
{
|
||||
std::cout << "Sleeping for " << milliseconds << "ms..." << std::endl;
|
||||
// usleep takes an input in microseconds
|
||||
usleep( milliseconds * 1000 );
|
||||
}
|
||||
} wait;
|
||||
|
||||
class Distribution : public std::vector< type >
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Really fills the vector with the distribution values.
|
||||
*/
|
||||
void fill( unsigned size )
|
||||
{
|
||||
for( unsigned i = 0; i < size; ++i )
|
||||
{
|
||||
push_back( next_element() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the next element of the distribution to put in the
|
||||
* vector.
|
||||
*
|
||||
* @returns Number of milliseconds to wait
|
||||
*/
|
||||
virtual int next_element() = 0;
|
||||
|
||||
// Idea for function name: enlarge_your_parser
|
||||
/**
|
||||
* @brief Creates params and retrieves values from parser
|
||||
*/
|
||||
virtual void make_parser( eoParser & parser ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns true if this distribution has been activated by the
|
||||
* command line.
|
||||
*
|
||||
* Serves to main program to check if at least one distribution has been
|
||||
* activated.
|
||||
*/
|
||||
bool isActive() { return _active; }
|
||||
|
||||
protected:
|
||||
|
||||
bool _active;
|
||||
};
|
||||
|
||||
class UniformDistribution : public Distribution
|
||||
{
|
||||
public:
|
||||
|
||||
UniformDistribution() : _rng(0)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
void make_parser( eoParser & parser )
|
||||
{
|
||||
_active = parser.createParam( false, "uniform", "Uniform distribution", '\0', "Uniform").value();
|
||||
_min = parser.createParam( 0.0, "uniform-min", "Minimum for uniform distribution", '\0', "Uniform").value();
|
||||
_max = parser.createParam( 1.0, "uniform-max", "Maximum for uniform distribution", '\0', "Uniform").value();
|
||||
}
|
||||
|
||||
int next_element()
|
||||
{
|
||||
return std::floor( 1000. * _rng.uniform( _min, _max ) );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
eoRng _rng;
|
||||
|
||||
double _min;
|
||||
double _max;
|
||||
|
||||
} uniformDistribution;
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
Node::init( argc, argv );
|
||||
eoParser parser( argc, argv );
|
||||
|
||||
// TODO for each available distribution, check if activated.
|
||||
// If no distribution is activated, show an error message
|
||||
// If two distributions or more are activated, show an error message
|
||||
// Otherwise, use the activated distribution as distrib
|
||||
Distribution & distrib = uniformDistribution;
|
||||
// Make parser of distribution here
|
||||
distrib.make_parser( parser );
|
||||
|
||||
unsigned size = parser.createParam( 10U, "size", "Number of elements to distribute.", 's', "Distribution").value();
|
||||
unsigned packet_size = parser.createParam( 1U, "packet_size", "Number of elements to distribute at each time for a single worker.", 'p', "Parallelization").value();
|
||||
|
||||
make_parallel( parser );
|
||||
make_help( parser );
|
||||
|
||||
ParallelApplyStore< type> store( wait, DEFAULT_MASTER, packet_size );
|
||||
|
||||
// Fill distribution
|
||||
distrib.fill( size );
|
||||
store.data( distrib );
|
||||
|
||||
DynamicAssignmentAlgorithm scheduling;
|
||||
ParallelApply< type > job( scheduling, DEFAULT_MASTER, store );
|
||||
|
||||
job.run();
|
||||
|
||||
if( job.isMaster() )
|
||||
{
|
||||
EmptyJob( scheduling, DEFAULT_MASTER ); // to terminate parallel apply
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
206
eo/test/mpi/t-mpi-eval.cpp
Normal file
206
eo/test/mpi/t-mpi-eval.cpp
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file shows an example of parallel evaluation of a population, when using an eoEasyEA algorithm.
|
||||
* Moreover, we add a basic wrapper on the parallel evaluation, so as to show how to retrieve the best solutions.
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <eo>
|
||||
#include <eoPopEvalFunc.h>
|
||||
|
||||
#include <es/make_real.h>
|
||||
#include "../real_value.h"
|
||||
|
||||
#include <mpi/eoMpi.h>
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class eoRealSerializable : public eoReal< eoMinimizingFitness >, public eoserial::Persistent
|
||||
{
|
||||
public:
|
||||
|
||||
eoRealSerializable(unsigned size = 0, double value = 0.0):
|
||||
eoReal<eoMinimizingFitness>(size, value) {}
|
||||
|
||||
eoserial::Object* pack() const
|
||||
{
|
||||
eoserial::Object* obj = new eoserial::Object;
|
||||
obj->add( "array",
|
||||
eoserial::makeArray< vector<double>, eoserial::MakeAlgorithm >
|
||||
( *this )
|
||||
);
|
||||
|
||||
bool invalidFitness = invalid();
|
||||
obj->add("invalid", eoserial::make( invalidFitness ) );
|
||||
if( !invalidFitness )
|
||||
{
|
||||
double fitnessVal = fitness();
|
||||
obj->add("fitness", eoserial::make( fitnessVal ) );
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
void unpack( const eoserial::Object* obj )
|
||||
{
|
||||
this->clear();
|
||||
eoserial::unpackArray< vector<double>, eoserial::Array::UnpackAlgorithm >
|
||||
( *obj, "array", *this );
|
||||
|
||||
bool invalidFitness;
|
||||
eoserial::unpack( *obj, "invalid", invalidFitness );
|
||||
if( invalidFitness ) {
|
||||
invalidate();
|
||||
} else {
|
||||
double fitnessVal;
|
||||
eoserial::unpack<double>( *obj, "fitness", fitnessVal );
|
||||
fitness( fitnessVal );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef eoRealSerializable EOT;
|
||||
|
||||
/*
|
||||
* Wrapper for HandleResponse: shows the best answer, as it is found.
|
||||
*
|
||||
* Finding the best solution is an associative operation (as it is based on a "min" function, which is associative too)
|
||||
* and that's why we can perform it here. Indeed, the min element of 5 elements is the min element of the 3 first
|
||||
* elements and the min element of the 2 last elements:
|
||||
* min(1, 2, 3, 4, 5) = min( min(1, 2, 3), min(4, 5) )
|
||||
*
|
||||
* This is a reduction. See MapReduce example to have another examples of reduction.
|
||||
*/
|
||||
struct CatBestAnswers : public eo::mpi::HandleResponseParallelApply<EOT>
|
||||
{
|
||||
CatBestAnswers()
|
||||
{
|
||||
best.fitness( 1000000000. );
|
||||
}
|
||||
|
||||
/*
|
||||
our structure inherits the member _wrapped from HandleResponseFunction,
|
||||
which is a HandleResponseFunction pointer;
|
||||
|
||||
it inherits also the member _d (like Data), which is a pointer to the
|
||||
ParallelApplyData used in the HandleResponseParallelApply<EOT>. Details
|
||||
of this data are contained in the file eoParallelApply. We need just to know that
|
||||
it contains a member assignedTasks which maps a worker rank and the sent slice
|
||||
to be processed by the worker, and a reference to the processed table via the
|
||||
call of the data() function.
|
||||
*/
|
||||
|
||||
// if EOT were a template, we would have to do: (thank you C++ :)
|
||||
// using eo::mpi::HandleResponseParallelApply<EOT>::_wrapped;
|
||||
// using eo::mpi::HandleResponseParallelApply<EOT>::d;
|
||||
|
||||
void operator()(int wrkRank)
|
||||
{
|
||||
eo::mpi::ParallelApplyData<EOT> * d = _data;
|
||||
// Retrieve informations about the slice processed by the worker
|
||||
int index = d->assignedTasks[wrkRank].index;
|
||||
int size = d->assignedTasks[wrkRank].size;
|
||||
// call to the wrapped function HERE
|
||||
(*_wrapped)( wrkRank );
|
||||
// Compare fitnesses of evaluated individuals with the best saved
|
||||
for(int i = index; i < index+size; ++i)
|
||||
{
|
||||
if( best.fitness() < d->table()[ i ].fitness() )
|
||||
{
|
||||
eo::log << eo::quiet << "Better solution found:" << d->table()[i].fitness() << std::endl;
|
||||
best = d->table()[ i ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
EOT best;
|
||||
};
|
||||
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
eo::mpi::Node::init( ac, av );
|
||||
// eo::log << eo::setlevel( eo::debug );
|
||||
eo::log << eo::setlevel( eo::quiet );
|
||||
|
||||
eoParser parser(ac, av);
|
||||
|
||||
unsigned int popSize = parser.getORcreateParam((unsigned int)100, "popSize", "Population Size", 'P', "Evolution Engine").value();
|
||||
unsigned int dimSize = parser.getORcreateParam((unsigned int)10, "dimSize", "Dimension Size", 'd', "Evolution Engine").value();
|
||||
|
||||
uint32_t seedParam = parser.getORcreateParam((uint32_t)0, "seed", "Random number seed", 0).value();
|
||||
if (seedParam == 0) { seedParam = time(0); }
|
||||
|
||||
make_parallel(parser);
|
||||
make_help(parser);
|
||||
|
||||
rng.reseed( seedParam );
|
||||
|
||||
eoUniformGenerator< double > gen(-5, 5);
|
||||
eoInitFixedLength< EOT > init( dimSize, gen );
|
||||
|
||||
eoEvalFuncPtr< EOT, double, const std::vector< double >& > mainEval( real_value );
|
||||
eoEvalFuncCounter< EOT > eval( mainEval );
|
||||
|
||||
// until this point, everything (but eo::mpi::Node::init) is exactly as in an sequential version.
|
||||
// We then instanciate the parallel algorithm. The store is directly used by the eoParallelPopLoopEval, which
|
||||
// internally uses parallel apply.
|
||||
int rank = eo::mpi::Node::comm().rank();
|
||||
eo::mpi::DynamicAssignmentAlgorithm assign;
|
||||
if( rank == eo::mpi::DEFAULT_MASTER )
|
||||
{
|
||||
eoPop< EOT > pop( popSize, init );
|
||||
|
||||
eo::log << "Size of population : " << popSize << std::endl;
|
||||
|
||||
eo::mpi::ParallelApplyStore< EOT > store( eval, eo::mpi::DEFAULT_MASTER );
|
||||
store.wrapHandleResponse( new CatBestAnswers );
|
||||
|
||||
eoParallelPopLoopEval< EOT > popEval( assign, eo::mpi::DEFAULT_MASTER, &store );
|
||||
|
||||
//eoParallelPopLoopEval< EOT > popEval( assign, eo::mpi::DEFAULT_MASTER, eval, 5 );
|
||||
|
||||
eo::log << eo::quiet << "Before first evaluation." << std::endl;
|
||||
popEval( pop, pop );
|
||||
eo::log << eo::quiet << "After first evaluation." << std::endl;
|
||||
|
||||
pop = eoPop< EOT >( popSize, init );
|
||||
popEval( pop, pop );
|
||||
eo::log << eo::quiet << "After second evaluation." << std::endl;
|
||||
|
||||
eo::log << eo::quiet << "DONE!" << std::endl;
|
||||
} else
|
||||
{
|
||||
eoPop< EOT > pop; // the population doesn't have to be initialized, as it is not used by workers.
|
||||
eoParallelPopLoopEval< EOT > popEval( assign, eo::mpi::DEFAULT_MASTER, eval );
|
||||
popEval( pop, pop );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
196
eo/test/mpi/t-mpi-multipleRoles.cpp
Normal file
196
eo/test/mpi/t-mpi-multipleRoles.cpp
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file shows an example of how to make a hierarchy between nodes, when using a parallel apply. In this basic
|
||||
* test, the master delegates the charge of finding workers to 2 "sub" masters, which then send part of the table to
|
||||
* their workers.
|
||||
*
|
||||
* It's convenient to establish a role map, so as to clearly identify every role:
|
||||
* - The node 0 is the general master, that delegates the job. It sends the table to the 2 submasters, and waits for the
|
||||
* results.
|
||||
* - Nodes 1 and 2 are the worker of the first job: the delegates. They receive the elements of the table and
|
||||
* retransmit them to the subworkers. They play the roles of worker in the delegating job, and master in the plus one
|
||||
* job.
|
||||
* - Following nodes (3 to 6) are workers of the plus one job. They do the real job. Nodes 3 and 5 are attached to
|
||||
* submaster 1, 4 and 6 to submaster 2.
|
||||
*
|
||||
* This test requires exactly 7 hosts. If the size is bigger, an exception will be thrown at the beginning.
|
||||
**/
|
||||
|
||||
# include <mpi/eoMpi.h>
|
||||
# include <mpi/eoParallelApply.h>
|
||||
# include <mpi/eoTerminateJob.h>
|
||||
|
||||
# include "t-mpi-common.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include <vector>
|
||||
using namespace std;
|
||||
|
||||
using namespace eo::mpi;
|
||||
|
||||
/*
|
||||
* This class allows the user to easily serialize a vector of elements which implement eoserial::Persistent too.
|
||||
*
|
||||
* T is the type of the contained element, which must implement eoserial::Persistent too.
|
||||
*
|
||||
* Here, it contains SerializableBase<int>, which is a serializable integer that can be used as an integer.
|
||||
*/
|
||||
template< class T >
|
||||
struct SerializableVector : public std::vector<T>, public eoserial::Persistent
|
||||
{
|
||||
public:
|
||||
|
||||
void unpack( const eoserial::Object* obj )
|
||||
{
|
||||
this->clear();
|
||||
eoserial::Array* vector = static_cast<eoserial::Array*>( obj->find("vector")->second );
|
||||
vector->deserialize< std::vector<T>, eoserial::Array::UnpackObjectAlgorithm >( *this );
|
||||
}
|
||||
|
||||
eoserial::Object* pack( void ) const
|
||||
{
|
||||
eoserial::Object* obj = new eoserial::Object;
|
||||
obj->add("vector", eoserial::makeArray< std::vector<T>, eoserial::SerializablePushAlgorithm >( *this ) );
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
|
||||
// The real job to execute, for the subworkers: add one to each element of a table.
|
||||
struct SubWork: public eoUF< SerializableBase<int>&, void >
|
||||
{
|
||||
void operator() ( SerializableBase<int> & x )
|
||||
{
|
||||
cout << "Subwork phase." << endl;
|
||||
++x;
|
||||
}
|
||||
};
|
||||
|
||||
// Function called by both subworkers and delegates.
|
||||
// v is the vector to process, rank is the MPI rank of the sub master
|
||||
void subtask( vector< SerializableBase<int> >& v, int rank )
|
||||
{
|
||||
// Attach workers according to nodes.
|
||||
// Submaster with rank 1 will have ranks 3 and 5 as subworkers.
|
||||
// Submaster with rank 2 will have ranks 4 and 6 as subworkers.
|
||||
vector<int> workers;
|
||||
workers.push_back( rank + 2 );
|
||||
workers.push_back( rank + 4 );
|
||||
DynamicAssignmentAlgorithm algo( workers );
|
||||
SubWork sw;
|
||||
|
||||
// Launch the job!
|
||||
ParallelApplyStore< SerializableBase<int> > store( sw, rank );
|
||||
store.data( v );
|
||||
ParallelApply< SerializableBase<int> > job( algo, rank, store );
|
||||
job.run();
|
||||
EmptyJob stop( algo, rank );
|
||||
}
|
||||
|
||||
// Functor applied by submasters. Wait for the subworkers responses and then add some random processing (here, multiply
|
||||
// each result by two).
|
||||
// Note that this work receives a vector of integers as an entry, while subworkers task's operator receives a simple
|
||||
// integer.
|
||||
struct Work: public eoUF< SerializableVector< SerializableBase<int> >&, void >
|
||||
{
|
||||
void operator() ( SerializableVector< SerializableBase<int> >& v )
|
||||
{
|
||||
cout << "Work phase..." << endl;
|
||||
subtask( v, Node::comm().rank() );
|
||||
for( unsigned i = 0; i < v.size(); ++i )
|
||||
{
|
||||
v[i] *= 2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// eo::log << eo::setlevel( eo::debug );
|
||||
Node::init( argc, argv );
|
||||
if( Node::comm().size() != 7 ) {
|
||||
throw std::runtime_error("World size should be 7.");
|
||||
}
|
||||
|
||||
SerializableVector< SerializableBase<int> > v;
|
||||
|
||||
v.push_back(1);
|
||||
v.push_back(3);
|
||||
v.push_back(3);
|
||||
v.push_back(7);
|
||||
v.push_back(42);
|
||||
|
||||
// As submasters' operator receives a vector<int> as an input, and ParallelApply takes a vector of
|
||||
// operator's input as an input, we have to deal with a vector of vector of integers for the master task.
|
||||
vector< SerializableVector< SerializableBase<int> > > metaV;
|
||||
// Here, we send twice the same vector. We could also have splitted the first vector into two vectors, one
|
||||
// containing the beginning and another one containing the end.
|
||||
metaV.push_back( v );
|
||||
metaV.push_back( v );
|
||||
|
||||
// Assigning roles is done by comparing MPI ranks.
|
||||
switch( Node::comm().rank() )
|
||||
{
|
||||
// Nodes from 0 to 2 are implicated into the delegating task.
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
{
|
||||
Work w;
|
||||
DynamicAssignmentAlgorithm algo( 1, 2 );
|
||||
ParallelApplyStore< SerializableVector< SerializableBase<int> > > store( w, 0 );
|
||||
store.data( metaV );
|
||||
ParallelApply< SerializableVector< SerializableBase<int> > > job( algo, 0, store );
|
||||
job.run();
|
||||
if( job.isMaster() )
|
||||
{
|
||||
EmptyJob stop( algo, 0 );
|
||||
v = metaV[0];
|
||||
cout << "Results : " << endl;
|
||||
for(unsigned i = 0; i < v.size(); ++i)
|
||||
{
|
||||
cout << v[i] << ' ';
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Other nodes are implicated into the subwork task.
|
||||
default:
|
||||
{
|
||||
// all the other nodes are sub workers
|
||||
int rank = Node::comm().rank();
|
||||
if ( rank == 3 or rank == 5 )
|
||||
{
|
||||
subtask( v, 1 );
|
||||
} else {
|
||||
subtask( v, 2 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
169
eo/test/mpi/t-mpi-multistart.cpp
Normal file
169
eo/test/mpi/t-mpi-multistart.cpp
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
# include <mpi/eoMultiStart.h>
|
||||
using namespace eo::mpi;
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <eo>
|
||||
#include <es.h>
|
||||
|
||||
/*
|
||||
* This file is based on the tutorial lesson 1. We'll consider that you know all the EO
|
||||
* related parts of the algorithm and we'll focus our attention on parallelization.
|
||||
*
|
||||
* This file shows an example of multistart applied to a eoSGA (simple genetic
|
||||
* algorithm). As individuals need to be serialized, we implement a class inheriting
|
||||
* from eoReal (which is the base individual), so as to manipulate individuals as they
|
||||
* were eoReal AND serialize them.
|
||||
*
|
||||
* The main function shows how to launch a multistart job, with default functors. If you
|
||||
* don't know which functors to use, these ones should fit the most of your purposes.
|
||||
*/
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* eoReal is a vector of double: we just have to serializes the value and the fitness.
|
||||
*/
|
||||
class SerializableEOReal: public eoReal<double>, public eoserial::Persistent
|
||||
{
|
||||
public:
|
||||
|
||||
SerializableEOReal(unsigned size = 0, double value = 0.0) :
|
||||
eoReal<double>(size, value)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
void unpack( const eoserial::Object* obj )
|
||||
{
|
||||
this->clear();
|
||||
eoserial::unpackArray
|
||||
< std::vector<double>, eoserial::Array::UnpackAlgorithm >
|
||||
( *obj, "vector", *this );
|
||||
|
||||
bool invalidFitness;
|
||||
eoserial::unpack( *obj, "invalid_fitness", invalidFitness );
|
||||
if( invalidFitness )
|
||||
{
|
||||
this->invalidate();
|
||||
} else
|
||||
{
|
||||
double f;
|
||||
eoserial::unpack( *obj, "fitness", f );
|
||||
this->fitness( f );
|
||||
}
|
||||
}
|
||||
|
||||
eoserial::Object* pack( void ) const
|
||||
{
|
||||
eoserial::Object* obj = new eoserial::Object;
|
||||
obj->add( "vector", eoserial::makeArray< std::vector<double>, eoserial::MakeAlgorithm >( *this ) );
|
||||
|
||||
bool invalidFitness = this->invalid();
|
||||
obj->add( "invalid_fitness", eoserial::make( invalidFitness ) );
|
||||
if( !invalidFitness )
|
||||
{
|
||||
obj->add( "fitness", eoserial::make( this->fitness() ) );
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
|
||||
// REPRESENTATION
|
||||
//-----------------------------------------------------------------------------
|
||||
// define your individuals
|
||||
typedef SerializableEOReal Indi;
|
||||
|
||||
// EVAL
|
||||
//-----------------------------------------------------------------------------
|
||||
// a simple fitness function that computes the euclidian norm of a real vector
|
||||
// @param _indi A real-valued individual
|
||||
|
||||
double real_value(const Indi & _indi)
|
||||
{
|
||||
double sum = 0;
|
||||
for (unsigned i = 0; i < _indi.size(); i++)
|
||||
sum += _indi[i]*_indi[i];
|
||||
return (-sum); // maximizing only
|
||||
}
|
||||
|
||||
/************************** PARALLELIZATION JOB *******************************/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Node::init( argc, argv );
|
||||
|
||||
// PARAMETRES
|
||||
// all parameters are hard-coded!
|
||||
const unsigned int SEED = 133742; // seed for random number generator
|
||||
const unsigned int VEC_SIZE = 8; // Number of object variables in genotypes
|
||||
const unsigned int POP_SIZE = 100; // Size of population
|
||||
const unsigned int T_SIZE = 3; // size for tournament selection
|
||||
const unsigned int MAX_GEN = 100; // Maximum number of generation before STOP
|
||||
const float CROSS_RATE = 0.8; // Crossover rate
|
||||
const double EPSILON = 0.01; // range for real uniform mutation
|
||||
const float MUT_RATE = 0.5; // mutation rate
|
||||
|
||||
eoEvalFuncPtr<Indi> eval( real_value );
|
||||
eoPop<Indi> pop;
|
||||
eoUniformGenerator< double > generator;
|
||||
eoInitFixedLength< Indi > init( VEC_SIZE, generator );
|
||||
pop = eoPop<Indi>( POP_SIZE, init );
|
||||
|
||||
eoDetTournamentSelect<Indi> select(T_SIZE);
|
||||
eoSegmentCrossover<Indi> xover;
|
||||
eoUniformMutation<Indi> mutation(EPSILON);
|
||||
|
||||
eoGenContinue<Indi> continuator(MAX_GEN);
|
||||
/* Does work too with a steady fit continuator. */
|
||||
// eoSteadyFitContinue< Indi > continuator( 10, 50 );
|
||||
|
||||
eoSGA<Indi> gga(select, xover, CROSS_RATE, mutation, MUT_RATE,
|
||||
eval, continuator);
|
||||
|
||||
/* How to assign tasks, which are starts? */
|
||||
DynamicAssignmentAlgorithm assignmentAlgo;
|
||||
/* Before a worker starts its algorithm, how does it reinits the population?
|
||||
* There are a few default usable functors, defined in eoMultiStart.h.
|
||||
*
|
||||
* This one (ReuseSamePopEA) doesn't modify the population after a start, so
|
||||
* the same population is reevaluated on each multistart: the solution tend
|
||||
* to get better and better.
|
||||
*/
|
||||
ReuseSamePopEA< Indi > resetAlgo( continuator, pop, eval );
|
||||
/**
|
||||
* How to send seeds to the workers, at the beginning of the parallel job?
|
||||
* This functors indicates that seeds should be random values.
|
||||
*/
|
||||
GetRandomSeeds< Indi > getSeeds( SEED );
|
||||
|
||||
// Builds the store
|
||||
MultiStartStore< Indi > store(
|
||||
gga,
|
||||
DEFAULT_MASTER,
|
||||
resetAlgo,
|
||||
getSeeds);
|
||||
|
||||
// Creates the multistart job and runs it.
|
||||
// The last argument indicates that we want to launch 5 runs.
|
||||
MultiStart< Indi > msjob( assignmentAlgo, DEFAULT_MASTER, store, 5 );
|
||||
msjob.run();
|
||||
|
||||
if( msjob.isMaster() )
|
||||
{
|
||||
msjob.best_individuals().sort();
|
||||
std::cout << "Global best individual has fitness " << msjob.best_individuals().best_element().fitness() << std::endl;
|
||||
}
|
||||
|
||||
MultiStart< Indi > msjob10( assignmentAlgo, DEFAULT_MASTER, store, 10 );
|
||||
msjob10.run();
|
||||
|
||||
if( msjob10.isMaster() )
|
||||
{
|
||||
msjob10.best_individuals().sort();
|
||||
std::cout << "Global best individual has fitness " << msjob10.best_individuals().best_element().fitness() << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
220
eo/test/mpi/t-mpi-parallelApply.cpp
Normal file
220
eo/test/mpi/t-mpi-parallelApply.cpp
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file shows an example of use of parallel apply, in the following context: each element of a table is
|
||||
* incremented... in a parallel fashion. While this operation is very easy to perform even on a single host, it's just
|
||||
* an example for parallel apply use.
|
||||
*
|
||||
* The table of integers has to be serialized before it's sent. The wrapper object SerializableBase allows to serialize
|
||||
* any type and manipulate it like this type: SerializableBase<int> can be exactly be used as an integer.
|
||||
*
|
||||
* Besides, this is also a test for assignment (scheduling) algorithms, in different cases. The test succeeds if and
|
||||
* only if the program terminates without any segfault ; otherwise, there could be a deadlock which prevents the end or
|
||||
* a segfault at any time.
|
||||
*
|
||||
* One important thing is to instanciate an EmptyJob after having launched a ParallelApplyJob, so as the workers to be
|
||||
* aware that the job is done (as it's a MultiJob).
|
||||
*
|
||||
* This test needs at least 3 processes to be launched. Under this size, it will directly throw an exception, at the
|
||||
* beginning;
|
||||
*/
|
||||
|
||||
# include <mpi/eoMpi.h>
|
||||
# include <mpi/eoParallelApply.h>
|
||||
# include <mpi/eoTerminateJob.h>
|
||||
|
||||
# include "t-mpi-common.h"
|
||||
|
||||
# include <iostream>
|
||||
# include <cstdlib>
|
||||
|
||||
# include <vector>
|
||||
using namespace std;
|
||||
|
||||
using namespace eo::mpi;
|
||||
|
||||
/*
|
||||
* The function to be called on each element of the table: just increment the value.
|
||||
*/
|
||||
struct plusOne : public eoUF< SerializableBase<int>&, void >
|
||||
{
|
||||
void operator() ( SerializableBase<int> & x )
|
||||
{
|
||||
++x; // implicit conversion of SerializableBase<int> in the integer it contains
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal structure representating a test.
|
||||
*/
|
||||
struct Test
|
||||
{
|
||||
AssignmentAlgorithm * assign; // used assignment algorithm for this test.
|
||||
string description; // textual description of the test
|
||||
int requiredNodesNumber; // number of required nodes. NB : chosen nodes ranks must be sequential
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// eo::log << eo::setlevel( eo::debug ); // if you like tty full of rainbows, decomment this line and comment the following one.
|
||||
eo::log << eo::setlevel( eo::quiet );
|
||||
|
||||
bool launchOnlyOne = false ; // Set this to true if you wanna launch only the first test.
|
||||
|
||||
Node::init( argc, argv );
|
||||
|
||||
// Initializes a vector with random values.
|
||||
srand( time(0) );
|
||||
vector< SerializableBase<int> > v;
|
||||
for( int i = 0; i < 1000; ++i )
|
||||
{
|
||||
v.push_back( rand() );
|
||||
}
|
||||
|
||||
// We need to be sure the values are correctly incremented between each test. So as to check this, we save the
|
||||
// original vector into a variable originalV, and put an offset variable to 0. After each test, the offset is
|
||||
// incremented and we can compare the returned value of each element to the value of each element in originalV +
|
||||
// offset. If the two values are different, there has been a problem.
|
||||
int offset = 0;
|
||||
vector< SerializableBase<int> > originalV = v;
|
||||
|
||||
// Instanciates the functor to apply on each element
|
||||
plusOne plusOneInstance;
|
||||
|
||||
vector< Test > tests;
|
||||
|
||||
const int ALL = Node::comm().size();
|
||||
if( ALL < 3 ) {
|
||||
throw std::runtime_error("Needs at least 3 processes to be launched!");
|
||||
}
|
||||
|
||||
// Tests are auto described thanks to member "description"
|
||||
Test tIntervalStatic;
|
||||
tIntervalStatic.assign = new StaticAssignmentAlgorithm( 1, REST_OF_THE_WORLD, v.size() );
|
||||
tIntervalStatic.description = "Correct static assignment with interval."; // workers have ranks from 1 to size - 1
|
||||
tIntervalStatic.requiredNodesNumber = ALL;
|
||||
tests.push_back( tIntervalStatic );
|
||||
|
||||
if( !launchOnlyOne )
|
||||
{
|
||||
Test tWorldStatic;
|
||||
tWorldStatic.assign = new StaticAssignmentAlgorithm( v.size() );
|
||||
tWorldStatic.description = "Correct static assignment with whole world as workers.";
|
||||
tWorldStatic.requiredNodesNumber = ALL;
|
||||
tests.push_back( tWorldStatic );
|
||||
|
||||
Test tStaticOverload;
|
||||
tStaticOverload.assign = new StaticAssignmentAlgorithm( v.size()+100 );
|
||||
tStaticOverload.description = "Static assignment with too many runs.";
|
||||
tStaticOverload.requiredNodesNumber = ALL;
|
||||
tests.push_back( tStaticOverload );
|
||||
|
||||
Test tUniqueStatic;
|
||||
tUniqueStatic.assign = new StaticAssignmentAlgorithm( 1, v.size() );
|
||||
tUniqueStatic.description = "Correct static assignment with unique worker.";
|
||||
tUniqueStatic.requiredNodesNumber = 2;
|
||||
tests.push_back( tUniqueStatic );
|
||||
|
||||
Test tVectorStatic;
|
||||
vector<int> workers;
|
||||
workers.push_back( 1 );
|
||||
workers.push_back( 2 );
|
||||
tVectorStatic.assign = new StaticAssignmentAlgorithm( workers, v.size() );
|
||||
tVectorStatic.description = "Correct static assignment with precise workers specified.";
|
||||
tVectorStatic.requiredNodesNumber = 3;
|
||||
tests.push_back( tVectorStatic );
|
||||
|
||||
Test tIntervalDynamic;
|
||||
tIntervalDynamic.assign = new DynamicAssignmentAlgorithm( 1, REST_OF_THE_WORLD );
|
||||
tIntervalDynamic.description = "Dynamic assignment with interval.";
|
||||
tIntervalDynamic.requiredNodesNumber = ALL;
|
||||
tests.push_back( tIntervalDynamic );
|
||||
|
||||
Test tUniqueDynamic;
|
||||
tUniqueDynamic.assign = new DynamicAssignmentAlgorithm( 1 );
|
||||
tUniqueDynamic.description = "Dynamic assignment with unique worker.";
|
||||
tUniqueDynamic.requiredNodesNumber = 2;
|
||||
tests.push_back( tUniqueDynamic );
|
||||
|
||||
Test tVectorDynamic;
|
||||
tVectorDynamic.assign = new DynamicAssignmentAlgorithm( workers );
|
||||
tVectorDynamic.description = "Dynamic assignment with precise workers specified.";
|
||||
tVectorDynamic.requiredNodesNumber = tVectorStatic.requiredNodesNumber;
|
||||
tests.push_back( tVectorDynamic );
|
||||
|
||||
Test tWorldDynamic;
|
||||
tWorldDynamic.assign = new DynamicAssignmentAlgorithm;
|
||||
tWorldDynamic.description = "Dynamic assignment with whole world as workers.";
|
||||
tWorldDynamic.requiredNodesNumber = ALL;
|
||||
tests.push_back( tWorldDynamic );
|
||||
}
|
||||
|
||||
for( unsigned int i = 0; i < tests.size(); ++i )
|
||||
{
|
||||
// Instanciates a store with the functor, the master rank and size of packet (see ParallelApplyStore doc).
|
||||
ParallelApplyStore< SerializableBase<int> > store( plusOneInstance, eo::mpi::DEFAULT_MASTER, 3 );
|
||||
// Updates the contained data
|
||||
store.data( v );
|
||||
// Creates the job with the assignment algorithm, the master rank and the store
|
||||
ParallelApply< SerializableBase<int> > job( *(tests[i].assign), eo::mpi::DEFAULT_MASTER, store );
|
||||
|
||||
// Only master writes information
|
||||
if( job.isMaster() )
|
||||
{
|
||||
cout << "Test : " << tests[i].description << endl;
|
||||
}
|
||||
|
||||
// Workers whose rank is inferior to required nodes number have to run the test, the other haven't anything to
|
||||
// do.
|
||||
if( Node::comm().rank() < tests[i].requiredNodesNumber )
|
||||
{
|
||||
job.run();
|
||||
}
|
||||
|
||||
// After the job run, the master checks the result with offset and originalV
|
||||
if( job.isMaster() )
|
||||
{
|
||||
// This job has to be instanciated, not launched, so as to tell the workers they're done with the parallel
|
||||
// job.
|
||||
EmptyJob stop( *(tests[i].assign), eo::mpi::DEFAULT_MASTER );
|
||||
++offset;
|
||||
for(unsigned i = 0; i < v.size(); ++i)
|
||||
{
|
||||
cout << v[i] << ' ';
|
||||
if( originalV[i] + offset != v[i] )
|
||||
{
|
||||
cout << " <-- ERROR at this point." << endl;
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
// MPI synchronization (all the processes wait to be here).
|
||||
Node::comm().barrier();
|
||||
|
||||
delete tests[i].assign;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
133
eo/test/mpi/t-mpi-wrapper.cpp
Normal file
133
eo/test/mpi/t-mpi-wrapper.cpp
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
(c) Thales group, 2012
|
||||
|
||||
This library 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;
|
||||
version 2 of the License.
|
||||
|
||||
This library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Benjamin Bouvier <benjamin.bouvier@gmail.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file shows an example of how to wrap a handler of a job store. Here, the wrapped handler is the "IsFinished"
|
||||
* one. The only function that has been added is that the wrapper prints a message on standard output, indicating what
|
||||
* the wrapped function returns as a result.
|
||||
*
|
||||
* This test is performed on a parallel apply job, the same as in parallelApply. The main difference is when
|
||||
* instanciating the store.
|
||||
*/
|
||||
|
||||
# include <mpi/eoMpi.h>
|
||||
# include <mpi/eoParallelApply.h>
|
||||
# include <mpi/eoTerminateJob.h>
|
||||
|
||||
# include "t-mpi-common.h"
|
||||
|
||||
# include <iostream>
|
||||
# include <cstdlib>
|
||||
|
||||
# include <vector>
|
||||
using namespace std;
|
||||
|
||||
using namespace eo::mpi;
|
||||
|
||||
// Job functor.
|
||||
struct plusOne : public eoUF< SerializableBase<int>&, void >
|
||||
{
|
||||
void operator() ( SerializableBase<int>& x )
|
||||
{
|
||||
++x;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Shows the wrapped result of IsFinished, prints a message and returns the wrapped value.
|
||||
* times is an integer counting how many time the wrapper (hence the wrapped too) has been called.
|
||||
*/
|
||||
template< class EOT >
|
||||
struct ShowWrappedResult : public IsFinishedParallelApply<EOT>
|
||||
{
|
||||
using IsFinishedParallelApply<EOT>::_wrapped;
|
||||
|
||||
ShowWrappedResult ( IsFinishedParallelApply<EOT> * w = 0 ) : IsFinishedParallelApply<EOT>( w ), times( 0 )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
bool operator()()
|
||||
{
|
||||
bool wrappedValue = _wrapped->operator()(); // (*_wrapped)();
|
||||
cout << times << ") Wrapped function would say that it is " << ( wrappedValue ? "":"not ") << "finished" << std::endl;
|
||||
++times;
|
||||
return wrappedValue;
|
||||
}
|
||||
|
||||
private:
|
||||
int times;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// eo::log << eo::setlevel( eo::debug );
|
||||
eo::log << eo::setlevel( eo::quiet );
|
||||
|
||||
Node::init( argc, argv );
|
||||
|
||||
srand( time(0) );
|
||||
vector< SerializableBase<int> > v;
|
||||
for( int i = 0; i < 1000; ++i )
|
||||
{
|
||||
v.push_back( rand() );
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
vector< SerializableBase<int> > originalV = v;
|
||||
|
||||
plusOne plusOneInstance;
|
||||
|
||||
StaticAssignmentAlgorithm assign( v.size() );
|
||||
|
||||
ParallelApplyStore< SerializableBase<int> > store( plusOneInstance, eo::mpi::DEFAULT_MASTER, 1 );
|
||||
store.data( v );
|
||||
// This is the only thing which changes: we wrap the IsFinished function.
|
||||
// According to RAII, we'll delete the invokated wrapper at the end of the main ; the store won't delete it
|
||||
// automatically.
|
||||
ShowWrappedResult< SerializableBase<int> > wrapper;
|
||||
store.wrapIsFinished( &wrapper );
|
||||
|
||||
ParallelApply< SerializableBase<int> > job( assign, eo::mpi::DEFAULT_MASTER, store );
|
||||
// Equivalent to:
|
||||
// Job< ParallelApplyData<int> > job( assign, 0, store );
|
||||
job.run();
|
||||
EmptyJob stop( assign, eo::mpi::DEFAULT_MASTER );
|
||||
|
||||
if( job.isMaster() )
|
||||
{
|
||||
++offset;
|
||||
for(unsigned i = 0; i < v.size(); ++i)
|
||||
{
|
||||
cout << v[i] << ' ';
|
||||
if( originalV[i] + offset != v[i] )
|
||||
{
|
||||
cout << " <-- ERROR at this point." << endl;
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
104
eo/test/mpi/template-job.cpp
Normal file
104
eo/test/mpi/template-job.cpp
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# include <mpi/eoMpi.h>
|
||||
|
||||
using namespace eo::mpi;
|
||||
|
||||
/*
|
||||
* This file is a template for a new eo::mpi::Job. You have everything that should be necessary to implement a new
|
||||
* parallelized algorithm.
|
||||
*
|
||||
* Replace __TEMPLATE__ by the name of your algorithm (for instance: MultiStart, ParallelApply, etc.).
|
||||
*/
|
||||
|
||||
template< class EOT >
|
||||
struct __TEMPLATE__Data
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class SendTask__TEMPLATE__ : public SendTaskFunction< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
using SendTaskFunction< __TEMPLATE__Data< EOT > >::_data;
|
||||
|
||||
void operator()( int wrkRank )
|
||||
{
|
||||
// TODO implement me
|
||||
}
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class HandleResponse__TEMPLATE__ : public HandleResponseFunction< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
using HandleResponseFunction< __TEMPLATE__Data< EOT > >::_data;
|
||||
|
||||
void operator()( int wrkRank )
|
||||
{
|
||||
// TODO implement me
|
||||
}
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class ProcessTask__TEMPLATE__ : public ProcessTaskFunction< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
using ProcessTaskFunction< __TEMPLATE__Data<EOT> >::_data;
|
||||
|
||||
void operator()()
|
||||
{
|
||||
// TODO implement me
|
||||
}
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class IsFinished__TEMPLATE__ : public IsFinishedFunction< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
using IsFinishedFunction< __TEMPLATE__Data< EOT > >::_data;
|
||||
|
||||
bool operator()()
|
||||
{
|
||||
// TODO implement me
|
||||
}
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class __TEMPLATE__Store : public JobStore< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
__TEMPLATE__Data<EOT>* data()
|
||||
{
|
||||
// TODO implement me
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template< class EOT >
|
||||
class __TEMPLATE__ : public MultiJob< __TEMPLATE__Data< EOT > >
|
||||
{
|
||||
public:
|
||||
|
||||
__TEMPLATE__( AssignmentAlgorithm & algo,
|
||||
int masterRank,
|
||||
__TEMPLATE__Store< EOT > & store ) :
|
||||
MultiJob< __TEMPLATE__Data< EOT > >( algo, masterRank, store )
|
||||
{
|
||||
// TODO implement me
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Node::init( argc, argv );
|
||||
|
||||
DynamicAssignmentAlgorithm assignmentAlgo;
|
||||
__TEMPLATE__Store<int> store;
|
||||
__TEMPLATE__<int> job( assignmentAlgo, DEFAULT_MASTER, store );
|
||||
}
|
||||
*/
|
||||
|
|
@ -69,7 +69,8 @@ int main()
|
|||
// Terminators
|
||||
eoGenContinue<Chrom> continuator1(10);
|
||||
eoFitContinue<Chrom> continuator2(CHROM_SIZE);
|
||||
eoCombinedContinue<Chrom> continuator(continuator1, continuator2);
|
||||
eoCombinedContinue<Chrom> continuator(continuator1);
|
||||
continuator.add( continuator2 );
|
||||
eoCheckPoint<Chrom> checkpoint(continuator);
|
||||
eoStdoutMonitor monitor;
|
||||
checkpoint.add(monitor);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,8 @@ int main()
|
|||
// Terminators
|
||||
eoGenContinue<Chrom> continuator1(10);
|
||||
eoFitContinue<Chrom> continuator2(CHROM_SIZE);
|
||||
eoCombinedContinue<Chrom> continuator(continuator1, continuator2);
|
||||
eoCombinedContinue<Chrom> continuator(continuator1);
|
||||
continuator.add( continuator2);
|
||||
eoCheckPoint<Chrom> checkpoint(continuator);
|
||||
eoStdoutMonitor monitor;
|
||||
checkpoint.add(monitor);
|
||||
|
|
|
|||
|
|
@ -72,7 +72,8 @@ int main()
|
|||
// Terminators
|
||||
eoGenContinue<Chrom> continuator1(10);
|
||||
eoFitContinue<Chrom> continuator2(CHROM_SIZE);
|
||||
eoCombinedContinue<Chrom> continuator(continuator1, continuator2);
|
||||
eoCombinedContinue<Chrom> continuator(continuator1);
|
||||
continuator.add(continuator2);
|
||||
eoCheckPoint<Chrom> checkpoint(continuator);
|
||||
eoStdoutMonitor monitor;
|
||||
checkpoint.add(monitor);
|
||||
|
|
|
|||
78
eo/test/t-eoEvalKeepBest.cpp
Normal file
78
eo/test/t-eoEvalKeepBest.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <es/make_real.h>
|
||||
#include <apply.h>
|
||||
#include <eoEvalKeepBest.h>
|
||||
#include "real_value.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
typedef eoReal<eoMinimizingFitness> EOT;
|
||||
|
||||
eoParser parser(argc, argv); // for user-parameter reading
|
||||
eoState state; // keeps all things allocated
|
||||
|
||||
|
||||
/*********************************************
|
||||
* problem or representation dependent stuff *
|
||||
*********************************************/
|
||||
|
||||
// The evaluation fn - encapsulated into an eval counter for output
|
||||
eoEvalFuncPtr<EOT, double, const std::vector<double>&>
|
||||
main_eval( real_value ); // use a function defined in real_value.h
|
||||
|
||||
// wrap the evaluation function in a call counter
|
||||
eoEvalFuncCounter<EOT> eval_counter(main_eval);
|
||||
|
||||
// the genotype - through a genotype initializer
|
||||
eoRealInitBounded<EOT>& init = make_genotype(parser, state, EOT());
|
||||
|
||||
// Build the variation operator (any seq/prop construct)
|
||||
eoGenOp<EOT>& op = make_op(parser, state, init);
|
||||
|
||||
|
||||
/*********************************************
|
||||
* Now the representation-independent things *
|
||||
*********************************************/
|
||||
|
||||
|
||||
// initialize the population - and evaluate
|
||||
// yes, this is representation indepedent once you have an eoInit
|
||||
eoPop<EOT>& pop = make_pop(parser, state, init);
|
||||
|
||||
// stopping criteria
|
||||
eoContinue<EOT> & term = make_continue(parser, state, eval_counter);
|
||||
|
||||
// things that are called at each generation
|
||||
eoCheckPoint<EOT> & checkpoint = make_checkpoint(parser, state, eval_counter, term);
|
||||
|
||||
// wrap the evaluator in another one that will keep the best individual
|
||||
// evaluated so far
|
||||
eoEvalKeepBest<EOT> eval_keep( eval_counter );
|
||||
|
||||
// algorithm
|
||||
eoAlgo<EOT>& ea = make_algo_scalar(parser, state, eval_keep, checkpoint, op);
|
||||
|
||||
|
||||
/***************************************
|
||||
* Now, call functors and DO something *
|
||||
***************************************/
|
||||
|
||||
// to be called AFTER all parameters have been read!
|
||||
make_help(parser);
|
||||
|
||||
// evaluate intial population AFTER help and status in case it takes time
|
||||
apply<EOT>(eval_keep, pop);
|
||||
|
||||
std::clog << "Best individual after initialization and " << eval_counter.value() << " evaluations" << std::endl;
|
||||
std::cout << eval_keep.best_element() << std::endl;
|
||||
|
||||
ea(pop); // run the ea
|
||||
|
||||
std::cout << "Best individual after search and " << eval_counter.value() << " evaluations" << std::endl;
|
||||
// you can also call value(), because it is an eoParam
|
||||
std::cout << eval_keep.value() << std::endl;
|
||||
}
|
||||
98
eo/test/t-eoInitVariableLength.cpp
Normal file
98
eo/test/t-eoInitVariableLength.cpp
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <eo>
|
||||
|
||||
// An adhoc atom type of our own
|
||||
class Quad : public std::vector<int>
|
||||
{
|
||||
public:
|
||||
// Just four times zero
|
||||
Quad() : std::vector<int>(4,0) {}
|
||||
};
|
||||
|
||||
// EO somewhat forces you to implement a way to read/print your atom type
|
||||
// You can either inherit from eoPrintable and overload readFrom/printOn
|
||||
// or, just like here, directly overload stream operators.
|
||||
|
||||
// read
|
||||
std::istream& operator>>( std::istream& is, Quad& q )
|
||||
{
|
||||
for( unsigned int i=0, n=4; i<n; ++i) {
|
||||
// use default int stream input
|
||||
is >> q[i];
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
// print
|
||||
std::ostream& operator<<( std::ostream& os, const Quad& q )
|
||||
{
|
||||
os << q[0];
|
||||
for( unsigned int i=1, n=4; i<n; ++i) {
|
||||
os << " " << q[i];
|
||||
}
|
||||
os << " ";
|
||||
return os;
|
||||
}
|
||||
|
||||
// An init for the atoms
|
||||
// Note that this mask the template passed to the eoInit
|
||||
class QuadInit : public eoInit<Quad>
|
||||
{
|
||||
public:
|
||||
// this is the API: an init modify the solution
|
||||
void operator()( Quad& q ) {
|
||||
for( unsigned int i=0, n=4; i<n; ++i) {
|
||||
// rng is the random number generator of EO
|
||||
q[i] = rng.random(10);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// The solution/individual type.
|
||||
// Just a proxy to an eoVector of atoms,
|
||||
// with a fitness as double.
|
||||
class QuadVec : public eoVector<double,Quad>
|
||||
{};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned int vec_size_min = 1;
|
||||
unsigned int vec_size_max = 10;
|
||||
unsigned int pop_size = 10;
|
||||
|
||||
// Fix a seed for the random generator,
|
||||
// thus, the results are predictable.
|
||||
// Set it to zero if you want pseudo-random numbers
|
||||
// that changes at each calls.
|
||||
rng.reseed( 1 );
|
||||
|
||||
// The operator that produce a random vector of four values.
|
||||
QuadInit atom_init;
|
||||
|
||||
// The operator that produces a random vector of a (vector of four values).
|
||||
eoInitVariableLength<QuadVec> vec_init( vec_size_min, vec_size_max, atom_init );
|
||||
|
||||
// You can initialize a population of N individuals by passing an initializer to it.
|
||||
eoPop<QuadVec> pop( pop_size, vec_init );
|
||||
|
||||
// eoPop can be printed easily,
|
||||
// thanks to the overloadings above.
|
||||
std::cout << pop << std::endl;
|
||||
|
||||
// With a seed at 1, this should output:
|
||||
/*
|
||||
10
|
||||
INVALID 6 5 9 5 9 0 1 6 0 4 8 9 0 6 9 4 9 5 5 3 6 3 0 2 8
|
||||
INVALID 9 9 2 0 3 2 4 3 3 6 2 8 2 4 5 4 7 5 3 0 5 4 9 8 3 2 7 7 9 4 4 4 6 6 3 9 2
|
||||
INVALID 1 1 4 1 4
|
||||
INVALID 5 3 8 9 8 8 1 4 1 6 6 5 4 3 2 7 5 1 2 6 1
|
||||
INVALID 3 7 8 1 4 0 9 1 0 6 4 2 1
|
||||
INVALID 6 7 4 6 8 1 2 6 0 5 1 2 6 9 2 6 8 6 1 5 5 4 1 0 3
|
||||
INVALID 5 2 7 7 6 1 4 0 7 5 5 9 7 2 4 7 1 6 1 9 0
|
||||
INVALID 3 5 5 3 9 2 9 9 1 1 7 2 1
|
||||
INVALID 6 9 9 9 0 0 7 1 7 9 7 8 5 3 7 5 6 7 3 6 7 6 3 3 5
|
||||
INVALID 1 6 2 4 3
|
||||
*/
|
||||
}
|
||||
|
|
@ -139,7 +139,8 @@ void main_function()
|
|||
eoGenContinue<Chrom> continuator1(50);
|
||||
eoFitContinue<Chrom> continuator2(65535.f);
|
||||
|
||||
eoCombinedContinue<Chrom> continuator(continuator1, continuator2);
|
||||
eoCombinedContinue<Chrom> continuator(continuator1);
|
||||
continuator.add( continuator2);
|
||||
|
||||
eoCheckPoint<Chrom> checkpoint(continuator);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,63 +2,63 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/ga)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/utils)
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${EO_SRC_DIR}/src/ga)
|
||||
include_directories(${EO_SRC_DIR}/src/utils)
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries
|
||||
######################################################################################
|
||||
|
||||
IF(NOT WIN32 OR CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
ENDIF(NOT WIN32 OR CYGWIN)
|
||||
if(NOT WIN32 OR CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}/lib)
|
||||
endif(NOT WIN32 OR CYGWIN)
|
||||
|
||||
# especially for Visual Studio
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
ENDIF(WIN32 AND NOT CYGWIN)
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
endif(WIN32 AND NOT CYGWIN)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your targets
|
||||
######################################################################################
|
||||
|
||||
# no matter what is the OS, hopefully
|
||||
ADD_EXECUTABLE(FirstBitGA FirstBitGA.cpp)
|
||||
ADD_EXECUTABLE(FirstRealGA FirstRealGA.cpp)
|
||||
ADD_EXECUTABLE(exercise1.3 exercise1.3.cpp)
|
||||
add_executable(FirstBitGA FirstBitGA.cpp)
|
||||
add_executable(FirstRealGA FirstRealGA.cpp)
|
||||
add_executable(exercise1.3 exercise1.3.cpp)
|
||||
|
||||
ADD_DEPENDENCIES(FirstBitGA ga eo eoutils)
|
||||
ADD_DEPENDENCIES(FirstRealGA ga eo eoutils)
|
||||
ADD_DEPENDENCIES(exercise1.3 ga eo eoutils)
|
||||
add_dependencies(FirstBitGA ga eo eoutils)
|
||||
add_dependencies(FirstRealGA ga eo eoutils)
|
||||
add_dependencies(exercise1.3 ga eo eoutils)
|
||||
|
||||
######################################################################################
|
||||
### 4) Optionnal
|
||||
######################################################################################
|
||||
|
||||
SET(FIRSTBITGA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(FirstBitGA PROPERTIES VERSION "${FIRSTBITGA_VERSION}")
|
||||
set(FIRSTBITGA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(FirstBitGA PROPERTIES VERSION "${FIRSTBITGA_VERSION}")
|
||||
|
||||
SET(FIRSTREALGA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(FirstRealGA PROPERTIES VERSION "${FIRSTREALGA_VERSION}")
|
||||
set(FIRSTREALGA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(FirstRealGA PROPERTIES VERSION "${FIRSTREALGA_VERSION}")
|
||||
|
||||
SET(EXERCICE13_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(exercise1.3 PROPERTIES VERSION "${EXERCICE13_VERSION}")
|
||||
set(EXERCICE13_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(exercise1.3 PROPERTIES VERSION "${EXERCICE13_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
### 5) Link the librairies for the targets
|
||||
######################################################################################
|
||||
|
||||
TARGET_LINK_LIBRARIES(FirstBitGA ga eo eoutils)
|
||||
TARGET_LINK_LIBRARIES(FirstRealGA ga eo eoutils)
|
||||
TARGET_LINK_LIBRARIES(exercise1.3 ga eo eoutils)
|
||||
target_link_libraries(FirstBitGA ga eo eoutils)
|
||||
target_link_libraries(FirstRealGA ga eo eoutils)
|
||||
target_link_libraries(exercise1.3 ga eo eoutils)
|
||||
|
||||
######################################################################################
|
||||
### 6) Configure project installation paths
|
||||
######################################################################################
|
||||
|
||||
INSTALL(TARGETS FirstBitGA RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson1 COMPONENT examples)
|
||||
INSTALL(TARGETS FirstRealGA RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson1 COMPONENT examples)
|
||||
INSTALL(TARGETS exercise1.3 RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson1 COMPONENT examples)
|
||||
install(TARGETS FirstBitGA RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson1 COMPONENT examples)
|
||||
install(TARGETS FirstRealGA RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson1 COMPONENT examples)
|
||||
install(TARGETS exercise1.3 RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson1 COMPONENT examples)
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
|
|
@ -2,59 +2,59 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/ga)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/utils)
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${EO_SRC_DIR}/src/ga)
|
||||
include_directories(${EO_SRC_DIR}/src/utils)
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries
|
||||
######################################################################################
|
||||
|
||||
IF(NOT WIN32 OR CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
ENDIF(NOT WIN32 OR CYGWIN)
|
||||
if(NOT WIN32 OR CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}/lib)
|
||||
endif(NOT WIN32 OR CYGWIN)
|
||||
|
||||
# especially for Visual Studio
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
ENDIF(WIN32 AND NOT CYGWIN)
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
endif(WIN32 AND NOT CYGWIN)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your targets
|
||||
######################################################################################
|
||||
|
||||
# no matter what is the OS, hopefully
|
||||
ADD_EXECUTABLE(FirstBitEA FirstBitEA.cpp)
|
||||
ADD_EXECUTABLE(FirstRealEA FirstRealEA.cpp)
|
||||
ADD_EXECUTABLE(exercise2.3 exercise2.3.cpp)
|
||||
add_executable(FirstBitEA FirstBitEA.cpp)
|
||||
add_executable(FirstRealEA FirstRealEA.cpp)
|
||||
add_executable(exercise2.3 exercise2.3.cpp)
|
||||
|
||||
######################################################################################
|
||||
### 4) Optionnal
|
||||
######################################################################################
|
||||
|
||||
SET(FIRSTBITEA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(FirstBitEA PROPERTIES VERSION "${FIRSTBITEA_VERSION}")
|
||||
set(FIRSTBITEA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(FirstBitEA PROPERTIES VERSION "${FIRSTBITEA_VERSION}")
|
||||
|
||||
SET(FIRSTREALEA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(FirstRealEA PROPERTIES VERSION "${FIRSTREALEA_VERSION}")
|
||||
set(FIRSTREALEA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(FirstRealEA PROPERTIES VERSION "${FIRSTREALEA_VERSION}")
|
||||
|
||||
SET(EXERCICE23_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(exercise2.3 PROPERTIES VERSION "${EXERCICE23_VERSION}")
|
||||
set(EXERCICE23_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(exercise2.3 PROPERTIES VERSION "${EXERCICE23_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
### 5) Link the librairies for the targets
|
||||
######################################################################################
|
||||
|
||||
TARGET_LINK_LIBRARIES(FirstBitEA ga eo eoutils)
|
||||
TARGET_LINK_LIBRARIES(FirstRealEA ga eo eoutils)
|
||||
TARGET_LINK_LIBRARIES(exercise2.3 ga eo eoutils)
|
||||
target_link_libraries(FirstBitEA ga eo eoutils)
|
||||
target_link_libraries(FirstRealEA ga eo eoutils)
|
||||
target_link_libraries(exercise2.3 ga eo eoutils)
|
||||
|
||||
######################################################################################
|
||||
### 6) Configure project installation paths
|
||||
######################################################################################
|
||||
|
||||
INSTALL(TARGETS FirstBitEA RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson2 COMPONENT examples)
|
||||
INSTALL(TARGETS FirstRealEA RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson2 COMPONENT examples)
|
||||
INSTALL(TARGETS exercise2.3 RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson2 COMPONENT examples)
|
||||
install(TARGETS FirstBitEA RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson2 COMPONENT examples)
|
||||
install(TARGETS FirstRealEA RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson2 COMPONENT examples)
|
||||
install(TARGETS exercise2.3 RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson2 COMPONENT examples)
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
|
|
@ -2,63 +2,63 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/ga)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/utils)
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${EO_SRC_DIR}/src/ga)
|
||||
include_directories(${EO_SRC_DIR}/src/utils)
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries
|
||||
######################################################################################
|
||||
|
||||
IF(NOT WIN32 OR CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
ENDIF(NOT WIN32 OR CYGWIN)
|
||||
if(NOT WIN32 OR CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}/lib)
|
||||
endif(NOT WIN32 OR CYGWIN)
|
||||
|
||||
# especially for Visual Studio
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
ENDIF(WIN32 AND NOT CYGWIN)
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
endif(WIN32 AND NOT CYGWIN)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your targets
|
||||
######################################################################################
|
||||
|
||||
# no matter what is the OS, hopefully
|
||||
ADD_EXECUTABLE(SecondBitEA SecondBitEA.cpp)
|
||||
ADD_EXECUTABLE(SecondRealEA SecondRealEA.cpp)
|
||||
ADD_EXECUTABLE(exercise3.1 exercise3.1.cpp)
|
||||
add_executable(SecondBitEA SecondBitEA.cpp)
|
||||
add_executable(SecondRealEA SecondRealEA.cpp)
|
||||
add_executable(exercise3.1 exercise3.1.cpp)
|
||||
|
||||
ADD_DEPENDENCIES(SecondBitEA ga eoutils eo)
|
||||
ADD_DEPENDENCIES(SecondRealEA ga eoutils eo)
|
||||
ADD_DEPENDENCIES(exercise3.1 ga eoutils eo)
|
||||
add_dependencies(SecondBitEA ga eoutils eo)
|
||||
add_dependencies(SecondRealEA ga eoutils eo)
|
||||
add_dependencies(exercise3.1 ga eoutils eo)
|
||||
|
||||
######################################################################################
|
||||
### 4) Optionnal
|
||||
######################################################################################
|
||||
|
||||
SET(SECONDBITEA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(SecondBitEA PROPERTIES VERSION "${SECONDBITEA_VERSION}")
|
||||
set(SECONDBITEA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(SecondBitEA PROPERTIES VERSION "${SECONDBITEA_VERSION}")
|
||||
|
||||
SET(SECONDREALEA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(SecondRealEA PROPERTIES VERSION "${SECONDREALEA_VERSION}")
|
||||
set(SECONDREALEA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(SecondRealEA PROPERTIES VERSION "${SECONDREALEA_VERSION}")
|
||||
|
||||
SET(EXERCICE31_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(exercise3.1 PROPERTIES VERSION "${EXERCICE31_VERSION}")
|
||||
set(EXERCICE31_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(exercise3.1 PROPERTIES VERSION "${EXERCICE31_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
### 5) Link the librairies for the targets
|
||||
######################################################################################
|
||||
|
||||
TARGET_LINK_LIBRARIES(SecondBitEA ga eoutils eo)
|
||||
TARGET_LINK_LIBRARIES(SecondRealEA ga eoutils eo)
|
||||
TARGET_LINK_LIBRARIES(exercise3.1 ga eoutils eo)
|
||||
target_link_libraries(SecondBitEA ga eoutils eo)
|
||||
target_link_libraries(SecondRealEA ga eoutils eo)
|
||||
target_link_libraries(exercise3.1 ga eoutils eo)
|
||||
|
||||
######################################################################################
|
||||
### 6) Configure project installation paths
|
||||
######################################################################################
|
||||
|
||||
INSTALL(TARGETS SecondBitEA RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson3 COMPONENT examples)
|
||||
INSTALL(TARGETS SecondRealEA RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson3 COMPONENT examples)
|
||||
INSTALL(TARGETS exercise3.1 RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson3 COMPONENT examples)
|
||||
install(TARGETS SecondBitEA RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson3 COMPONENT examples)
|
||||
install(TARGETS SecondRealEA RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson3 COMPONENT examples)
|
||||
install(TARGETS exercise3.1 RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson3 COMPONENT examples)
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
|
|
@ -2,97 +2,97 @@
|
|||
### 0) Copy the ESEA.param and RealEA.param files in the build directory for an easy use.
|
||||
######################################################################################
|
||||
|
||||
EXECUTE_PROCESS(
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${EO_SOURCE_DIR}/tutorial/Lesson4/ESEA.param
|
||||
${EO_BINARY_DIR}/tutorial/Lesson4/ESEA.param
|
||||
${EO_SRC_DIR}/tutorial/Lesson4/ESEA.param
|
||||
${EO_BIN_DIR}/tutorial/Lesson4/ESEA.param
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${EO_SOURCE_DIR}/tutorial/Lesson4/RealEA.param
|
||||
${EO_BINARY_DIR}/tutorial/Lesson4/RealEA.param
|
||||
${EO_SRC_DIR}/tutorial/Lesson4/RealEA.param
|
||||
${EO_BIN_DIR}/tutorial/Lesson4/RealEA.param
|
||||
)
|
||||
|
||||
##############
|
||||
# OLD_TARGETS
|
||||
##############
|
||||
#ADD_CUSTOM_TARGET(param DEPENDS ${EO_SOURCE_DIR}/tutorial/Lesson4/ESEA.param)
|
||||
#ADD_CUSTOM_COMMAND(
|
||||
#add_custom_target(param DEPENDS ${EO_SRC_DIR}/tutorial/Lesson4/ESEA.param)
|
||||
#add_custom_command(
|
||||
# TARGET param
|
||||
# POST_BUILD
|
||||
# COMMAND ${CMAKE_COMMAND}
|
||||
# ARGS -E copy_if_different
|
||||
# ${EO_SOURCE_DIR}/tutorial/Lesson4/ESEA.param
|
||||
# ${EO_BINARY_DIR}/tutorial/Lesson4)
|
||||
#ADD_CUSTOM_TARGET(param DEPENDS ${EO_SOURCE_DIR}/tutorial/Lesson4/RealEA.param)
|
||||
#ADD_CUSTOM_COMMAND(
|
||||
# ${EO_SRC_DIR}/tutorial/Lesson4/ESEA.param
|
||||
# ${EO_BIN_DIR}/tutorial/Lesson4)
|
||||
#add_custom_target(param DEPENDS ${EO_SRC_DIR}/tutorial/Lesson4/RealEA.param)
|
||||
#add_custom_command(
|
||||
# TARGET param
|
||||
# POST_BUILD
|
||||
# COMMAND ${CMAKE_COMMAND}
|
||||
# ARGS -E copy_if_different
|
||||
# ${EO_SOURCE_DIR}/tutorial/Lesson4/RealEA.param
|
||||
# ${EO_BINARY_DIR}/tutorial/Lesson4)
|
||||
# ${EO_SRC_DIR}/tutorial/Lesson4/RealEA.param
|
||||
# ${EO_BIN_DIR}/tutorial/Lesson4)
|
||||
|
||||
######################################################################################
|
||||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/es)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/utils)
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/ga)
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${EO_SRC_DIR}/src/es)
|
||||
include_directories(${EO_SRC_DIR}/src/utils)
|
||||
include_directories(${EO_SRC_DIR}/src/ga)
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries
|
||||
######################################################################################
|
||||
|
||||
IF(NOT WIN32 OR CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
ENDIF(NOT WIN32 OR CYGWIN)
|
||||
if(NOT WIN32 OR CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}/lib)
|
||||
endif(NOT WIN32 OR CYGWIN)
|
||||
|
||||
# especially for Visual Studio
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
ENDIF(WIN32 AND NOT CYGWIN)
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
endif(WIN32 AND NOT CYGWIN)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your targets
|
||||
######################################################################################
|
||||
|
||||
# no matter what is the OS, hopefully
|
||||
ADD_EXECUTABLE(BitEA BitEA.cpp)
|
||||
ADD_EXECUTABLE(RealEA RealEA.cpp)
|
||||
ADD_EXECUTABLE(ESEA ESEA.cpp)
|
||||
add_executable(BitEA BitEA.cpp)
|
||||
add_executable(RealEA RealEA.cpp)
|
||||
add_executable(ESEA ESEA.cpp)
|
||||
|
||||
#ADD_DEPENDENCIES(BitEA es ga eo eoutils)
|
||||
#ADD_DEPENDENCIES(RealEA es ga eo eoutils)
|
||||
#ADD_DEPENDENCIES(ESEA es ga eo eoutils)
|
||||
#add_dependencies(BitEA es ga eo eoutils)
|
||||
#add_dependencies(RealEA es ga eo eoutils)
|
||||
#add_dependencies(ESEA es ga eo eoutils)
|
||||
|
||||
######################################################################################
|
||||
### 4) Optionnal
|
||||
######################################################################################
|
||||
|
||||
SET(BITEA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(BitEA PROPERTIES VERSION "${BITEA_VERSION}")
|
||||
set(BITEA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(BitEA PROPERTIES VERSION "${BITEA_VERSION}")
|
||||
|
||||
SET(REALEA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(RealEA PROPERTIES VERSION "${REALEA_VERSION}")
|
||||
set(REALEA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(RealEA PROPERTIES VERSION "${REALEA_VERSION}")
|
||||
|
||||
SET(ESEA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(ESEA PROPERTIES VERSION "${ESEA_VERSION}")
|
||||
set(ESEA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(ESEA PROPERTIES VERSION "${ESEA_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
### 5) Link the librairies for the targets
|
||||
######################################################################################
|
||||
|
||||
TARGET_LINK_LIBRARIES(BitEA es ga eo eoutils)
|
||||
TARGET_LINK_LIBRARIES(RealEA es ga eo eoutils)
|
||||
TARGET_LINK_LIBRARIES(ESEA es ga eo eoutils)
|
||||
target_link_libraries(BitEA es ga eo eoutils)
|
||||
target_link_libraries(RealEA es ga eo eoutils)
|
||||
target_link_libraries(ESEA es ga eo eoutils)
|
||||
|
||||
######################################################################################
|
||||
### 6) Configure project installation paths
|
||||
######################################################################################
|
||||
|
||||
INSTALL(TARGETS BitEA RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson4 COMPONENT examples)
|
||||
INSTALL(TARGETS RealEA RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson4 COMPONENT examples)
|
||||
INSTALL(TARGETS ESEA RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson4 COMPONENT examples)
|
||||
install(TARGETS BitEA RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson4 COMPONENT examples)
|
||||
install(TARGETS RealEA RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson4 COMPONENT examples)
|
||||
install(TARGETS ESEA RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson4 COMPONENT examples)
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
|
|
@ -2,55 +2,55 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries
|
||||
######################################################################################
|
||||
|
||||
IF(NOT WIN32 OR CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
ENDIF(NOT WIN32 OR CYGWIN)
|
||||
if(NOT WIN32 OR CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}/lib)
|
||||
endif(NOT WIN32 OR CYGWIN)
|
||||
|
||||
# especially for Visual Studio
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
ENDIF(WIN32 AND NOT CYGWIN)
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
endif(WIN32 AND NOT CYGWIN)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your targets
|
||||
######################################################################################
|
||||
|
||||
# no matter what is the OS, hopefully
|
||||
ADD_EXECUTABLE(OneMaxEA OneMaxEA.cpp)
|
||||
ADD_EXECUTABLE(OneMaxLibEA OneMaxLibEA.cpp make_OneMax.cpp)
|
||||
add_executable(OneMaxEA OneMaxEA.cpp)
|
||||
add_executable(OneMaxLibEA OneMaxLibEA.cpp make_OneMax.cpp)
|
||||
|
||||
ADD_DEPENDENCIES(OneMaxEA es ga eo eoutils)
|
||||
ADD_DEPENDENCIES(OneMaxLibEA es ga eo eoutils)
|
||||
add_dependencies(OneMaxEA es ga eo eoutils)
|
||||
add_dependencies(OneMaxLibEA es ga eo eoutils)
|
||||
|
||||
######################################################################################
|
||||
### 4) Optionnal
|
||||
######################################################################################
|
||||
|
||||
SET(ONEMAXEA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(OneMaxEA PROPERTIES VERSION "${ONEMAXEA_VERSION}")
|
||||
set(ONEMAXEA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(OneMaxEA PROPERTIES VERSION "${ONEMAXEA_VERSION}")
|
||||
|
||||
SET(ONEMAXLIBEA_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(OneMaxLibEA PROPERTIES VERSION "${ONEMAXLIBEA_VERSION}")
|
||||
set(ONEMAXLIBEA_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(OneMaxLibEA PROPERTIES VERSION "${ONEMAXLIBEA_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
### 5) Link the librairies for the targets
|
||||
######################################################################################
|
||||
|
||||
TARGET_LINK_LIBRARIES(OneMaxEA es ga eo eoutils)
|
||||
TARGET_LINK_LIBRARIES(OneMaxLibEA es ga eo eoutils)
|
||||
target_link_libraries(OneMaxEA es ga eo eoutils)
|
||||
target_link_libraries(OneMaxLibEA es ga eo eoutils)
|
||||
|
||||
######################################################################################
|
||||
### 6) Configure project installation paths
|
||||
######################################################################################
|
||||
|
||||
INSTALL(TARGETS OneMaxEA RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson5 COMPONENT examples)
|
||||
INSTALL(TARGETS OneMaxLibEA RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson5 COMPONENT examples)
|
||||
install(TARGETS OneMaxEA RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson5 COMPONENT examples)
|
||||
install(TARGETS OneMaxLibEA RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson5 COMPONENT examples)
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
|
|
@ -2,50 +2,50 @@
|
|||
### 1) Include the sources
|
||||
######################################################################################
|
||||
|
||||
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
|
||||
include_directories(${EO_SRC_DIR}/src)
|
||||
|
||||
######################################################################################
|
||||
### 2) Specify where CMake can find the libraries
|
||||
######################################################################################
|
||||
|
||||
IF(NOT WIN32 OR CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}/lib)
|
||||
ENDIF(NOT WIN32 OR CYGWIN)
|
||||
if(NOT WIN32 OR CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}/lib)
|
||||
endif(NOT WIN32 OR CYGWIN)
|
||||
|
||||
# especially for Visual Studio
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
LINK_DIRECTORIES(${EO_BINARY_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
ENDIF(WIN32 AND NOT CYGWIN)
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
link_directories(${EO_BIN_DIR}\\lib\\${CMAKE_BUILD_TYPE})
|
||||
endif(WIN32 AND NOT CYGWIN)
|
||||
|
||||
######################################################################################
|
||||
### 3) Define your targets
|
||||
######################################################################################
|
||||
|
||||
ADD_EXECUTABLE(BinaryPSO BinaryPSO.cpp)
|
||||
ADD_EXECUTABLE(RealPSO RealPSO.cpp)
|
||||
add_executable(BinaryPSO BinaryPSO.cpp)
|
||||
add_executable(RealPSO RealPSO.cpp)
|
||||
|
||||
######################################################################################
|
||||
### 4) Optionnal
|
||||
######################################################################################
|
||||
|
||||
SET(BINARYPSO_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(BinaryPSO PROPERTIES VERSION "${BINARYPSO_VERSION}")
|
||||
set(BINARYPSO_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(BinaryPSO PROPERTIES VERSION "${BINARYPSO_VERSION}")
|
||||
|
||||
SET(REALPSO_VERSION ${GLOBAL_VERSION})
|
||||
SET_TARGET_PROPERTIES(RealPSO PROPERTIES VERSION "${REALPSO_VERSION}")
|
||||
set(REALPSO_VERSION ${GLOBAL_VERSION})
|
||||
set_target_properties(RealPSO PROPERTIES VERSION "${REALPSO_VERSION}")
|
||||
|
||||
######################################################################################
|
||||
### 5) Link the librairies for the targets
|
||||
######################################################################################
|
||||
|
||||
TARGET_LINK_LIBRARIES(BinaryPSO eo eoutils)
|
||||
TARGET_LINK_LIBRARIES(RealPSO eo eoutils)
|
||||
target_link_libraries(BinaryPSO eo eoutils)
|
||||
target_link_libraries(RealPSO eo eoutils)
|
||||
|
||||
######################################################################################
|
||||
### 6) Configure project installation paths
|
||||
######################################################################################
|
||||
|
||||
INSTALL(TARGETS BinaryPSO RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson6 COMPONENT examples)
|
||||
INSTALL(TARGETS RealPSO RUNTIME DESTINATION share${INSTALL_SUB_DIR}/eo/examples/Lesson6 COMPONENT examples)
|
||||
install(TARGETS BinaryPSO RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson6 COMPONENT examples)
|
||||
install(TARGETS RealPSO RUNTIME DESTINATION local/share${INSTALL_SUB_DIR}/eo/examples/Lesson6 COMPONENT examples)
|
||||
|
||||
######################################################################################
|
||||
|
|
|
|||
63
eo/tutorial/Parallelization/INSTALL
Normal file
63
eo/tutorial/Parallelization/INSTALL
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
How to install EoMPI
|
||||
====================
|
||||
|
||||
Install OpenMpi
|
||||
---------------
|
||||
|
||||
1) Download OpenMPI on their website or with the following command:
|
||||
|
||||
wget http://www.open-mpi.org/software/ompi/v1.6/downloads/openmpi-1.6.tar.bz2
|
||||
|
||||
2) Untar the downloaded archive in a directory and change working directory to there:
|
||||
|
||||
tar -xvjf openmpi*.tar.bz2
|
||||
cd openmpi-X.Y
|
||||
|
||||
3) Use configuration script to indicate in which directory OpenMPI should be installed, and other options:
|
||||
|
||||
Simplest configuration:
|
||||
./configure --prefix=/home/`whoami`/openmpi/
|
||||
|
||||
Only static libraries:
|
||||
./configure --enable-static --disable-shared
|
||||
|
||||
Only static libraries, with prefix, disable build for Fortran77 and Fortran90, add support for SGE:
|
||||
./configure --enable-static --disable-shared --prefix=/home/`whoami`/openmpi/ --disable-mpi-f77 --disable-mpi-f90 --with-sge
|
||||
|
||||
Other options are available in the README file.
|
||||
|
||||
4) Make it and install:
|
||||
|
||||
In sequential:
|
||||
make all install
|
||||
|
||||
Or in parallel:
|
||||
make -j 2 all
|
||||
make install
|
||||
|
||||
5) Try to compile and run the sample program:
|
||||
|
||||
~/openmpi/bin/mpicxx -o sample mpi.c
|
||||
~/openmpi/bin/mpirun -np 3 ./sample
|
||||
|
||||
Configure EO to use MPI
|
||||
-----------------------
|
||||
|
||||
You only need to configure eo-conf.cmake so as to use MPI :
|
||||
|
||||
1) Put the WITH_MPI boolean to true:
|
||||
|
||||
SET(WITH_MPI TRUE CACHE BOOL "Use mpi ?" FORCE)
|
||||
|
||||
2) Indicate in which directories you have installed openmpi:
|
||||
|
||||
SET(MPI_DIR "/where/did/you/install/openmpi" CACHE PATH "OpenMPI directory" FORCE)
|
||||
|
||||
3) Recompile eo:
|
||||
|
||||
./distclean
|
||||
./build_gcc_linux_release.sh
|
||||
|
||||
4) If you meet any issue, don't hesitate to contact the EO mailing list:
|
||||
|
||||
eodev-main@lists.sourceforge.net
|
||||
405
eo/tutorial/Parallelization/css/deck.core.css
Normal file
405
eo/tutorial/Parallelization/css/deck.core.css
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body.deck-container {
|
||||
overflow-y: auto;
|
||||
position: static;
|
||||
}
|
||||
|
||||
.deck-container {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 0 48px;
|
||||
font-size: 16px;
|
||||
line-height: 1.25;
|
||||
overflow: hidden;
|
||||
/* Resets and base styles from HTML5 Boilerplate */
|
||||
/* End HTML5 Boilerplate adaptations */
|
||||
}
|
||||
.js .deck-container {
|
||||
visibility: hidden;
|
||||
}
|
||||
.ready .deck-container {
|
||||
visibility: visible;
|
||||
}
|
||||
.touch .deck-container {
|
||||
-webkit-text-size-adjust: none;
|
||||
-moz-text-size-adjust: none;
|
||||
}
|
||||
.deck-container div, .deck-container span, .deck-container object, .deck-container iframe,
|
||||
.deck-container h1, .deck-container h2, .deck-container h3, .deck-container h4, .deck-container h5, .deck-container h6, .deck-container p, .deck-container blockquote, .deck-container pre,
|
||||
.deck-container abbr, .deck-container address, .deck-container cite, .deck-container code, .deck-container del, .deck-container dfn, .deck-container em, .deck-container img, .deck-container ins, .deck-container kbd, .deck-container q, .deck-container samp,
|
||||
.deck-container small, .deck-container strong, .deck-container sub, .deck-container sup, .deck-container var, .deck-container b, .deck-container i, .deck-container dl, .deck-container dt, .deck-container dd, .deck-container ol, .deck-container ul, .deck-container li,
|
||||
.deck-container fieldset, .deck-container form, .deck-container label, .deck-container legend,
|
||||
.deck-container table, .deck-container caption, .deck-container tbody, .deck-container tfoot, .deck-container thead, .deck-container tr, .deck-container th, .deck-container td,
|
||||
.deck-container article, .deck-container aside, .deck-container canvas, .deck-container details, .deck-container figcaption, .deck-container figure,
|
||||
.deck-container footer, .deck-container header, .deck-container hgroup, .deck-container menu, .deck-container nav, .deck-container section, .deck-container summary,
|
||||
.deck-container time, .deck-container mark, .deck-container audio, .deck-container video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
.deck-container article, .deck-container aside, .deck-container details, .deck-container figcaption, .deck-container figure,
|
||||
.deck-container footer, .deck-container header, .deck-container hgroup, .deck-container menu, .deck-container nav, .deck-container section {
|
||||
display: block;
|
||||
}
|
||||
.deck-container blockquote, .deck-container q {
|
||||
quotes: none;
|
||||
}
|
||||
.deck-container blockquote:before, .deck-container blockquote:after, .deck-container q:before, .deck-container q:after {
|
||||
content: "";
|
||||
content: none;
|
||||
}
|
||||
.deck-container ins {
|
||||
background-color: #ff9;
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
}
|
||||
.deck-container mark {
|
||||
background-color: #ff9;
|
||||
color: #000;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
}
|
||||
.deck-container del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.deck-container abbr[title], .deck-container dfn[title] {
|
||||
border-bottom: 1px dotted;
|
||||
cursor: help;
|
||||
}
|
||||
.deck-container table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
.deck-container hr {
|
||||
display: block;
|
||||
height: 1px;
|
||||
border: 0;
|
||||
border-top: 1px solid #ccc;
|
||||
margin: 1em 0;
|
||||
padding: 0;
|
||||
}
|
||||
.deck-container input, .deck-container select {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.deck-container select, .deck-container input, .deck-container textarea, .deck-container button {
|
||||
font: 99% sans-serif;
|
||||
}
|
||||
.deck-container pre, .deck-container code, .deck-container kbd, .deck-container samp {
|
||||
font-family: monospace, sans-serif;
|
||||
}
|
||||
.deck-container a {
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
.deck-container a:hover, .deck-container a:active {
|
||||
outline: none;
|
||||
}
|
||||
.deck-container ul, .deck-container ol {
|
||||
margin-left: 2em;
|
||||
vertical-align: top;
|
||||
}
|
||||
.deck-container ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
.deck-container nav ul, .deck-container nav li {
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
list-style-image: none;
|
||||
}
|
||||
.deck-container small {
|
||||
font-size: 85%;
|
||||
}
|
||||
.deck-container strong, .deck-container th {
|
||||
font-weight: bold;
|
||||
}
|
||||
.deck-container td {
|
||||
vertical-align: top;
|
||||
}
|
||||
.deck-container sub, .deck-container sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
}
|
||||
.deck-container sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
.deck-container sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
.deck-container textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
.ie6 .deck-container legend, .ie7 .deck-container legend {
|
||||
margin-left: -7px;
|
||||
}
|
||||
.deck-container input[type="radio"] {
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
.deck-container input[type="checkbox"] {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.ie7 .deck-container input[type="checkbox"] {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
.ie6 .deck-container input {
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
.deck-container label, .deck-container input[type="button"], .deck-container input[type="submit"], .deck-container input[type="image"], .deck-container button {
|
||||
cursor: pointer;
|
||||
}
|
||||
.deck-container button, .deck-container input, .deck-container select, .deck-container textarea {
|
||||
margin: 0;
|
||||
}
|
||||
.deck-container input:invalid, .deck-container textarea:invalid {
|
||||
border-radius: 1px;
|
||||
-moz-box-shadow: 0px 0px 5px red;
|
||||
-webkit-box-shadow: 0px 0px 5px red;
|
||||
box-shadow: 0px 0px 5px red;
|
||||
}
|
||||
.deck-container input:invalid .no-boxshadow, .deck-container textarea:invalid .no-boxshadow {
|
||||
background-color: #f0dddd;
|
||||
}
|
||||
.deck-container button {
|
||||
width: auto;
|
||||
overflow: visible;
|
||||
}
|
||||
.ie7 .deck-container img {
|
||||
-ms-interpolation-mode: bicubic;
|
||||
}
|
||||
.deck-container, .deck-container select, .deck-container input, .deck-container textarea {
|
||||
color: #444;
|
||||
}
|
||||
.deck-container a {
|
||||
color: #607890;
|
||||
}
|
||||
.deck-container a:hover, .deck-container a:focus {
|
||||
color: #036;
|
||||
}
|
||||
.deck-container a:link {
|
||||
-webkit-tap-highlight-color: #fff;
|
||||
}
|
||||
.deck-container.deck-loading {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.slide {
|
||||
width: auto;
|
||||
min-height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.slide h1 {
|
||||
font-size: 4.5em;
|
||||
}
|
||||
.slide h1, .slide .vcenter {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
padding-top: 1em;
|
||||
max-height: 100%;
|
||||
}
|
||||
.csstransforms .slide h1, .csstransforms .slide .vcenter {
|
||||
padding: 0 48px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
-webkit-transform: translate(0, -50%);
|
||||
-moz-transform: translate(0, -50%);
|
||||
-ms-transform: translate(0, -50%);
|
||||
-o-transform: translate(0, -50%);
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
.slide .vcenter h1 {
|
||||
position: relative;
|
||||
top: auto;
|
||||
padding: 0;
|
||||
-webkit-transform: none;
|
||||
-moz-transform: none;
|
||||
-ms-transform: none;
|
||||
-o-transform: none;
|
||||
transform: none;
|
||||
}
|
||||
.slide h2 {
|
||||
font-size: 2.25em;
|
||||
font-weight: bold;
|
||||
padding-top: .5em;
|
||||
margin: 0 0 .66666em 0;
|
||||
border-bottom: 3px solid #888;
|
||||
}
|
||||
.slide h3 {
|
||||
font-size: 1.4375em;
|
||||
font-weight: bold;
|
||||
margin-bottom: .30435em;
|
||||
}
|
||||
.slide h4 {
|
||||
font-size: 1.25em;
|
||||
font-weight: bold;
|
||||
margin-bottom: .25em;
|
||||
}
|
||||
.slide h5 {
|
||||
font-size: 1.125em;
|
||||
font-weight: bold;
|
||||
margin-bottom: .2222em;
|
||||
}
|
||||
.slide h6 {
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.slide img, .slide iframe, .slide video {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
.slide video, .slide iframe, .slide img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.slide p, .slide blockquote, .slide iframe, .slide img, .slide ul, .slide ol, .slide pre, .slide video {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.slide pre {
|
||||
white-space: pre;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
padding: 1em;
|
||||
border: 1px solid #888;
|
||||
}
|
||||
.slide em {
|
||||
font-style: italic;
|
||||
}
|
||||
.slide li {
|
||||
padding: .25em 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.deck-before, .deck-previous, .deck-next, .deck-after {
|
||||
position: absolute;
|
||||
left: -999em;
|
||||
top: -999em;
|
||||
}
|
||||
|
||||
.deck-current {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.slide .slide {
|
||||
visibility: hidden;
|
||||
position: static;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.deck-child-current {
|
||||
position: static;
|
||||
z-index: 2;
|
||||
}
|
||||
.deck-child-current .slide {
|
||||
visibility: hidden;
|
||||
}
|
||||
.deck-child-current .deck-previous, .deck-child-current .deck-before, .deck-child-current .deck-current {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@media screen and (max-device-width: 480px) {
|
||||
/* html { -webkit-text-size-adjust:none; -ms-text-size-adjust:none; } */
|
||||
}
|
||||
@media print {
|
||||
* {
|
||||
background: transparent !important;
|
||||
color: black !important;
|
||||
text-shadow: none !important;
|
||||
filter: none !important;
|
||||
-ms-filter: none !important;
|
||||
-webkit-box-reflect: none !important;
|
||||
-moz-box-reflect: none !important;
|
||||
-webkit-box-shadow: none !important;
|
||||
-moz-box-shadow: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
* :before, * :after {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
a, a:visited {
|
||||
color: #444 !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a[href]:after {
|
||||
content: " (" attr(href) ")";
|
||||
}
|
||||
|
||||
abbr[title]:after {
|
||||
content: " (" attr(title) ")";
|
||||
}
|
||||
|
||||
.ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after {
|
||||
content: "";
|
||||
}
|
||||
|
||||
pre, blockquote {
|
||||
border: 1px solid #999;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
thead {
|
||||
display: table-header-group;
|
||||
}
|
||||
|
||||
tr, img {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
@page {
|
||||
margin: 0.5cm;
|
||||
}
|
||||
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
|
||||
h2, h3 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
|
||||
.slide {
|
||||
position: static !important;
|
||||
visibility: visible !important;
|
||||
display: block !important;
|
||||
-webkit-transform: none !important;
|
||||
-moz-transform: none !important;
|
||||
-o-transform: none !important;
|
||||
-ms-transform: none !important;
|
||||
transform: none !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
h1, .vcenter {
|
||||
-webkit-transform: none !important;
|
||||
-moz-transform: none !important;
|
||||
-o-transform: none !important;
|
||||
-ms-transform: none !important;
|
||||
transform: none !important;
|
||||
padding: 0 !important;
|
||||
position: static !important;
|
||||
}
|
||||
|
||||
.deck-container > .slide {
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
.deck-container {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
padding: 0 !important;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
script {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
41
eo/tutorial/Parallelization/css/deck.goto.css
Normal file
41
eo/tutorial/Parallelization/css/deck.goto.css
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
.deck-container .goto-form {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
bottom: 10px;
|
||||
left: 50%;
|
||||
height: 1.75em;
|
||||
margin: 0 0 0 -9.125em;
|
||||
line-height: 1.75em;
|
||||
padding: 0.625em;
|
||||
display: none;
|
||||
background: #ccc;
|
||||
overflow: hidden;
|
||||
}
|
||||
.borderradius .deck-container .goto-form {
|
||||
-webkit-border-radius: 10px;
|
||||
-moz-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.deck-container .goto-form label {
|
||||
font-weight: bold;
|
||||
}
|
||||
.deck-container .goto-form label, .deck-container .goto-form input {
|
||||
display: inline-block;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.deck-goto .goto-form {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#goto-slide {
|
||||
width: 8.375em;
|
||||
margin: 0 0.625em;
|
||||
height: 1.4375em;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.goto-form, #goto-slide {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
13
eo/tutorial/Parallelization/css/deck.hash.css
Normal file
13
eo/tutorial/Parallelization/css/deck.hash.css
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
.deck-container .deck-permalink {
|
||||
display: none;
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
bottom: 30px;
|
||||
right: 0;
|
||||
width: 48px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-history .deck-container:hover .deck-permalink {
|
||||
display: block;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue