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.
|
* Abstract class for multi-objective algorithms.
|
||||||
*/
|
*/
|
||||||
class moeoAlgo
|
class moeoAlgo
|
||||||
{};
|
{
|
||||||
|
public:
|
||||||
|
virtual ~moeoAlgo() = default;
|
||||||
|
|
||||||
|
/** Whether this algorithm supports finalize() for post-integration updates. */
|
||||||
|
virtual bool hasFinalize() const { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
#endif /*MOEOALGO_H_*/
|
#endif /*MOEOALGO_H_*/
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,17 @@ public:
|
||||||
while (continuator (_pop));
|
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:
|
protected:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,14 @@
|
||||||
*/
|
*/
|
||||||
template < class MOEOT >
|
template < class MOEOT >
|
||||||
class moeoPopAlgo : public moeoAlgo, public eoAlgo < 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_*/
|
#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
|
namespace smp
|
||||||
{
|
{
|
||||||
|
|
||||||
// Forward declaration
|
// Forward declarations
|
||||||
template<class bEOT>
|
template<class bEOT>
|
||||||
class IslandModel;
|
class IslandModel;
|
||||||
|
|
||||||
|
template<class bEOT>
|
||||||
|
class MPI_IslandModel;
|
||||||
|
|
||||||
|
template<class bEOT>
|
||||||
|
class Redis_IslandModel;
|
||||||
|
|
||||||
/** AbstractIsland: An abstract island.
|
/** AbstractIsland: An abstract island.
|
||||||
|
|
||||||
The abstract island is used to manipulate island pointers wihout the knowledge of the algorithm.
|
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.
|
* @param _model The model which manipulate the island.
|
||||||
*/
|
*/
|
||||||
virtual void setModel(IslandModel<bEOT>* _model) = 0;
|
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.
|
* 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
|
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
||||||
|
|
||||||
Alexandre Quemy, Thibault Lasnier - INSA Rouen
|
Alexandre Quemy, Thibault Lasnier - INSA Rouen
|
||||||
|
Eremey Valetov
|
||||||
|
|
||||||
This software is governed by the CeCILL license under French law and
|
This software is governed by the CeCILL license under French law and
|
||||||
abiding by the rules of distribution of free software. You can ue,
|
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
|
license as circulated by CEA, CNRS and INRIA at the following URL
|
||||||
"http://www.cecill.info".
|
"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
|
ParadisEO WebSite : http://paradiseo.gforge.inria.fr
|
||||||
Contact: paradiseo-help@lists.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>
|
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) :
|
paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::Island(
|
||||||
// The PPExpander looks for the continuator in the parameters pack.
|
std::function<EOT(bEOT&)> _convertFromBase, std::function<bEOT(EOT&)> _convertToBase,
|
||||||
// The private inheritance of ContWrapper wraps the continuator and add islandNotifier.
|
eoPop<EOT>& _pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy, Args&... args) :
|
||||||
ContWrapper<EOT, bEOT>(Loop<Args...>().template findValue<eoContinue<EOT>>(args...), this),
|
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<algoEOT>(wrap_pp<eoContinue<EOT>>(this->ck,args)...)),
|
||||||
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
|
|
||||||
eval(Loop<Args...>().template findValue<eoEvalFunc<EOT>>(args...)),
|
eval(Loop<Args...>().template findValue<eoEvalFunc<EOT>>(args...)),
|
||||||
pop(_pop),
|
pop(_pop),
|
||||||
intPolicy(_intPolicy),
|
intPolicy(_intPolicy),
|
||||||
migPolicy(_migPolicy),
|
migPolicy(_migPolicy),
|
||||||
stopped(false),
|
stopped(false),
|
||||||
model(nullptr),
|
|
||||||
convertFromBase(_convertFromBase),
|
convertFromBase(_convertFromBase),
|
||||||
convertToBase(_convertToBase)
|
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>
|
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(
|
Island(
|
||||||
// Default conversion functions for homogeneous islands
|
|
||||||
[](bEOT& i) -> EOT { return std::forward<EOT>(i); },
|
[](bEOT& i) -> EOT { return std::forward<EOT>(i); },
|
||||||
[](EOT& i) -> bEOT { return std::forward<bEOT>(i); },
|
[](EOT& i) -> bEOT { return std::forward<bEOT>(i); },
|
||||||
_pop, _intPolicy, _migPolicy, args...)
|
_pop, _intPolicy, _migPolicy, args...)
|
||||||
{ }
|
{}
|
||||||
|
|
||||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||||
paradiseo::smp::Island<EOAlgo,EOT,bEOT>::~Island()
|
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>
|
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::operator()()
|
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;
|
stopped = false;
|
||||||
algo(pop);
|
algo(pop);
|
||||||
stopped = true;
|
stopped = true;
|
||||||
// Let's wait the end of communications with the island model
|
for (auto& message : sentMessages)
|
||||||
for(auto& message : sentMessages)
|
|
||||||
message.wait();
|
message.wait();
|
||||||
|
|
||||||
// Clear the sentMessages container
|
|
||||||
sentMessages.clear();
|
sentMessages.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::setModel(IslandModel<bEOT>* _model)
|
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>
|
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||||
eoPop<EOT>& paradiseo::smp::Island<EOAlgo,EOT,bEOT>::getPop() const
|
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;
|
return pop;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::check()
|
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::check()
|
||||||
{
|
{
|
||||||
// Sending
|
for (PolicyElement<EOT>& elem : migPolicy)
|
||||||
for(PolicyElement<EOT>& elem : migPolicy)
|
if (!elem(pop)) {
|
||||||
if(!elem(pop))
|
eo::log << eo::debug << "Island::check: migration policy triggered, sending migrants (pop size=" << pop.size() << ")" << std::endl;
|
||||||
send(elem.getSelect());
|
send(elem.getSelect());
|
||||||
|
}
|
||||||
// Receiving
|
|
||||||
receive();
|
receive();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||||
bool paradiseo::smp::Island<EOAlgo,EOT,bEOT>::isStopped(void) const
|
bool paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::isStopped(void) const
|
||||||
{
|
{
|
||||||
return (bool)stopped;
|
return (bool)stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::setRunning(void)
|
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::setRunning(void)
|
||||||
{
|
{
|
||||||
stopped = false;
|
stopped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::send(eoSelect<EOT>& _select)
|
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::send(eoSelect<EOT>& _select)
|
||||||
{
|
{
|
||||||
// Allow island to work alone
|
if (modelKind_ == IslandModelKind::None)
|
||||||
if(model != nullptr)
|
return;
|
||||||
{
|
|
||||||
eoPop<EOT> migPop;
|
|
||||||
_select(pop, migPop);
|
|
||||||
|
|
||||||
// Convert pop to base pop
|
eoPop<EOT> migPop;
|
||||||
eoPop<bEOT> baseMigPop;
|
_select(pop, migPop);
|
||||||
for(auto& indi : migPop)
|
eo::log << eo::debug << "Island::send: selected " << migPop.size() << " migrant(s) from pop of " << pop.size() << std::endl;
|
||||||
baseMigPop.push_back(std::move(convertToBase(indi)));
|
|
||||||
|
|
||||||
// Delete delivered messages
|
eoPop<bEOT> baseMigPop;
|
||||||
sentMessages.erase(std::remove_if(sentMessages.begin(), sentMessages.end(),
|
for (auto& indi : migPop)
|
||||||
[&](std::shared_future<bool>& i) -> bool
|
baseMigPop.push_back(std::move(convertToBase(indi)));
|
||||||
{ return i.wait_for(std::chrono::nanoseconds(0)) == std::future_status::ready; }
|
|
||||||
),
|
|
||||||
sentMessages.end());
|
|
||||||
|
|
||||||
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>
|
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||||
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::receive(void)
|
void paradiseo::smp::Island<EOAlgo,EOT,bEOT,algoEOT>::receive(void)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(this->m);
|
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;
|
eoPop<EOT> offspring;
|
||||||
for(auto& indi : base_offspring)
|
for (auto& indi : base_offspring)
|
||||||
offspring.push_back(std::move(convertFromBase(indi)));
|
offspring.push_back(std::move(convertFromBase(indi)));
|
||||||
|
|
||||||
// Evaluate objects to integrate
|
// Re-evaluate immigrants for heterogeneous islands
|
||||||
// We first invalidate the individuals in order to explicitly force the evaluation
|
if (_islandType == HETEROGENEOUS_ISLAND) {
|
||||||
for(auto& indi : offspring)
|
#ifdef _OPENMP
|
||||||
{
|
#pragma omp parallel for
|
||||||
indi.invalidate();
|
#endif
|
||||||
eval(indi);
|
for (size_t i = 0; i < offspring.size(); ++i) {
|
||||||
|
offspring[i].invalidate();
|
||||||
|
eval(offspring[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
intPolicy(pop, offspring);
|
intPolicy(pop, offspring);
|
||||||
listImigrants.pop();
|
|
||||||
|
|
||||||
|
if (algo.hasFinalize())
|
||||||
|
algo.finalize(pop);
|
||||||
|
|
||||||
|
listImigrants.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<template <class> class EOAlgo, class EOT, class bEOT>
|
template<template <class> class EOAlgo, class EOT, class bEOT, class algoEOT>
|
||||||
bool paradiseo::smp::Island<EOAlgo,EOT,bEOT>::update(eoPop<bEOT> _data)
|
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);
|
std::lock_guard<std::mutex> lock(this->m);
|
||||||
listImigrants.push(_data);
|
listImigrants.push(_data);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
||||||
|
|
||||||
Alexandre Quemy, Thibault Lasnier - INSA Rouen
|
Alexandre Quemy, Thibault Lasnier - INSA Rouen
|
||||||
|
Eremey Valetov
|
||||||
|
|
||||||
This software is governed by the CeCILL license under French law and
|
This software is governed by the CeCILL license under French law and
|
||||||
abiding by the rules of distribution of free software. You can ue,
|
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 <contWrapper.h>
|
||||||
#include <contDispatching.h>
|
#include <contDispatching.h>
|
||||||
|
|
||||||
|
#include <MPI_IslandModel.h>
|
||||||
|
|
||||||
namespace paradiseo
|
namespace paradiseo
|
||||||
{
|
{
|
||||||
namespace smp
|
namespace smp
|
||||||
{
|
{
|
||||||
|
|
||||||
|
enum IslandType {
|
||||||
|
HOMOGENEOUS_ISLAND,
|
||||||
|
HETEROGENEOUS_ISLAND,
|
||||||
|
DEFAULT = HETEROGENEOUS_ISLAND
|
||||||
|
};
|
||||||
|
|
||||||
/** Island: Concrete island that wraps an algorithm
|
/** Island: Concrete island that wraps an algorithm
|
||||||
|
|
||||||
The island wraps an algorithm and provide mecanisms for emigration and integration of populations.
|
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.
|
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
|
@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>
|
class Island : private ContWrapper<EOT, bEOT>, public AIsland<bEOT>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor with type converters
|
||||||
* @param _convertFromBase Function to convert EOT from base EOT
|
* @param _convertFromBase Function to convert EOT from base EOT
|
||||||
* @param _convertToBase Function to convert base EOT to EOT
|
* @param _convertToBase Function to convert base EOT to EOT
|
||||||
* @param _pop Population of the island
|
* @param _pop Population of the island
|
||||||
|
|
@ -77,73 +89,47 @@ public:
|
||||||
* @param args Parameters to construct the algorithm.
|
* @param args Parameters to construct the algorithm.
|
||||||
*/
|
*/
|
||||||
template<class... Args>
|
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
|
* Constructor for homogeneous islands (bEOT == EOT)
|
||||||
* @param _pop Population of the island
|
|
||||||
* @param _intPolicy Integration policy
|
|
||||||
* @param _migPolicy Migration policy
|
|
||||||
* @param args Parameters to construct the algorithm.
|
|
||||||
*/
|
*/
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
Island(eoPop<EOT>& pop, IntPolicy<EOT>& _intPolicy, MigPolicy<EOT>& _migPolicy, Args&... 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);
|
void operator()(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* Set model
|
|
||||||
* @param _model Pointer to the Island Model corresponding
|
|
||||||
*/
|
|
||||||
virtual void setModel(IslandModel<bEOT>* _model);
|
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;
|
eoPop<EOT>& getPop() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if there is population to receive or to migrate
|
|
||||||
*/
|
|
||||||
virtual void check(void);
|
virtual void check(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the list of imigrants.
|
|
||||||
* @param _data Elements to integrate in the main population.
|
|
||||||
*/
|
|
||||||
bool update(eoPop<bEOT> _data);
|
bool update(eoPop<bEOT> _data);
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the algorithm is stopped.
|
|
||||||
* @return true if stopped
|
|
||||||
*/
|
|
||||||
virtual bool isStopped(void) const;
|
virtual bool isStopped(void) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the stopped indicator on false
|
|
||||||
*/
|
|
||||||
virtual void setRunning(void);
|
virtual void setRunning(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if there is population to receive
|
|
||||||
*/
|
|
||||||
virtual void receive(void);
|
virtual void receive(void);
|
||||||
|
|
||||||
//AIsland<bEOT> clone() const;
|
|
||||||
|
|
||||||
virtual ~Island();
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
|
||||||
* Send population to mediator
|
|
||||||
* @param _select Method to select EOT to send
|
|
||||||
*/
|
|
||||||
virtual void send(eoSelect<EOT>& _select);
|
virtual void send(eoSelect<EOT>& _select);
|
||||||
|
|
||||||
EOAlgo<EOT> algo;
|
EOAlgo<algoEOT> algo;
|
||||||
eoEvalFunc<EOT>& eval;
|
eoEvalFunc<EOT>& eval;
|
||||||
eoPop<EOT>& pop;
|
eoPop<EOT>& pop;
|
||||||
std::queue<eoPop<bEOT>> listImigrants;
|
std::queue<eoPop<bEOT>> listImigrants;
|
||||||
|
|
@ -151,9 +137,16 @@ protected:
|
||||||
MigPolicy<EOT>& migPolicy;
|
MigPolicy<EOT>& migPolicy;
|
||||||
std::atomic<bool> stopped;
|
std::atomic<bool> stopped;
|
||||||
std::vector<std::shared_future<bool>> sentMessages;
|
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<EOT(bEOT&)> convertFromBase;
|
||||||
std::function<bEOT(EOT&)> convertToBase;
|
std::function<bEOT(EOT&)> convertToBase;
|
||||||
|
IslandType _islandType = DEFAULT;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <island.cpp>
|
#include <island.cpp>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2012
|
||||||
|
|
||||||
Alexandre Quemy, Thibault Lasnier - INSA Rouen
|
Alexandre Quemy, Thibault Lasnier - INSA Rouen
|
||||||
|
Eremey Valetov
|
||||||
|
|
||||||
This software is governed by the CeCILL license under French law and
|
This software is governed by the CeCILL license under French law and
|
||||||
abiding by the rules of distribution of free software. You can ue,
|
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 <thread>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#include <bimap.h>
|
#include <bimap.h>
|
||||||
#include <abstractIsland.h>
|
#include <abstractIsland.h>
|
||||||
|
|
@ -55,36 +57,132 @@ of specified islands, built with same parameters.
|
||||||
@see smp::IslandModel
|
@see smp::IslandModel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Original overload: uses IslandModel (shared-memory)
|
||||||
template<template <class> class EOAlgo, class EOT, class... IslandInit>
|
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)
|
std::vector<eoPop<EOT>> IslandModelWrapper(unsigned _islandNumber, AbstractTopology& _topo, unsigned _popSize, eoInit<EOT> &_chromInit, IslandInit&&... args)
|
||||||
{
|
{
|
||||||
// Model creation
|
|
||||||
IslandModel<EOT> model(_topo);
|
IslandModel<EOT> model(_topo);
|
||||||
|
|
||||||
// Island and pop containers
|
|
||||||
std::vector<Island<EOAlgo,EOT>*> islands(_islandNumber);
|
std::vector<Island<EOAlgo,EOT>*> islands(_islandNumber);
|
||||||
std::vector<eoPop<EOT>> pops(_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);
|
pops[i] = eoPop<EOT>(_popSize, _chromInit);
|
||||||
islands[i] = new Island<EOAlgo, EOT>(pops[i], args...);
|
islands[i] = new Island<EOAlgo, EOT>(pops[i], args...);
|
||||||
model.add(*islands[i]);
|
model.add(*islands[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the model
|
|
||||||
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;
|
delete island;
|
||||||
|
|
||||||
return pops;
|
return pops;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,9 @@ Contact: paradiseo-help@lists.gforge.inria.fr
|
||||||
|
|
||||||
#include <MWModel.h>
|
#include <MWModel.h>
|
||||||
#include <scheduler.h>
|
#include <scheduler.h>
|
||||||
|
#include <SerializableBase.h>
|
||||||
#include <islandModel.h>
|
#include <islandModel.h>
|
||||||
|
#include <MPI_IslandModel.h>
|
||||||
#include <islandModelWrapper.h>
|
#include <islandModelWrapper.h>
|
||||||
#include <island.h>
|
#include <island.h>
|
||||||
#include <abstractIsland.h>
|
#include <abstractIsland.h>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue