-
Notifications
You must be signed in to change notification settings - Fork 17
Add global comm #341
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Add global comm #341
Changes from all commits
2f7318d
313df5e
e8cd7cd
dcbc7f3
f197296
29984dc
22d089e
3761c83
e11b082
21f0ce7
25671dd
a9a7267
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ set(PCMS_COUPLER_HEADERS | |
| field_exchange_planner.h | ||
| partition.h | ||
| overlap_mask.h | ||
| global_communicator.h | ||
| ) | ||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,10 +11,44 @@ | |
| #include "pcms/utility/assert.h" | ||
| #include "pcms/utility/common.h" | ||
| #include "pcms/utility/profile.h" | ||
| #include "pcms/coupler/global_communicator.h" | ||
| #include <memory> | ||
|
|
||
| namespace pcms | ||
| { | ||
| template <typename T> | ||
| class GlobalDataInterface | ||
| { | ||
| public: | ||
| GlobalDataInterface(const std::string& name, MPI_Comm mpi_comm, | ||
| redev::Channel& channel) | ||
| : mpi_comm_(mpi_comm), comm_(name, mpi_comm_, channel) | ||
| { | ||
| PCMS_FUNCTION_TIMER; | ||
| } | ||
|
|
||
| void SendData(T* msg, std::string variable_name, std::size_t msg_size, | ||
| redev::Mode mode = redev::Mode::Synchronous) | ||
| { | ||
| PCMS_FUNCTION_TIMER; | ||
| comm_.Send(msg, variable_name, msg_size, mode); | ||
| } | ||
|
|
||
| std::vector<T> ReceiveData(std::string variable_name, std::size_t msg_size, | ||
| redev::Mode mode = redev::Mode::Synchronous) | ||
| { | ||
| PCMS_FUNCTION_TIMER; | ||
| return comm_.Receive(variable_name, msg_size, mode); | ||
| } | ||
|
|
||
| private: | ||
| MPI_Comm mpi_comm_; | ||
| GlobalCommunicator<T> comm_; | ||
| }; | ||
| using GlobalDataVariant = | ||
| std::variant<GlobalDataInterface<int8_t>, GlobalDataInterface<int32_t>, | ||
| GlobalDataInterface<int64_t>, GlobalDataInterface<float>, | ||
| GlobalDataInterface<double>>; | ||
|
|
||
| class Application; | ||
|
|
||
|
|
@@ -31,6 +65,28 @@ class FieldHandle | |
| void Receive(redev::Mode mode = redev::Mode::Synchronous) const; | ||
| [[nodiscard]] Field<T>& GetField() const; | ||
|
|
||
| private: | ||
| Application* app_; | ||
| std::string name_; | ||
| }; | ||
| template <typename T> | ||
| class DataHandle | ||
| { | ||
| public: | ||
| DataHandle(Application* app, std::string name) | ||
| : app_(app), name_(std::move(name)) | ||
| { | ||
| } | ||
|
|
||
| void Send(T* msg, std::string variable_name, std::size_t msg_size, | ||
| redev::Mode mode = redev::Mode::Synchronous) const; | ||
|
|
||
| [[nodiscard]] std::vector<T> Receive( | ||
| std::string variable_name, std::size_t msg_size, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this API be consistent with |
||
| redev::Mode mode = redev::Mode::Synchronous) const; | ||
|
|
||
| [[nodiscard]] GlobalDataInterface<T>& GetDataInterface() const; | ||
|
|
||
| private: | ||
| Application* app_; | ||
| std::string name_; | ||
|
|
@@ -70,7 +126,11 @@ class Application | |
| FieldHandle<T> AddField(std::string name, Field<T>&& field, | ||
| std::unique_ptr<FieldSerializer<T>> serializer, | ||
| bool participates = true); | ||
|
|
||
| template <typename T> | ||
| DataHandle<T> AddData(std::string name, MPI_Comm mpi_comm); | ||
| template <typename T> | ||
| [[nodiscard]] GlobalDataInterface<T>& GetDataInterface( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this return the handle we discussed? |
||
| const std::string& name); | ||
| void SendField(const std::string& name, | ||
| redev::Mode mode = redev::Mode::Synchronous) | ||
| { | ||
|
|
@@ -91,6 +151,27 @@ class Application | |
| [mode](auto& field_communicator) { field_communicator->Receive(); }, | ||
| detail::find_or_error(name, field_communicators_)); | ||
| }; | ||
| template <typename T> | ||
| void SendData(const std::string& name, T* msg, std::string variable_name, | ||
| std::size_t msg_size, | ||
| redev::Mode mode = redev::Mode::Synchronous) | ||
| { | ||
| PCMS_FUNCTION_TIMER; | ||
| PCMS_ALWAYS_ASSERT(InSendPhase()); | ||
| GetDataInterface<T>(name).SendData(msg, std::move(variable_name), msg_size, | ||
| mode); | ||
| } | ||
|
|
||
| template <typename T> | ||
| std::vector<T> ReceiveData(const std::string& name, std::string variable_name, | ||
| std::size_t msg_size, | ||
| redev::Mode mode = redev::Mode::Synchronous) | ||
| { | ||
| PCMS_FUNCTION_TIMER; | ||
| PCMS_ALWAYS_ASSERT(InReceivePhase()); | ||
| return GetDataInterface<T>(name).ReceiveData(std::move(variable_name), | ||
| msg_size, mode); | ||
| } | ||
| [[nodiscard]] bool InSendPhase() const noexcept | ||
| { | ||
| PCMS_FUNCTION_TIMER; | ||
|
|
@@ -160,7 +241,53 @@ class Application | |
| std::map<const FieldLayout*, std::unique_ptr<FieldLayoutCommunicator>> | ||
| field_layout_communicators_; | ||
| std::map<std::string, std::unique_ptr<OverlapMask>> layout_overlap_masks_; | ||
| std::map<std::string, GlobalDataVariant> global_data_interfaces_; | ||
| }; | ||
| template <typename T> | ||
| DataHandle<T> Application::AddData(std::string name, MPI_Comm mpi_comm) | ||
| { | ||
| PCMS_FUNCTION_TIMER; | ||
| auto [it, inserted] = global_data_interfaces_.try_emplace( | ||
| name, std::in_place_type<GlobalDataInterface<T>>, name, mpi_comm, channel_); | ||
| if (!inserted) { | ||
| throw pcms_error("Global data interface with this name already exists"); | ||
| } | ||
| return DataHandle<T>{this, std::move(name)}; | ||
| } | ||
| template <typename T> | ||
| GlobalDataInterface<T>& Application::GetDataInterface(const std::string& name) | ||
| { | ||
| auto* data_interface = std::get_if<GlobalDataInterface<T>>( | ||
| &detail::find_or_error(name, global_data_interfaces_)); | ||
| if (data_interface == nullptr) { | ||
| throw pcms_error( | ||
| "Global data interface stored with different type than requested"); | ||
| } | ||
| return *data_interface; | ||
| } | ||
| template <typename T> | ||
| GlobalDataInterface<T>& DataHandle<T>::GetDataInterface() const | ||
| { | ||
| PCMS_ALWAYS_ASSERT(app_ != nullptr); | ||
| return app_->GetDataInterface<T>(name_); | ||
| } | ||
| template <typename T> | ||
| void DataHandle<T>::Send(T* msg, std::string variable_name, | ||
| std::size_t msg_size, redev::Mode mode) const | ||
| { | ||
| PCMS_ALWAYS_ASSERT(app_ != nullptr); | ||
| app_->SendData<T>(name_, msg, std::move(variable_name), msg_size, mode); | ||
| } | ||
|
|
||
| template <typename T> | ||
| std::vector<T> DataHandle<T>::Receive(std::string variable_name, | ||
| std::size_t msg_size, | ||
| redev::Mode mode) const | ||
| { | ||
| PCMS_ALWAYS_ASSERT(app_ != nullptr); | ||
|
|
||
| return app_->ReceiveData<T>(name_, std::move(variable_name), msg_size, mode); | ||
| } | ||
|
|
||
| class Coupler | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| #ifndef PCMS_GLOBAL_COMMUNICATOR_H | ||
| #define PCMS_GLOBAL_COMMUNICATOR_H | ||
| #include <redev.h> | ||
| #include <pcms/utility/profile.h> | ||
| namespace pcms | ||
| { | ||
| using redev::Mode; | ||
| template <typename T> | ||
| struct GlobalCommunicator | ||
| { | ||
| using value_type = T; | ||
|
|
||
| public: | ||
| GlobalCommunicator(std::string name, MPI_Comm mpi_comm, | ||
| redev::Channel& channel) | ||
| : mpi_comm(mpi_comm), channel_(channel), name_(std::move(name)) | ||
| { | ||
| PCMS_FUNCTION_TIMER; | ||
| comm_ = channel_.CreateComm<T>(name_, mpi_comm, redev::CommType::Global); | ||
| } | ||
| GlobalCommunicator(const GlobalCommunicator&) = delete; | ||
| GlobalCommunicator& operator=(const GlobalCommunicator&) = delete; | ||
| GlobalCommunicator(GlobalCommunicator&&) = default; | ||
| GlobalCommunicator& operator=(GlobalCommunicator&&) = default; | ||
|
|
||
| void Send(T* msg, std::string VarName, size_t msg_size, | ||
| Mode mode = Mode::Synchronous) | ||
| { | ||
| PCMS_FUNCTION_TIMER; | ||
| PCMS_ALWAYS_ASSERT(channel_.InSendCommunicationPhase()); | ||
| comm_.SetCommParams(VarName, msg_size); | ||
| comm_.Send(msg, mode); | ||
| } | ||
| std::vector<T> Receive(std::string VarName, size_t msg_size, | ||
| Mode mode = Mode::Synchronous) | ||
| { | ||
| PCMS_FUNCTION_TIMER; | ||
| PCMS_ALWAYS_ASSERT(channel_.InReceiveCommunicationPhase()); | ||
| comm_.SetCommParams(VarName, msg_size); | ||
| auto data = comm_.Recv(mode); | ||
| return data; | ||
| } | ||
|
|
||
| private: | ||
| MPI_Comm mpi_comm; | ||
| redev::Channel& channel_; | ||
| std::string name_; | ||
| redev::BidirectionalComm<T> comm_; | ||
| }; | ||
| } // namespace pcms | ||
| #endif // PCMS_GLOBAL_COMMUNICATOR_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should take an array_view instead of a pointer and a size.