-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Expose the remote cross-simulator coupling to python.
- Loading branch information
1 parent
689eea3
commit b573830
Showing
9 changed files
with
274 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
.. _cppremote: | ||
|
||
Remote Communication | ||
#################### | ||
|
||
Wraps remote communication for Arbor. This is meant to facilitate sending data | ||
_to_ Arbor, not for pulling data into Arbor from the outside, which is done | ||
automatically. If you are developing a bridge between Arbor and another | ||
simulator that supports calling C++, this is the correct place. In all other | ||
cases it is likely not what you are looking for. For a description of the | ||
protocol see :ref:`here <interconnectivity>` | ||
|
||
.. cpp:namespace:: arb::remote | ||
|
||
Control Messages | ||
================ | ||
|
||
.. cpp:class:: msg_null | ||
|
||
Empty message, possibly used as a keep-alive signal. | ||
|
||
|
||
.. cpp:class:: msg_abort | ||
|
||
Request termination, giving the reason as a message. | ||
|
||
.. cpp:member:: char[512] reason | ||
|
||
.. cpp:class:: msg_epoch | ||
|
||
Commence next epoch, giving the open interval :math:`[from, to)` with times | ||
in `ms`. | ||
|
||
.. cpp:member:: double t_start | ||
|
||
.. cpp:member:: double t_end | ||
|
||
.. cpp:class:: msg_done | ||
|
||
Conclude simulation, giving the final time :math:`t_{\mathrm{final}}` in `ms`. | ||
|
||
.. cpp:member:: double time | ||
|
||
.. cpp:type:: ctrl_message = std::variant<msg_null, msg_abort, msg_epoch, msg_done> | ||
|
||
.. function:: exchange_ctrl(ctrl_message message, MPI_Comm comm) | ||
|
||
Send ``message`` to all peers in the MPI intercomm ``comm`` and receive the | ||
unanimous answer. ``message`` must be one of the types ``msg_*`` above. | ||
|
||
Spike Exchange | ||
============== | ||
|
||
.. cpp:class:: arb_spike | ||
|
||
.. cpp:member:: uint32_t gid | ||
|
||
Global id of the spiking cell, must fit in an unsigned 32b integer. | ||
``gid`` must be unique in the external network. | ||
|
||
.. cpp:member:: uint32_t lid | ||
|
||
Local id on the spiking cell, must fit in an unsigned 32b integer. This | ||
``lid`` describes which logical part of the cell ``gid`` emitted the | ||
spike. If the external simulation doesn't distinguish betwenn different | ||
sources on the same cell, always set this to zero. | ||
|
||
.. cpp:member:: double time | ||
|
||
Time at which the occured. | ||
|
||
.. function:: gather_spikes(const std::vector<arb_spike>& spikes, MPI_Comm comm) | ||
|
||
Sends a buffer of spikes over ``comm`` receiving back the concatenated | ||
result of all calling MPI tasks in Arbor. This is a collective | ||
operation; each MPI task on the remote side must call it simultaneously | ||
with its _local_ part of the spikes to send. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
.. _pyremote: | ||
|
||
Remote Communication | ||
#################### | ||
|
||
Wraps remote communication for Arbor. This is meant to facilitate sending data | ||
_to_ Arbor, not for pulling data into Arbor from the outside, which is done | ||
automatically. If you are developing a bridge between Arbor and another | ||
simulator that is written in pure Python, this is the correct place. In all | ||
other cases it is likely not what you are looking for. For a description of the | ||
protocol see | ||
|
||
.. currentmodule:: arbor | ||
|
||
Control Messages | ||
================ | ||
|
||
.. class:: msg_null | ||
|
||
Empty message, possibly used as a keep-alive signal. | ||
|
||
.. function:: msg_null() | ||
|
||
.. class:: msg_abort | ||
|
||
Request termination, giving the reason as a message (< 512 bytes) | ||
|
||
.. function:: msg_abort(reason) | ||
|
||
.. class:: msg_epoch | ||
|
||
Commence next epoch, giving the open interval :math:`[from, to)` with times | ||
in `ms`. | ||
|
||
.. function:: msg_epoch(from, to) | ||
|
||
.. class:: msg_done | ||
|
||
Conclude simulation, giving the final time :math:`t_{\mathrm{final}}` in `ms`. | ||
|
||
.. function:: msg_done(tfinal) | ||
|
||
.. function:: exchange_ctrl(message, comm) | ||
|
||
Send ``message`` to all peers in the MPI intercomm ``comm`` and receive the | ||
unanimous answer. ``message`` must be one of the types ``msg_*`` above. | ||
|
||
Spike Exchange | ||
============== | ||
|
||
.. class:: arb_spike | ||
|
||
.. attribute:: gid | ||
|
||
Global id of the spiking cell, must fit in an unsigned 32b integer. | ||
``gid`` must be unique in the external network. | ||
|
||
.. attribute:: lid | ||
|
||
Local id on the spiking cell, must fit in an unsigned 32b integer. This | ||
``lid`` describes which logical part of the cell ``gid`` emitted the | ||
spike. If the external simulation doesn't distinguish betwenn different | ||
sources on the same cell, always set this to zero. | ||
|
||
.. attribute:: time | ||
|
||
Time at which the occured. | ||
|
||
.. function:: gather_spikes(spikes, comm) | ||
|
||
Sends a buffer of spikes over ``comm`` receiving back the concatenated | ||
result of all calling MPI tasks in Arbor. This is a collective | ||
operation; each MPI task on the remote side must call it simultaneously | ||
with its _local_ part of the spikes to send. |
Submodule units
updated
40 files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,7 @@ set(pyarb_source | |
simulation.cpp | ||
single_cell_model.cpp | ||
env.cpp | ||
remote.cpp | ||
units.cpp | ||
) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
#include <arbor/version.hpp> | ||
|
||
#ifdef ARB_MPI_ENABLED | ||
|
||
#include "mpi.hpp" | ||
|
||
#include <arbor/communication/remote.hpp> | ||
#include <arbor/version.hpp> | ||
|
||
#include <pybind11/pybind11.h> | ||
#include <pybind11/stl.h> | ||
|
||
#include "conversion.hpp" | ||
#include "context.hpp" | ||
#include "error.hpp" | ||
#include "strprintf.hpp" | ||
|
||
namespace pyarb { | ||
using namespace pybind11::literals; | ||
|
||
void register_remote(pybind11::module& m) { | ||
auto s = m.def_submodule("remote", "Wrappers for remote communication."); | ||
|
||
pybind11::class_<arb::remote::msg_null> msg_null(s, "msg_null", "Empty message."); | ||
msg_null | ||
.def(pybind11::init<>([]() { return arb::remote::msg_null{};})) | ||
.def("__repr__", [](const arb::remote::msg_null&){return "(arb::remote::msg_null)";}) | ||
.def("__str__", [](const arb::remote::msg_null&){return "(msg_null)";}); | ||
|
||
pybind11::class_<arb::remote::msg_abort> msg_abort(s, "msg_abort", "Aborting with error."); | ||
msg_abort | ||
.def(pybind11::init<>([](const std::string& s) { | ||
auto res = arb::remote::msg_abort{}; | ||
std::memset(res.reason, 0x0, sizeof(res.reason)); | ||
std::strncpy(res.reason, s.c_str(), 511); | ||
return res; | ||
}), | ||
"reason"_a, | ||
"Signal abort with a reason.") | ||
.def(pybind11::init<>([]() { | ||
auto res = arb::remote::msg_abort{}; | ||
std::memset(res.reason, 0x0, sizeof(res.reason)); | ||
return res; | ||
}), | ||
"Signal abort without a reason.") | ||
.def("__repr__", [](const arb::remote::msg_abort& s){return util::pprintf("(arb::remote::msg_abort reason={})", s.reason);}) | ||
.def("__str__", [](const arb::remote::msg_abort& s){return util::pprintf("(abort reason={})", s.reason);}); | ||
|
||
pybind11::class_<arb::remote::msg_epoch> msg_epoch(s, "msg_epoch", "Commencing epoch."); | ||
msg_epoch | ||
.def(pybind11::init<>([](double f, double t) { return arb::remote::msg_epoch{f, t}; }), | ||
"from"_a, "to"_a, | ||
"Signal commencing of epoch [from, to).") | ||
.def("__repr__", [](const arb::remote::msg_epoch& s){return util::pprintf("(arb::remote::msg_epoch from={} to={})", s.t_start, s.t_end);}) | ||
.def("__str__", [](const arb::remote::msg_epoch& s){return util::pprintf("(epoch from={} to={})", s.t_start, s.t_end);}); | ||
|
||
pybind11::class_<arb::remote::msg_done> msg_done(s, "msg_done", "Concluded simulation period with final time."); | ||
msg_done | ||
.def(pybind11::init<>([](float t) { return arb::remote::msg_done{t}; }), | ||
"final"_a, | ||
"Signal conclusion of simulation at time `final``.") | ||
.def("__repr__", [](const arb::remote::msg_done& s){return util::pprintf("(arb::remote::msg_done to={})", s.time);}) | ||
.def("__str__", [](const arb::remote::msg_done& s){return util::pprintf("(done to={})", s.time);}); | ||
|
||
s.def("exchange_ctrl", | ||
[](arb::remote::ctrl_message msg, pybind11::object mpi) { | ||
auto err = "Invalid MPI Communicator."; | ||
if (can_convert_to_mpi_comm(mpi)) { | ||
return arb::remote::exchange_ctrl(msg, convert_to_mpi_comm(mpi)); | ||
} | ||
else if (auto c = py2optional<mpi_comm_shim>(mpi, err)) { | ||
return arb::remote::exchange_ctrl(msg, c->comm); | ||
} else { | ||
throw pyarb_error(err); | ||
} | ||
}, | ||
"msg"_a, "mpi_comm"_a, | ||
"Send given control message to all peers and receive their (unanimous) answer."); | ||
|
||
pybind11::class_<arb::remote::arb_spike> arb_spike(s, "arb_spike", "Empty message."); | ||
arb_spike.def(pybind11::init<>([](std::uint32_t gid, std::uint32_t lid, double t) { return arb::remote::arb_spike{{gid, lid}, t};}), | ||
"gid"_a, "lid"_a, "time"_a, | ||
"Spike caused by cell `gid` on location `lid` at time `time`.") | ||
.def("__repr__", [](const arb::remote::arb_spike& s){return util::pprintf("(arb::remote::arb_spike gid={} lid={} time={})", s.source.gid, s.source.lid, s.time);}) | ||
.def("__str__", [](const arb::remote::arb_spike& s){return util::pprintf("(spike gid={} lid={} time={})", s.source.gid, s.source.lid, s.time);}); | ||
|
||
s.def("gather_spikes", | ||
[](const std::vector<arb::remote::arb_spike>& msg, pybind11::object mpi) { | ||
auto err = "Invalid MPI Communicator."; | ||
if (can_convert_to_mpi_comm(mpi)) { | ||
return arb::remote::gather_spikes(msg, convert_to_mpi_comm(mpi)); | ||
} | ||
else if (auto c = py2optional<mpi_comm_shim>(mpi, err)) { | ||
return arb::remote::gather_spikes(msg, c->comm); | ||
} else { | ||
throw pyarb_error(err); | ||
} | ||
}, | ||
"msg"_a, "mpi_comm"_a, | ||
"Send list of spikes to all peers and receive their collected answer."); | ||
} | ||
} | ||
#endif |