Merge 2bfd27007f into 3259d1b452
This commit is contained in:
commit
692225bdbb
12 changed files with 819 additions and 167 deletions
|
|
@ -42,6 +42,12 @@
|
|||
* Abstract class for multi-objective algorithms.
|
||||
*/
|
||||
class moeoAlgo
|
||||
{};
|
||||
{
|
||||
public:
|
||||
virtual ~moeoAlgo() = default;
|
||||
|
||||
/** Whether this algorithm supports finalize() for post-integration updates. */
|
||||
virtual bool hasFinalize() const { return false; }
|
||||
};
|
||||
|
||||
#endif /*MOEOALGO_H_*/
|
||||
|
|
|
|||
|
|
@ -148,6 +148,17 @@ public:
|
|||
while (continuator (_pop));
|
||||
}
|
||||
|
||||
/**
|
||||
* Recompute fitness and diversity assignments on the population.
|
||||
* Useful after integrating immigrants from an island model.
|
||||
* @param _pop the population to finalize
|
||||
*/
|
||||
void finalize(eoPop<MOEOT>& _pop) override {
|
||||
fitnessAssignment(_pop);
|
||||
diversityAssignment(_pop);
|
||||
}
|
||||
|
||||
bool hasFinalize() const override { return true; }
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,14 @@
|
|||
*/
|
||||
template < class MOEOT >
|
||||
class moeoPopAlgo : public moeoAlgo, public eoAlgo < MOEOT >
|
||||
{};
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Recompute fitness/diversity after external population changes (e.g. immigrant integration).
|
||||
* Default implementation is a no-op. Override in subclasses that need it.
|
||||
* @param _pop the population to finalize
|
||||
*/
|
||||
virtual void finalize(eoPop<MOEOT>&) {}
|
||||
};
|
||||
|
||||
#endif /*MOEOPOPALGO_H_*/
|
||||
|
|
|
|||
272
smp/src/MPI_IslandModel.cpp
Normal file
272
smp/src/MPI_IslandModel.cpp
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
<MPI_IslandModel.cpp>
|
||||
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
||||
|
||||
Alexandre Quemy, Thibault Lasnier - INSA Rouen
|
||||
Eremey Valetov
|
||||
|
||||
This software is governed by the CeCILL license under French law and
|
||||
abiding by the rules of distribution of free software. You can use,
|
||||
modify and/ or redistribute the software under the terms of the CeCILL
|
||||
license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
"http://www.cecill.info".
|
||||
|
||||
ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <mpi.h>
|
||||
#include <SerializableBase.h>
|
||||
#include <serial/Parser.h>
|
||||
#include <utils/eoLogger.h>
|
||||
|
||||
template<class EOT>
|
||||
MPI_IslandModel<EOT>::MPI_IslandModel(AbstractTopology& _topo, int _pollIntervalMs)
|
||||
: topo(_topo), pollIntervalMs(_pollIntervalMs), running(false)
|
||||
{
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &num_mpi_ranks);
|
||||
}
|
||||
|
||||
template<class EOT>
|
||||
void paradiseo::smp::MPI_IslandModel<EOT>::add(AIsland<EOT>& _island)
|
||||
{
|
||||
islands.push_back(std::pair<AIsland<EOT>*, bool>(&_island, false));
|
||||
islands.back().first->setModel(this);
|
||||
}
|
||||
|
||||
template<class EOT>
|
||||
void MPI_IslandModel<EOT>::operator()() {
|
||||
running = true;
|
||||
initModel();
|
||||
|
||||
std::thread islandThread;
|
||||
if (mpi_rank < static_cast<int>(islands.size())) {
|
||||
auto& it = islands[mpi_rank];
|
||||
it.first->setRunning();
|
||||
islandThread = std::thread(&AIsland<EOT>::operator(), it.first);
|
||||
}
|
||||
|
||||
int localIslandRunning = 1;
|
||||
int globalIslandRunning = 0;
|
||||
|
||||
do {
|
||||
localIslandRunning = (mpi_rank < static_cast<int>(islands.size()) &&
|
||||
!islands[mpi_rank].first->isStopped()) ? 1 : 0;
|
||||
|
||||
send();
|
||||
|
||||
MPI_Allreduce(&localIslandRunning, &globalIslandRunning, 1,
|
||||
MPI_INT, MPI_SUM, MPI_COMM_WORLD);
|
||||
if (globalIslandRunning > 0)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(pollIntervalMs));
|
||||
} while (globalIslandRunning > 0);
|
||||
|
||||
if (islandThread.joinable())
|
||||
islandThread.join();
|
||||
|
||||
for (auto& message : sentMessages)
|
||||
message.wait();
|
||||
sentMessages.clear();
|
||||
|
||||
// Discard remaining outgoing emigrants — all islands have stopped,
|
||||
// so migrated individuals would never be processed by recipients.
|
||||
// Using send() here risks MPI deadlock when multiple ranks each
|
||||
// have pending emigrants to send but no matching receives posted.
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
while (!listEmigrants.empty()) listEmigrants.pop();
|
||||
}
|
||||
|
||||
std::thread lastIntegrationThread;
|
||||
if (mpi_rank < static_cast<int>(islands.size())) {
|
||||
lastIntegrationThread = std::thread([&]() {
|
||||
islands[mpi_rank].first->receive();
|
||||
});
|
||||
}
|
||||
|
||||
if (lastIntegrationThread.joinable())
|
||||
lastIntegrationThread.join();
|
||||
|
||||
// Wait for any async island.update() tasks launched during the drain phase.
|
||||
// Without this, islands may be deleted while tasks still reference them.
|
||||
for (auto& message : sentMessages)
|
||||
message.wait();
|
||||
sentMessages.clear();
|
||||
|
||||
// Cancel remaining non-blocking sends. After the polling loop and drain,
|
||||
// any unsent data targets stopped islands — safe to discard.
|
||||
for (auto& ps : pendingSends) {
|
||||
MPI_Cancel(&ps.request);
|
||||
MPI_Wait(&ps.request, MPI_STATUS_IGNORE);
|
||||
}
|
||||
pendingSends.clear();
|
||||
|
||||
running = false;
|
||||
}
|
||||
|
||||
template<class EOT>
|
||||
bool paradiseo::smp::MPI_IslandModel<EOT>::update(eoPop<EOT> _data, AIsland<EOT>* _island)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
listEmigrants.push(std::pair<eoPop<EOT>,AIsland<EOT>*>(_data, _island));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class EOT>
|
||||
void paradiseo::smp::MPI_IslandModel<EOT>::setTopology(AbstractTopology& _topo)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
topo = _topo;
|
||||
if (running) {
|
||||
topo.construct(islands.size());
|
||||
for (auto it : islands)
|
||||
if (!it.second)
|
||||
topo.isolateNode(table.getLeft()[it.first]);
|
||||
}
|
||||
}
|
||||
|
||||
template<class EOT>
|
||||
void paradiseo::smp::MPI_IslandModel<EOT>::send(void) {
|
||||
// Receive first, then send — prevents accumulation of unprocessed messages.
|
||||
if (!islands.empty() && mpi_rank < static_cast<int>(islands.size())) {
|
||||
unsigned myId = mpi_rank;
|
||||
std::vector<unsigned> neighbors = topo.getIdNeighbors(myId);
|
||||
|
||||
for (unsigned idFromNeighbor : neighbors) {
|
||||
int tag = idFromNeighbor * 1000 + mpi_rank;
|
||||
int flag = 0;
|
||||
MPI_Status mpiStatus;
|
||||
MPI_Iprobe(idFromNeighbor, tag, MPI_COMM_WORLD, &flag, &mpiStatus);
|
||||
|
||||
if (flag) {
|
||||
// Single-message receive: MPI_Iprobe confirmed the complete
|
||||
// message is available, so MPI_Recv returns immediately.
|
||||
// This avoids the two-message protocol (size + data) in
|
||||
// comm.recv(), which can deadlock when the size message
|
||||
// arrives before the data message is progressed by MPI.
|
||||
int count = 0;
|
||||
MPI_Get_count(&mpiStatus, MPI_CHAR, &count);
|
||||
std::string serialized(count, '\0');
|
||||
MPI_Recv(&serialized[0], count, MPI_CHAR, idFromNeighbor, tag,
|
||||
MPI_COMM_WORLD, MPI_STATUS_IGNORE);
|
||||
|
||||
eoserial::Object* obj = eoserial::Parser::parse(serialized);
|
||||
SerializableBase<eoPop<EOT>> receivedSerializablePop;
|
||||
receivedSerializablePop.unpack(obj);
|
||||
delete obj;
|
||||
|
||||
eoPop<EOT> receivedPop = receivedSerializablePop;
|
||||
eo::log << eo::debug << "MPI_IslandModel: rank " << mpi_rank
|
||||
<< " received " << receivedPop.size() << " migrant(s) from island "
|
||||
<< idFromNeighbor << " (tag=" << tag << ")" << std::endl;
|
||||
|
||||
sentMessages.push_back(std::async(std::launch::async,
|
||||
&AIsland<EOT>::update,
|
||||
table.getRight()[myId],
|
||||
std::move(receivedPop)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up completed async tasks
|
||||
sentMessages.erase(std::remove_if(sentMessages.begin(), sentMessages.end(),
|
||||
[](std::shared_future<bool>& i) -> bool
|
||||
{ return i.wait_for(std::chrono::nanoseconds(0)) == std::future_status::ready; }
|
||||
),
|
||||
sentMessages.end());
|
||||
|
||||
// Then send outgoing emigrants
|
||||
eoPop<EOT> migPop;
|
||||
unsigned idFrom = 0;
|
||||
bool hasMigrant = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
if (!listEmigrants.empty()) {
|
||||
idFrom = table.getLeft()[listEmigrants.front().second];
|
||||
migPop = std::move(listEmigrants.front().first);
|
||||
listEmigrants.pop();
|
||||
hasMigrant = true;
|
||||
}
|
||||
}
|
||||
if (hasMigrant) {
|
||||
std::vector<unsigned> neighbors = topo.getIdNeighbors(idFrom);
|
||||
|
||||
// Serialize once for all neighbors (same protocol as comm.send for Persistent)
|
||||
SerializableBase<eoPop<EOT>> serializablePop(migPop);
|
||||
eoserial::Object* obj = serializablePop.pack();
|
||||
std::stringstream ss;
|
||||
obj->print(ss);
|
||||
delete obj;
|
||||
std::string serialized = ss.str();
|
||||
int size = static_cast<int>(serialized.size()) + 1;
|
||||
|
||||
for (unsigned idTo : neighbors) {
|
||||
int tag = idFrom * 1000 + idTo;
|
||||
eo::log << eo::debug << "MPI_IslandModel: rank " << mpi_rank
|
||||
<< " sending " << migPop.size() << " migrant(s) from island "
|
||||
<< idFrom << " to island " << idTo << " (tag=" << tag << ")" << std::endl;
|
||||
|
||||
// Single non-blocking send. The receiver uses MPI_Get_count
|
||||
// from MPI_Iprobe to determine the size, eliminating the
|
||||
// separate blocking size message that could deadlock.
|
||||
pendingSends.emplace_back();
|
||||
PendingSend& ps = pendingSends.back();
|
||||
ps.buffer = serialized;
|
||||
MPI_Isend(ps.buffer.data(), size, MPI_CHAR, idTo, tag,
|
||||
MPI_COMM_WORLD, &ps.request);
|
||||
}
|
||||
}
|
||||
|
||||
completePendingSends();
|
||||
}
|
||||
|
||||
template<class EOT>
|
||||
void paradiseo::smp::MPI_IslandModel<EOT>::completePendingSends() {
|
||||
auto it = pendingSends.begin();
|
||||
while (it != pendingSends.end()) {
|
||||
int completed = 0;
|
||||
MPI_Test(&it->request, &completed, MPI_STATUS_IGNORE);
|
||||
if (completed)
|
||||
it = pendingSends.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
template<class EOT>
|
||||
bool paradiseo::smp::MPI_IslandModel<EOT>::isRunning() const
|
||||
{
|
||||
return (bool)running;
|
||||
}
|
||||
|
||||
template<class EOT>
|
||||
void paradiseo::smp::MPI_IslandModel<EOT>::initModel(void)
|
||||
{
|
||||
if (num_mpi_ranks > static_cast<int>(islands.size()) + 1) {
|
||||
eo::log << eo::errors << "MPI_IslandModel: number of MPI ranks ("
|
||||
<< num_mpi_ranks << ") exceeds number of islands + 1 ("
|
||||
<< islands.size() + 1 << ")" << std::endl;
|
||||
MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
}
|
||||
|
||||
for (auto& it : islands)
|
||||
it.second = true;
|
||||
|
||||
topo.construct(islands.size());
|
||||
table = createTable();
|
||||
}
|
||||
|
||||
template<class EOT>
|
||||
Bimap<unsigned, AIsland<EOT>*> paradiseo::smp::MPI_IslandModel<EOT>::createTable()
|
||||
{
|
||||
Bimap<unsigned, AIsland<EOT>*> table;
|
||||
unsigned islandId = 0;
|
||||
for (auto it : islands) {
|
||||
table.add(islandId, it.first);
|
||||
islandId++;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
105
smp/src/MPI_IslandModel.h
Normal file
105
smp/src/MPI_IslandModel.h
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
<MPI_IslandModel.h>
|
||||
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
||||
|
||||
Alexandre Quemy, Thibault Lasnier - INSA Rouen
|
||||
Eremey Valetov
|
||||
|
||||
This software is governed by the CeCILL license under French law and
|
||||
abiding by the rules of distribution of free software. You can use,
|
||||
modify and/ or redistribute the software under the terms of the CeCILL
|
||||
license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
"http://www.cecill.info".
|
||||
|
||||
In this respect, the user's attention is drawn to the risks associated
|
||||
with loading, using, modifying and/or developing or reproducing the
|
||||
software by the user in light of its specific status of free software,
|
||||
that may mean that it is complicated to manipulate, and that also
|
||||
therefore means that it is reserved for developers and experienced
|
||||
professionals having in-depth computer knowledge. Users are therefore
|
||||
encouraged to load and test the software's suitability as regards their
|
||||
requirements in conditions enabling the security of their systems and/or
|
||||
data to be ensured and, more generally, to use and operate it in the
|
||||
same conditions as regards security.
|
||||
The fact that you are presently reading this means that you have had
|
||||
knowledge of the CeCILL license and that you accept its terms.
|
||||
|
||||
ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*/
|
||||
|
||||
#ifndef SMP_MPI_ISLAND_MODEL_H_
|
||||
#define SMP_MPI_ISLAND_MODEL_H_
|
||||
|
||||
#include <queue>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <future>
|
||||
#include <thread>
|
||||
#include <mpi.h>
|
||||
#include <sstream>
|
||||
|
||||
#include <bimap.h>
|
||||
#include <abstractIsland.h>
|
||||
#include <topology/topology.h>
|
||||
|
||||
namespace paradiseo
|
||||
{
|
||||
namespace smp
|
||||
{
|
||||
|
||||
/**
|
||||
* MPI-distributed island model.
|
||||
* Each MPI rank runs one island; migration is handled via MPI send/recv
|
||||
* using SerializableBase for population serialization.
|
||||
*
|
||||
* @see smp::Island, smp::MigPolicy
|
||||
*/
|
||||
template<class EOT>
|
||||
class MPI_IslandModel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param _topo topology defining island connectivity
|
||||
* @param _pollIntervalMs polling interval in milliseconds (default 1000)
|
||||
*/
|
||||
MPI_IslandModel(AbstractTopology& _topo, int _pollIntervalMs = 1000);
|
||||
|
||||
void add(AIsland<EOT>& _island);
|
||||
void operator()();
|
||||
bool update(eoPop<EOT> _data, AIsland<EOT>* _island);
|
||||
void setTopology(AbstractTopology& _topo);
|
||||
bool isRunning() const;
|
||||
|
||||
protected:
|
||||
void send(void);
|
||||
void initModel(void);
|
||||
Bimap<unsigned, AIsland<EOT>*> createTable();
|
||||
|
||||
// Non-blocking MPI send: buffer must stay alive until send completes
|
||||
struct PendingSend {
|
||||
MPI_Request request;
|
||||
std::string buffer;
|
||||
};
|
||||
|
||||
void completePendingSends();
|
||||
|
||||
std::queue<std::pair<eoPop<EOT>,AIsland<EOT>*>> listEmigrants;
|
||||
Bimap<unsigned, AIsland<EOT>*> table;
|
||||
std::vector<std::pair<AIsland<EOT>*, bool>> islands;
|
||||
AbstractTopology& topo;
|
||||
std::vector<std::shared_future<bool>> sentMessages;
|
||||
std::list<PendingSend> pendingSends;
|
||||
std::mutex m;
|
||||
int mpi_rank, num_mpi_ranks;
|
||||
int pollIntervalMs;
|
||||
std::atomic<bool> running;
|
||||
};
|
||||
|
||||
#include <MPI_IslandModel.cpp>
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
59
smp/src/SerializableBase.h
Normal file
59
smp/src/SerializableBase.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
<SerializableBase.h>
|
||||
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
||||
|
||||
Eremey Valetov
|
||||
|
||||
This software is governed by the CeCILL license under French law and
|
||||
abiding by the rules of distribution of free software. You can use,
|
||||
modify and/ or redistribute the software under the terms of the CeCILL
|
||||
license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
"http://www.cecill.info".
|
||||
|
||||
In this respect, the user's attention is drawn to the risks associated
|
||||
with loading, using, modifying and/or developing or reproducing the
|
||||
software by the user in light of its specific status of free software,
|
||||
that may mean that it is complicated to manipulate, and that also
|
||||
therefore means that it is reserved for developers and experienced
|
||||
professionals having in-depth computer knowledge. Users are therefore
|
||||
encouraged to load and test the software's suitability as regards their
|
||||
requirements in conditions enabling the security of their systems and/or
|
||||
data to be ensured and, more generally, to use and operate it in the
|
||||
same conditions as regards security.
|
||||
The fact that you are presently reading this means that you have had
|
||||
knowledge of the CeCILL license and that you accept its terms.
|
||||
|
||||
ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*/
|
||||
|
||||
#ifndef SERIALIZABLE_BASE_H
|
||||
#define SERIALIZABLE_BASE_H
|
||||
|
||||
#include <serial/eoSerial.h>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* Wrapper that makes any type T serializable via ParadisEO's eoserial framework.
|
||||
* Used by MPI_IslandModel to serialize/deserialize populations for inter-process transfer.
|
||||
*/
|
||||
template<class T>
|
||||
class SerializableBase : public eoserial::Persistent {
|
||||
public:
|
||||
SerializableBase();
|
||||
SerializableBase(T base);
|
||||
virtual ~SerializableBase();
|
||||
|
||||
operator T&();
|
||||
void setValue(const T& newValue);
|
||||
|
||||
void unpack(const eoserial::Object* obj) override;
|
||||
eoserial::Object* pack() const override;
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
|
||||
#include "SerializableBase.tpp"
|
||||
|
||||
#endif // SERIALIZABLE_BASE_H
|
||||
46
smp/src/SerializableBase.tpp
Normal file
46
smp/src/SerializableBase.tpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
<SerializableBase.tpp>
|
||||
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
||||
|
||||
Eremey Valetov
|
||||
|
||||
This software is governed by the CeCILL license under French law and
|
||||
abiding by the rules of distribution of free software. You can use,
|
||||
modify and/ or redistribute the software under the terms of the CeCILL
|
||||
license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
"http://www.cecill.info".
|
||||
|
||||
ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*/
|
||||
|
||||
template<class T>
|
||||
SerializableBase<T>::SerializableBase() : _value() {}
|
||||
|
||||
template<class T>
|
||||
SerializableBase<T>::SerializableBase(T base) : _value(std::move(base)) {}
|
||||
|
||||
template<class T>
|
||||
SerializableBase<T>::~SerializableBase() = default;
|
||||
|
||||
template<class T>
|
||||
SerializableBase<T>::operator T&() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SerializableBase<T>::setValue(const T& newValue) {
|
||||
_value = newValue;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SerializableBase<T>::unpack(const eoserial::Object* obj) {
|
||||
eoserial::unpack(*obj, "value", _value);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
eoserial::Object* SerializableBase<T>::pack() const {
|
||||
eoserial::Object* obj = new eoserial::Object;
|
||||
obj->add("value", eoserial::make(_value));
|
||||
return obj;
|
||||
}
|
||||
|
|
@ -40,10 +40,16 @@ namespace paradiseo
|
|||
namespace smp
|
||||
{
|
||||
|
||||
// Forward declaration
|
||||
// Forward declarations
|
||||
template<class bEOT>
|
||||
class IslandModel;
|
||||
|
||||
template<class bEOT>
|
||||
class MPI_IslandModel;
|
||||
|
||||
template<class bEOT>
|
||||
class Redis_IslandModel;
|
||||
|
||||
/** AbstractIsland: An abstract island.
|
||||
|
||||
The abstract island is used to manipulate island pointers wihout the knowledge of the algorithm.
|
||||
|
|
@ -64,6 +70,8 @@ public:
|
|||
* @param _model The model which manipulate the island.
|
||||
*/
|
||||
virtual void setModel(IslandModel<bEOT>* _model) = 0;
|
||||
virtual void setModel(MPI_IslandModel<bEOT>*) {}
|
||||
virtual void setModel(Redis_IslandModel<bEOT>*) {}
|
||||
|
||||
/**
|
||||
* Check if there is population to receive or to emigrate.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
||||
|
||||
Alexandre Quemy, Thibault Lasnier - INSA Rouen
|
||||
Eremey Valetov
|
||||
|
||||
This software is governed by the CeCILL license under French law and
|
||||
abiding by the rules of distribution of free software. You can ue,
|
||||
|
|
@ -10,167 +11,210 @@ modify and/ or redistribute the software under the terms of the CeCILL
|
|||
license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
"http://www.cecill.info".
|
||||
|
||||
In this respect, the user's attention is drawn to the risks associated
|
||||
with loading, using, modifying and/or developing or reproducing the
|
||||
software by the user in light of its specific status of free software,
|
||||
that may mean that it is complicated to manipulate, and that also
|
||||
therefore means that it is reserved for developers and experienced
|
||||
professionals having in-depth computer knowledge. Users are therefore
|
||||
encouraged to load and test the software's suitability as regards their
|
||||
requirements in conditions enabling the security of their systems and/or
|
||||
data to be ensured and, more generally, to use and operate it in the
|
||||
same conditions as regards security.
|
||||
The fact that you are presently reading this means that you have had
|
||||
knowledge of the CeCILL license and that you accept its terms.
|
||||
|
||||
ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||
Contact: paradiseo-help@lists.gforge.inria.fr
|
||||
*/
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
#include <utils/eoLogger.h>
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
template<class... Args>
|
||||
paradiseo::smp::Island<EOAlgo,EOT,bEOT>::Island(std::function<EOT(bEOT&)> _convertFromBase, std::function<bEOT(EOT&)> _convertToBase, eoPop<EOT>& _pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy, Args&... args) :
|
||||
// The PPExpander looks for the continuator in the parameters pack.
|
||||
// The private inheritance of ContWrapper wraps the continuator and add islandNotifier.
|
||||
paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::Island(
|
||||
std::function<EOT(bEOT&)> _convertFromBase, std::function<bEOT(EOT&)> _convertToBase,
|
||||
eoPop<EOT>& _pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy, Args&... args) :
|
||||
ContWrapper<EOT, bEOT>(Loop<Args...>().template findValue<eoContinue<EOT>>(args...), this),
|
||||
// We inject the wrapped continuator by tag dispatching method during the algorithm construction.
|
||||
algo(EOAlgo<EOT>(wrap_pp<eoContinue<EOT>>(this->ck,args)...)),
|
||||
// With the PPE we look for the eval function in order to evaluate EOT to integrate
|
||||
algo(EOAlgo<algoEOT>(wrap_pp<eoContinue<EOT>>(this->ck,args)...)),
|
||||
eval(Loop<Args...>().template findValue<eoEvalFunc<EOT>>(args...)),
|
||||
pop(_pop),
|
||||
intPolicy(_intPolicy),
|
||||
migPolicy(_migPolicy),
|
||||
stopped(false),
|
||||
model(nullptr),
|
||||
convertFromBase(_convertFromBase),
|
||||
convertToBase(_convertToBase)
|
||||
{
|
||||
// Check in compile time the inheritance thanks to type_trait.
|
||||
static_assert(std::is_base_of<eoAlgo<EOT>,EOAlgo<EOT>>::value, "Algorithm must inherit from eoAlgo<EOT>");
|
||||
}
|
||||
{}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
template<class... Args>
|
||||
paradiseo::smp::Island<EOAlgo,EOT,bEOT>::Island(eoPop<EOT>& _pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy, Args&... args) :
|
||||
paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::Island(
|
||||
eoPop<EOT>& _pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy, Args&... args) :
|
||||
Island(
|
||||
// Default conversion functions for homogeneous islands
|
||||
[](bEOT& i) -> EOT { return std::forward<EOT>(i); },
|
||||
[](EOT& i) -> bEOT { return std::forward<bEOT>(i); },
|
||||
_pop, _intPolicy, _migPolicy, args...)
|
||||
{ }
|
||||
{}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
paradiseo::smp::Island<EOAlgo,EOT,bEOT>::~Island()
|
||||
{ }
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
template<class... Args>
|
||||
paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::Island(
|
||||
std::function<EOT(bEOT&)> _convertFromBase, std::function<bEOT(EOT&)> _convertToBase,
|
||||
eoPop<EOT>& _pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy,
|
||||
IslandType islandType, Args&... args) :
|
||||
ContWrapper<EOT, bEOT>(Loop<Args...>().template findValue<eoContinue<EOT>>(args...), this),
|
||||
algo(EOAlgo<algoEOT>(wrap_pp<eoContinue<EOT>>(this->ck,args)...)),
|
||||
eval(Loop<Args...>().template findValue<eoEvalFunc<EOT>>(args...)),
|
||||
pop(_pop),
|
||||
intPolicy(_intPolicy),
|
||||
migPolicy(_migPolicy),
|
||||
stopped(false),
|
||||
convertFromBase(_convertFromBase),
|
||||
convertToBase(_convertToBase),
|
||||
_islandType(islandType)
|
||||
{}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::operator()()
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
template<class... Args>
|
||||
paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::Island(
|
||||
eoPop<EOT>& _pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy,
|
||||
IslandType islandType, Args&... args) :
|
||||
Island(
|
||||
[](bEOT& i) -> EOT { return std::forward<EOT>(i); },
|
||||
[](EOT& i) -> bEOT { return std::forward<bEOT>(i); },
|
||||
_pop, _intPolicy, _migPolicy, islandType, args...)
|
||||
{}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::operator()()
|
||||
{
|
||||
stopped = false;
|
||||
algo(pop);
|
||||
stopped = true;
|
||||
// Let's wait the end of communications with the island model
|
||||
for(auto& message : sentMessages)
|
||||
for (auto& message : sentMessages)
|
||||
message.wait();
|
||||
|
||||
// Clear the sentMessages container
|
||||
sentMessages.clear();
|
||||
}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::setModel(IslandModel<bEOT>* _model)
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::setModel(IslandModel<bEOT>* _model)
|
||||
{
|
||||
model = _model;
|
||||
sharedModel_ = _model;
|
||||
modelKind_ = IslandModelKind::Shared;
|
||||
}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
eoPop<EOT>& paradiseo::smp::Island<EOAlgo,EOT,bEOT>::getPop() const
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::setModel(MPI_IslandModel<bEOT>* _model)
|
||||
{
|
||||
mpiModel_ = _model;
|
||||
modelKind_ = IslandModelKind::MPI;
|
||||
}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::setModel(Redis_IslandModel<bEOT>* _model)
|
||||
{
|
||||
redisModel_ = _model;
|
||||
modelKind_ = IslandModelKind::Redis;
|
||||
}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
eoPop<EOT>& paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::getPop() const
|
||||
{
|
||||
return pop;
|
||||
}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::check()
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::check()
|
||||
{
|
||||
// Sending
|
||||
for(PolicyElement<EOT>& elem : migPolicy)
|
||||
if(!elem(pop))
|
||||
for (PolicyElement<EOT>& elem : migPolicy)
|
||||
if (!elem(pop)) {
|
||||
eo::log << eo::debug << "Island::check: migration policy triggered, sending migrants (pop size=" << pop.size() << ")" << std::endl;
|
||||
send(elem.getSelect());
|
||||
|
||||
// Receiving
|
||||
}
|
||||
receive();
|
||||
}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
bool paradiseo::smp::Island<EOAlgo,EOT,bEOT>::isStopped(void) const
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
bool paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::isStopped(void) const
|
||||
{
|
||||
return (bool)stopped;
|
||||
}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::setRunning(void)
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::setRunning(void)
|
||||
{
|
||||
stopped = false;
|
||||
}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::send(eoSelect<EOT>& _select)
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::send(eoSelect<EOT>& _select)
|
||||
{
|
||||
// Allow island to work alone
|
||||
if(model != nullptr)
|
||||
{
|
||||
eoPop<EOT> migPop;
|
||||
_select(pop, migPop);
|
||||
if (modelKind_ == IslandModelKind::None)
|
||||
return;
|
||||
|
||||
// Convert pop to base pop
|
||||
eoPop<bEOT> baseMigPop;
|
||||
for(auto& indi : migPop)
|
||||
baseMigPop.push_back(std::move(convertToBase(indi)));
|
||||
eoPop<EOT> migPop;
|
||||
_select(pop, migPop);
|
||||
eo::log << eo::debug << "Island::send: selected " << migPop.size() << " migrant(s) from pop of " << pop.size() << std::endl;
|
||||
|
||||
// Delete delivered messages
|
||||
sentMessages.erase(std::remove_if(sentMessages.begin(), sentMessages.end(),
|
||||
[&](std::shared_future<bool>& i) -> bool
|
||||
{ return i.wait_for(std::chrono::nanoseconds(0)) == std::future_status::ready; }
|
||||
),
|
||||
sentMessages.end());
|
||||
eoPop<bEOT> baseMigPop;
|
||||
for (auto& indi : migPop)
|
||||
baseMigPop.push_back(std::move(convertToBase(indi)));
|
||||
|
||||
sentMessages.push_back(std::async(std::launch::async, &IslandModel<bEOT>::update, model, std::move(baseMigPop), this));
|
||||
sentMessages.erase(std::remove_if(sentMessages.begin(), sentMessages.end(),
|
||||
[](std::shared_future<bool>& i) -> bool
|
||||
{ return i.wait_for(std::chrono::nanoseconds(0)) == std::future_status::ready; }
|
||||
),
|
||||
sentMessages.end());
|
||||
|
||||
switch (modelKind_) {
|
||||
case IslandModelKind::Shared:
|
||||
sentMessages.push_back(std::async(std::launch::async,
|
||||
&IslandModel<bEOT>::update, sharedModel_,
|
||||
std::move(baseMigPop), this));
|
||||
break;
|
||||
case IslandModelKind::MPI:
|
||||
sentMessages.push_back(std::async(std::launch::async,
|
||||
&MPI_IslandModel<bEOT>::update, mpiModel_,
|
||||
std::move(baseMigPop), this));
|
||||
break;
|
||||
case IslandModelKind::Redis:
|
||||
sentMessages.push_back(std::async(std::launch::async,
|
||||
&Redis_IslandModel<bEOT>::update, redisModel_,
|
||||
std::move(baseMigPop), this));
|
||||
break;
|
||||
case IslandModelKind::None:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::receive(void)
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::receive(void)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(this->m);
|
||||
while (!listImigrants.empty())
|
||||
{
|
||||
eoPop<bEOT> base_offspring = std::move(listImigrants.front());
|
||||
|
||||
// Convert objects from base to our objects type
|
||||
while (!listImigrants.empty()) {
|
||||
eoPop<bEOT> base_offspring = std::move(listImigrants.front());
|
||||
eo::log << eo::debug << "Island::receive: integrating " << base_offspring.size()
|
||||
<< " immigrant(s) into pop of " << pop.size() << std::endl;
|
||||
|
||||
eoPop<EOT> offspring;
|
||||
for(auto& indi : base_offspring)
|
||||
for (auto& indi : base_offspring)
|
||||
offspring.push_back(std::move(convertFromBase(indi)));
|
||||
|
||||
// Evaluate objects to integrate
|
||||
// We first invalidate the individuals in order to explicitly force the evaluation
|
||||
for(auto& indi : offspring)
|
||||
{
|
||||
indi.invalidate();
|
||||
eval(indi);
|
||||
// Re-evaluate immigrants for heterogeneous islands
|
||||
if (_islandType == HETEROGENEOUS_ISLAND) {
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (size_t i = 0; i < offspring.size(); ++i) {
|
||||
offspring[i].invalidate();
|
||||
eval(offspring[i]);
|
||||
}
|
||||
}
|
||||
|
||||
intPolicy(pop, offspring);
|
||||
listImigrants.pop();
|
||||
|
||||
if (algo.hasFinalize())
|
||||
algo.finalize(pop);
|
||||
|
||||
listImigrants.pop();
|
||||
}
|
||||
}
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
||||
bool paradiseo::smp::Island<EOAlgo,EOT,bEOT>::update(eoPop<bEOT> _data)
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||
bool paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::update(eoPop<bEOT> _data)
|
||||
{
|
||||
//std::cout << "On update dans l'île" << std::endl;
|
||||
std::lock_guard<std::mutex> lock(this->m);
|
||||
listImigrants.push(_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
||||
|
||||
Alexandre Quemy, Thibault Lasnier - INSA Rouen
|
||||
Eremey Valetov
|
||||
|
||||
This software is governed by the CeCILL license under French law and
|
||||
abiding by the rules of distribution of free software. You can ue,
|
||||
|
|
@ -51,24 +52,35 @@ Contact: paradiseo-help@lists.gforge.inria.fr
|
|||
#include <contWrapper.h>
|
||||
#include <contDispatching.h>
|
||||
|
||||
#include <MPI_IslandModel.h>
|
||||
|
||||
namespace paradiseo
|
||||
{
|
||||
namespace smp
|
||||
{
|
||||
|
||||
enum IslandType {
|
||||
HOMOGENEOUS_ISLAND,
|
||||
HETEROGENEOUS_ISLAND,
|
||||
DEFAULT = HETEROGENEOUS_ISLAND
|
||||
};
|
||||
|
||||
/** Island: Concrete island that wraps an algorithm
|
||||
|
||||
The island wraps an algorithm and provide mecanisms for emigration and integration of populations.
|
||||
An island also have a base type which represents the type of individuals of the Island Model.
|
||||
The optional algoEOT template parameter allows the algorithm to operate on a different
|
||||
type than the island's EOT (useful when the algorithm's MOEOT differs from the base type).
|
||||
|
||||
@see smp::AbstractIsland, smp::MigPolicy
|
||||
*/
|
||||
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT = EOT>
|
||||
template<template <class> class EOAlgo, class EOT, class bEOT = EOT, class algoEOT = EOT>
|
||||
class Island : private ContWrapper<EOT, bEOT>, public AIsland<bEOT>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* Constructor with type converters
|
||||
* @param _convertFromBase Function to convert EOT from base EOT
|
||||
* @param _convertToBase Function to convert base EOT to EOT
|
||||
* @param _pop Population of the island
|
||||
|
|
@ -77,73 +89,47 @@ public:
|
|||
* @param args Parameters to construct the algorithm.
|
||||
*/
|
||||
template<class... Args>
|
||||
Island(std::function<EOT(bEOT&)> _convertFromBase, std::function<bEOT(EOT&)> _convertToBase, eoPop<EOT>& pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy, Args&... args);
|
||||
Island(std::function<EOT(bEOT&)> _convertFromBase, std::function<bEOT(EOT&)> _convertToBase,
|
||||
eoPop<EOT>& pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy, Args&... args);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param _pop Population of the island
|
||||
* @param _intPolicy Integration policy
|
||||
* @param _migPolicy Migration policy
|
||||
* @param args Parameters to construct the algorithm.
|
||||
* Constructor for homogeneous islands (bEOT == EOT)
|
||||
*/
|
||||
template<class... Args>
|
||||
Island(eoPop<EOT>& pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy, Args&... args);
|
||||
|
||||
/**
|
||||
* Start the island.
|
||||
* Constructor with type converters and island type
|
||||
*/
|
||||
template<class... Args>
|
||||
Island(std::function<EOT(bEOT&)> _convertFromBase, std::function<bEOT(EOT&)> _convertToBase,
|
||||
eoPop<EOT>& pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy,
|
||||
IslandType islandType, Args&... args);
|
||||
|
||||
/**
|
||||
* Constructor with island type
|
||||
*/
|
||||
template<class... Args>
|
||||
Island(eoPop<EOT>& pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy,
|
||||
IslandType islandType, Args&... args);
|
||||
|
||||
void operator()(void);
|
||||
|
||||
/**
|
||||
* Set model
|
||||
* @param _model Pointer to the Island Model corresponding
|
||||
*/
|
||||
virtual void setModel(IslandModel<bEOT>* _model);
|
||||
virtual void setModel(MPI_IslandModel<bEOT>* _model);
|
||||
virtual void setModel(Redis_IslandModel<bEOT>* _model);
|
||||
|
||||
/**
|
||||
* Return a reference to the island population.
|
||||
* @return Reference to the island population
|
||||
*/
|
||||
eoPop<EOT>& getPop() const;
|
||||
|
||||
/**
|
||||
* Check if there is population to receive or to migrate
|
||||
*/
|
||||
virtual void check(void);
|
||||
|
||||
/**
|
||||
* Update the list of imigrants.
|
||||
* @param _data Elements to integrate in the main population.
|
||||
*/
|
||||
bool update(eoPop<bEOT> _data);
|
||||
|
||||
/**
|
||||
* Check if the algorithm is stopped.
|
||||
* @return true if stopped
|
||||
*/
|
||||
virtual bool isStopped(void) const;
|
||||
|
||||
/**
|
||||
* Set the stopped indicator on false
|
||||
*/
|
||||
virtual void setRunning(void);
|
||||
|
||||
/**
|
||||
* Check if there is population to receive
|
||||
*/
|
||||
virtual void receive(void);
|
||||
|
||||
//AIsland<bEOT> clone() const;
|
||||
|
||||
virtual ~Island();
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Send population to mediator
|
||||
* @param _select Method to select EOT to send
|
||||
*/
|
||||
virtual void send(eoSelect<EOT>& _select);
|
||||
|
||||
EOAlgo<EOT> algo;
|
||||
EOAlgo<algoEOT> algo;
|
||||
eoEvalFunc<EOT>& eval;
|
||||
eoPop<EOT>& pop;
|
||||
std::queue<eoPop<bEOT>> listImigrants;
|
||||
|
|
@ -151,9 +137,16 @@ protected:
|
|||
MigPolicy<EOT>& migPolicy;
|
||||
std::atomic<bool> stopped;
|
||||
std::vector<std::shared_future<bool>> sentMessages;
|
||||
IslandModel<bEOT>* model;
|
||||
|
||||
enum class IslandModelKind { None, Shared, MPI, Redis };
|
||||
IslandModelKind modelKind_ = IslandModelKind::None;
|
||||
IslandModel<bEOT>* sharedModel_ = nullptr;
|
||||
MPI_IslandModel<bEOT>* mpiModel_ = nullptr;
|
||||
Redis_IslandModel<bEOT>* redisModel_ = nullptr;
|
||||
|
||||
std::function<EOT(bEOT&)> convertFromBase;
|
||||
std::function<bEOT(EOT&)> convertToBase;
|
||||
IslandType _islandType = DEFAULT;
|
||||
};
|
||||
|
||||
#include <island.cpp>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
||||
|
||||
Alexandre Quemy, Thibault Lasnier - INSA Rouen
|
||||
Eremey Valetov
|
||||
|
||||
This software is governed by the CeCILL license under French law and
|
||||
abiding by the rules of distribution of free software. You can ue,
|
||||
|
|
@ -36,6 +37,7 @@ Contact: paradiseo-help@lists.gforge.inria.fr
|
|||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
#include <bimap.h>
|
||||
#include <abstractIsland.h>
|
||||
|
|
@ -55,36 +57,132 @@ of specified islands, built with same parameters.
|
|||
@see smp::IslandModel
|
||||
*/
|
||||
|
||||
// Original overload: uses IslandModel (shared-memory)
|
||||
template<template <class> class EOAlgo, class EOT, class... IslandInit>
|
||||
std::vector<eoPop<EOT>> IslandModelWrapper(unsigned _islandNumber, AbstractTopology& _topo, unsigned _popSize, eoInit<EOT> &_chromInit, IslandInit&&... args)
|
||||
{
|
||||
// Model creation
|
||||
IslandModel<EOT> model(_topo);
|
||||
|
||||
// Island and pop containers
|
||||
std::vector<Island<EOAlgo,EOT>*> islands(_islandNumber);
|
||||
std::vector<eoPop<EOT>> pops(_islandNumber);
|
||||
|
||||
// Generate islands and put them in the model
|
||||
for(unsigned i = 0; i < _islandNumber; i++)
|
||||
{
|
||||
for (unsigned i = 0; i < _islandNumber; i++) {
|
||||
pops[i] = eoPop<EOT>(_popSize, _chromInit);
|
||||
islands[i] = new Island<EOAlgo, EOT>(pops[i], args...);
|
||||
model.add(*islands[i]);
|
||||
}
|
||||
|
||||
// Start the model
|
||||
model();
|
||||
|
||||
// Delete islands
|
||||
for(auto& island : islands)
|
||||
for (auto& island : islands)
|
||||
delete island;
|
||||
|
||||
return pops;
|
||||
}
|
||||
|
||||
// Overload with configurable IslandModelType template parameter
|
||||
template<template <class> class EOAlgo, class EOT, template <class> class IslandModelType, class... IslandInit>
|
||||
std::vector<eoPop<EOT>> IslandModelWrapper(unsigned _islands, AbstractTopology& _topo, unsigned _popSize, eoInit<EOT> &_chromInit, IslandInit&&... args)
|
||||
{
|
||||
IslandModelType<EOT> model(_topo);
|
||||
|
||||
std::vector<Island<EOAlgo,EOT>*> islands(_islands);
|
||||
std::vector<eoPop<EOT>> pops(_islands);
|
||||
|
||||
for (unsigned i = 0; i < _islands; i++) {
|
||||
pops[i] = eoPop<EOT>(_popSize, _chromInit);
|
||||
islands[i] = new Island<EOAlgo, EOT>(pops[i], std::forward<IslandInit>(args)...);
|
||||
model.add(*islands[i]);
|
||||
}
|
||||
|
||||
model();
|
||||
|
||||
for (auto& island : islands)
|
||||
delete island;
|
||||
|
||||
return pops;
|
||||
}
|
||||
|
||||
// Overload with initial_values for seeding populations
|
||||
template<template <class> class EOAlgo, class EOT, template <class> class IslandModelType, class... IslandInit>
|
||||
std::vector<eoPop<EOT>> IslandModelWrapper(unsigned _islands, AbstractTopology& _topo, unsigned _popSize, const std::vector<std::vector<double>> &initial_values, eoInit<EOT> &_chromInit, IslandInit&&... args)
|
||||
{
|
||||
IslandModelType<EOT> model(_topo);
|
||||
|
||||
std::vector<Island<EOAlgo,EOT>*> islands(_islands);
|
||||
std::vector<eoPop<EOT>> pops(_islands);
|
||||
|
||||
for (unsigned i = 0; i < _islands; i++) {
|
||||
pops[i] = eoPop<EOT>(_popSize, _chromInit);
|
||||
for (size_t j = 0; j < initial_values.size() && j < pops[i].size(); j++) {
|
||||
assert(initial_values[j].size() == pops[i][j].size());
|
||||
for (size_t k = 0; k < initial_values[j].size(); k++)
|
||||
pops[i][j][k] = initial_values[j][k];
|
||||
}
|
||||
islands[i] = new Island<EOAlgo, EOT>(pops[i], std::forward<IslandInit>(args)...);
|
||||
model.add(*islands[i]);
|
||||
}
|
||||
|
||||
model();
|
||||
|
||||
for (auto& island : islands)
|
||||
delete island;
|
||||
|
||||
return pops;
|
||||
}
|
||||
|
||||
// Overload with algoEOT template parameter (for algorithms operating on a different type)
|
||||
template<template <class> class EOAlgo, class EOT, class algoEOT, template <class> class IslandModelType, class... IslandInit>
|
||||
std::vector<eoPop<EOT>> IslandModelWrapper(unsigned _islands, AbstractTopology& _topo, unsigned _popSize, eoInit<EOT> &_chromInit, IslandInit&&... args)
|
||||
{
|
||||
IslandModelType<EOT> model(_topo);
|
||||
|
||||
std::vector<Island<EOAlgo,EOT,EOT,algoEOT>*> islands(_islands);
|
||||
std::vector<eoPop<EOT>> pops(_islands);
|
||||
|
||||
for (unsigned i = 0; i < _islands; i++) {
|
||||
pops[i] = eoPop<EOT>(_popSize, _chromInit);
|
||||
islands[i] = new Island<EOAlgo, EOT, EOT, algoEOT>(pops[i], std::forward<IslandInit>(args)...);
|
||||
model.add(*islands[i]);
|
||||
}
|
||||
|
||||
model();
|
||||
|
||||
for (auto& island : islands)
|
||||
delete island;
|
||||
|
||||
return pops;
|
||||
}
|
||||
|
||||
// Overload with algoEOT and initial_values
|
||||
template<template <class> class EOAlgo, class EOT, class algoEOT, template <class> class IslandModelType, class... IslandInit>
|
||||
std::vector<eoPop<EOT>> IslandModelWrapper(unsigned _islands, AbstractTopology& _topo, unsigned _popSize, const std::vector<std::vector<double>> &initial_values, eoInit<EOT> &_chromInit, IslandInit&&... args)
|
||||
{
|
||||
IslandModelType<EOT> model(_topo);
|
||||
|
||||
std::vector<Island<EOAlgo,EOT,EOT,algoEOT>*> islands(_islands);
|
||||
std::vector<eoPop<EOT>> pops(_islands);
|
||||
|
||||
for (unsigned i = 0; i < _islands; i++) {
|
||||
pops[i] = eoPop<EOT>(_popSize, _chromInit);
|
||||
for (size_t j = 0; j < initial_values.size() && j < pops[i].size(); j++) {
|
||||
assert(initial_values[j].size() == pops[i][j].size());
|
||||
for (size_t k = 0; k < initial_values[j].size(); k++)
|
||||
pops[i][j][k] = initial_values[j][k];
|
||||
}
|
||||
islands[i] = new Island<EOAlgo, EOT, EOT, algoEOT>(pops[i], std::forward<IslandInit>(args)...);
|
||||
model.add(*islands[i]);
|
||||
}
|
||||
|
||||
model();
|
||||
|
||||
for (auto& island : islands)
|
||||
delete island;
|
||||
|
||||
return pops;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ Contact: paradiseo-help@lists.gforge.inria.fr
|
|||
|
||||
#include <MWModel.h>
|
||||
#include <scheduler.h>
|
||||
#include <SerializableBase.h>
|
||||
#include <islandModel.h>
|
||||
#include <MPI_IslandModel.h>
|
||||
#include <islandModelWrapper.h>
|
||||
#include <island.h>
|
||||
#include <abstractIsland.h>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue