-
Notifications
You must be signed in to change notification settings - Fork 53
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
Pack/Unpack data for user-data #1224
base: main
Are you sure you want to change the base?
Changes from 63 commits
96ff4b5
a5f70f3
cea2b11
993c979
a03b01e
6ee7851
df3abdf
c985b9e
eff194f
3d63d86
05e4984
d28dc55
5376ef7
0c233a2
770c60a
8c76526
d37eca1
16edf34
060e173
00e19b4
ed9eb01
e640c3e
e4d2413
8d667c9
1a9ecca
92b6de6
f66ca3d
a3b1b71
f225fc4
43a4cb0
369c691
f21bba4
d37ba59
00bfae6
fb549c8
d3ca0bb
7bf372e
bbd680c
7100f81
f2a524f
c45ac31
d425aac
d04ef8e
9ab1fe4
1cae747
77a6c47
21b0820
af26edf
b5fcd22
cfbf37c
49cf6ab
b0bc6ec
de2b97f
5bc3983
def4cbb
0f60271
67b413d
85d69e5
bc48d36
8d05446
1a66765
9885468
ffc6a49
291c0f5
c36773c
4d03763
ad6270c
691ae7d
14e66da
8287200
56c6046
18330e6
8132698
f6dc3fb
b347bd7
9090f1a
5fc9572
e6d1e38
7e1b537
ec33c01
fab6496
8d322b5
aac35e2
5be27c6
976fef3
d188ba4
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 |
---|---|---|
@@ -0,0 +1,249 @@ | ||
/* | ||
This file is part of t8code. | ||
t8code is a C library to manage a collection (a forest) of multiple | ||
connected adaptive space-trees of general element classes in parallel. | ||
|
||
Copyright (C) 2024 the developers | ||
|
||
t8code is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation; either version 2 of the License, or | ||
(at your option) any later version. | ||
|
||
t8code is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
|
||
You should have received a copy of the GNU General Public License | ||
along with t8code; if not, write to the Free Software Foundation, Inc., | ||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
*/ | ||
|
||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#ifndef T8_DATA_HANDLER_HXX | ||
#define T8_DATA_HANDLER_HXX | ||
|
||
#include <t8.h> | ||
#include <vector> | ||
#include <t8_data/t8_data_handler_base.hxx> | ||
#include <algorithm> | ||
#include <memory> | ||
#include <type_traits> | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
class t8_abstract_data_handler { | ||
public: | ||
/** | ||
* Pure virtual function to determine the buffer size. | ||
* | ||
* This function must be implemented by derived classes to calculate | ||
* the size of the buffer required for communication. | ||
* | ||
* \param[in] comm The MPI communicator. | ||
* \return The size of the buffer. | ||
*/ | ||
virtual int | ||
buffer_size (sc_MPI_Comm comm) | ||
= 0; | ||
|
||
/** | ||
* Packs a vector into a buffer. The vector data will be prefixed with the number of elements in the vector. | ||
* | ||
* This pure virtual function is responsible for packing a vector prefix into the provided buffer. | ||
* | ||
* \param[in, out] buffer A pointer to the buffer where the vector prefix will be packed. | ||
* \param[in] num_bytes The number of bytes to be packed. | ||
* \param[in] pos A reference to an integer representing the current position in the buffer. This will be updated as bytes are packed. | ||
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. What would I need this for? 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. This is used to fill the buffer for MPI communication for data structures that are non-trivial and do not lay linear in memory. 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. Isn't it then [in, out]? |
||
* \param[in] comm The MPI communicator used for the operation. | ||
*/ | ||
virtual void | ||
pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
= 0; | ||
|
||
/** | ||
* Unpacks a vector from a buffer. Expected to be prefixed with the number of elements in the vector. | ||
* | ||
* This pure virtual function is responsible for unpacking a vector prefix from the provided buffer. | ||
* | ||
* \param[in] buffer Pointer to the buffer containing the packed data. | ||
* \param[in] num_bytes The number of bytes in the buffer. | ||
* \param[in] pos Reference to an integer representing the current position in the buffer. This will be updated as data is unpacked. | ||
* \param[in] outcount Reference to an integer where the count of unpacked elements will be stored. | ||
* \param[in] comm The MPI communicator used for the operation. | ||
*/ | ||
virtual void | ||
unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) | ||
= 0; | ||
|
||
/** | ||
* Pure virtual function to send data to a specified destination. | ||
* | ||
* This function is responsible for packing and sending data to a given destination | ||
* with a specific tag using the provided MPI communicator. | ||
* | ||
* \param[in] dest The destination rank to which the data will be sent. | ||
* \param[in] tag The tag associated with the message to be sent. | ||
* \param[in] comm The MPI communicator used for the communication. | ||
* \return An integer indicating the status of the send operation. | ||
*/ | ||
virtual int | ||
send (const int dest, const int tag, sc_MPI_Comm comm) | ||
= 0; | ||
|
||
/** | ||
* Receives a message from a specified source. | ||
* | ||
* This pure virtual function is responsible for receiving and unpacking a message from a given source | ||
* with a specific tag within the provided MPI communicator. The function will also | ||
* update the status and output count of the received message. | ||
* | ||
* \param[in] source The rank of the source process from which the message is received. | ||
* \param[in] tag The tag of the message to be received. | ||
* \param[in] comm The MPI communicator within which the message is received. | ||
* \param[in] status A pointer to an MPI status object that will be updated with the status of the received message. | ||
* \param[in] outcount A reference to an integer that will be updated with the count of received elements. | ||
* \return An integer indicating the success or failure of the receive operation. | ||
*/ | ||
virtual int | ||
recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) | ||
= 0; | ||
|
||
/** | ||
* Pure virtual function to get the type. | ||
* | ||
* This function must be overridden in derived classes to return the type. | ||
* | ||
* \return An integer representing the type. | ||
*/ | ||
virtual int | ||
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. Which integer is for which type? Is there an enum for this? 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. This is currently more a place-holder than a proper implementation. An enum over all of our types that can be used by this class would be nice. 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. Do you want to add a TODO? |
||
type () | ||
= 0; | ||
|
||
virtual ~t8_abstract_data_handler () {}; | ||
}; | ||
|
||
/** | ||
* \class t8_data_handler | ||
* \brief A template class for handling data in a distributed environment. | ||
* | ||
* This class inherits from t8_abstract_data_handler and provides methods for | ||
* packing, unpacking, sending, and receiving data using MPI. | ||
* | ||
* \tparam T The type of data to be handled. | ||
*/ | ||
template <typename T> | ||
Davknapp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
class t8_data_handler: public t8_abstract_data_handler { | ||
public: | ||
t8_data_handler (): single_handler () | ||
Davknapp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
m_data = nullptr; | ||
} | ||
|
||
t8_data_handler (const std::vector<T> &data): m_data (std::make_shared<std::vector<T>> (data)), single_handler () | ||
Davknapp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
} | ||
|
||
void | ||
Davknapp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
get_data (std::vector<T> &data) const | ||
Davknapp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
if (m_data) { | ||
data = *m_data; | ||
} | ||
} | ||
|
||
int | ||
buffer_size (sc_MPI_Comm comm) override | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
int total_size = 0; | ||
const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); | ||
SC_CHECK_MPI (mpiret); | ||
if (m_data) { | ||
for (const auto &item : *m_data) { | ||
total_size += single_handler.size (item, comm); | ||
} | ||
} | ||
return total_size; | ||
} | ||
|
||
void | ||
pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) override | ||
Davknapp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
const int num_data = m_data->size (); | ||
const int mpiret = sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); | ||
SC_CHECK_MPI (mpiret); | ||
|
||
for (const auto &item : *m_data) { | ||
single_handler.pack (item, pos, buffer, num_bytes, comm); | ||
} | ||
} | ||
|
||
void | ||
unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) override | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
const int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); | ||
SC_CHECK_MPI (mpiret); | ||
T8_ASSERT (outcount >= 0); | ||
|
||
if (!m_data) { | ||
m_data = std::make_shared<std::vector<T>> (outcount); | ||
} | ||
else { | ||
m_data->resize (outcount); | ||
} | ||
for (auto &item : *m_data) { | ||
single_handler.unpack (buffer, num_bytes, pos, item, comm); | ||
} | ||
} | ||
|
||
int | ||
send (const int dest, const int tag, sc_MPI_Comm comm) override | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
#if T8_ENABLE_MPI | ||
int pos = 0; | ||
const int num_bytes = buffer_size (comm); | ||
std::vector<char> buffer (num_bytes); | ||
pack_vector_prefix (buffer.data (), num_bytes, pos, comm); | ||
|
||
const int mpiret = sc_MPI_Send (buffer.data (), num_bytes, sc_MPI_PACKED, dest, tag, comm); | ||
SC_CHECK_MPI (mpiret); | ||
return mpiret; | ||
#else | ||
t8_infof ("send only available when configured with --enable-mpi\n"); | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return sc_MPI_ERR_OTHER; | ||
#endif | ||
} | ||
|
||
int | ||
recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) override | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
#if T8_ENABLE_MPI | ||
int pos = 0; | ||
int mpiret = sc_MPI_Probe (source, tag, comm, status); | ||
SC_CHECK_MPI (mpiret); | ||
|
||
int num_bytes; | ||
mpiret = sc_MPI_Get_count (status, sc_MPI_PACKED, &num_bytes); | ||
SC_CHECK_MPI (mpiret); | ||
std::vector<char> buffer (num_bytes); | ||
|
||
mpiret = sc_MPI_Recv (buffer.data (), num_bytes, sc_MPI_PACKED, source, tag, comm, status); | ||
SC_CHECK_MPI (mpiret); | ||
unpack_vector_prefix (buffer.data (), num_bytes, pos, outcount, comm); | ||
return mpiret; | ||
#else | ||
t8_infof ("recv only available when configured with --enable-mpi\n"); | ||
return sc_MPI_ERR_OTHER; | ||
#endif | ||
} | ||
|
||
int | ||
type () override | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
return single_handler.type (); | ||
} | ||
|
||
private: | ||
std::shared_ptr<std::vector<T>> m_data; | ||
t8_single_data_handler<T> single_handler; | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}; | ||
|
||
#endif /* T8_DATA_HANDLER_HXX */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
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. Why is this file called |
||
This file is part of t8code. | ||
t8code is a C library to manage a collection (a forest) of multiple | ||
connected adaptive space-trees of general element classes in parallel. | ||
|
||
Copyright (C) 2024 the developers | ||
|
||
t8code is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation; either version 2 of the License, or | ||
(at your option) any later version. | ||
|
||
t8code is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
|
||
You should have received a copy of the GNU General Public License | ||
along with t8code; if not, write to the Free Software Foundation, Inc., | ||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
*/ | ||
|
||
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. File description is missing 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. Please adapt the file description to the format we use in other files: https://github.com/DLR-AMR/t8code/blob/main/src/t8_eclass.h#L23-L29 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. For all files, the other formats are also off |
||
#ifndef T8_DATA_HANDLER_BASE | ||
#define T8_DATA_HANDLER_BASE | ||
|
||
#include <t8.h> | ||
|
||
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. Class docstring is missing |
||
template <typename T> | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
class t8_single_data_handler { | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public: | ||
t8_single_data_handler () {}; | ||
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. Docstring is missing |
||
|
||
int | ||
sandro-elsweijer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
size (const T &data, sc_MPI_Comm comm); | ||
|
||
/** | ||
* Packs the given data into a buffer for communication. | ||
* | ||
* \tparam T The type of the data to be packed. | ||
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. Since the class is templated and not the member function I would remove this. And if we leave it T->TType |
||
* \param[in] data The data to be packed. | ||
* \param[in] pos The current position in the buffer where the data should be packed. | ||
* \param[in, out] buffer The buffer where the data will be packed. | ||
* \param[in] num_bytes The number of bytes available in the buffer. | ||
* \param[in] comm The MPI communicator used for communication. | ||
*/ | ||
void | ||
pack (const T &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm); | ||
|
||
/** | ||
* Unpacks data from a buffer. | ||
* | ||
* This function unpacks data from a given buffer into the provided data structure. | ||
* | ||
* \tparam T The type of the data to be unpacked. | ||
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. Same as above |
||
* \param[in] buffer A pointer to the buffer containing the packed data. | ||
* \param[in] num_bytes The number of bytes in the buffer. | ||
* \param[in] pos A reference to an integer representing the current position in the buffer. | ||
* \param[in, out] data A pointer to the data structure where the unpacked data will be stored. | ||
* \param[in] comm The MPI communicator used for communication. | ||
*/ | ||
void | ||
unpack (const void *buffer, const int num_bytes, int &pos, T &data, sc_MPI_Comm comm); | ||
|
||
/** | ||
* Returns the type of the data handler. | ||
* | ||
* This function returns the type of the data handler. | ||
* | ||
* \return An integer representing the type. | ||
*/ | ||
int | ||
type (); | ||
|
||
~t8_single_data_handler () {}; | ||
}; | ||
|
||
#endif /* T8_DATA_HANDLER_BASE */ |
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.
Happy New Year 🥳