* considered as a request message by the receiving rank.
* - receive message: The answer to a send/request message.
*
- * @tparam T1 The type of the elements of the vector to sent.
- * @tparam T2 The type of the elements of the vector to received.
+ * @tparam RequestType The type of the elements of the vector to sent.
+ * @tparam AnswerType The type of the elements of the vector to received.
*
* @note Since the payloads of the messages are optional, users have
* to deal with buffers themselves. The ConsensusAlgorithm classes
* to be sent can be inserted to or read from, and (2) communicate
* these vectors blindly.
*/
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
class Process
{
public:
* @note The buffer is empty. Before using it, you have to set its size.
*/
virtual void
- create_request(const unsigned int other_rank,
- std::vector<T1> & send_buffer);
+ create_request(const unsigned int other_rank,
+ std::vector<RequestType> &send_buffer);
/**
* Prepare the buffer where the payload of the answer of the request to
* its size.
*/
virtual void
- answer_request(const unsigned int other_rank,
- const std::vector<T1> &buffer_recv,
- std::vector<T2> & request_buffer);
+ answer_request(const unsigned int other_rank,
+ const std::vector<RequestType> &buffer_recv,
+ std::vector<AnswerType> & request_buffer);
/**
* Process the payload of the answer of the request to the process with
* @param[in] recv_buffer data to be sent part of the request (optional)
*/
virtual void
- read_answer(const unsigned int other_rank,
- const std::vector<T2> &recv_buffer);
+ read_answer(const unsigned int other_rank,
+ const std::vector<AnswerType> &recv_buffer);
};
* to actually compute such communication patterns and perform the
* communication.
*
- * @tparam T1 The type of the elements of the vector to be sent.
- * @tparam T2 The type of the elements of the vector to be received.
+ * @tparam RequestType The type of the elements of the vector to be sent.
+ * @tparam AnswerType The type of the elements of the vector to be received.
*/
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
class Interface
{
public:
* function that takes an argument.
*/
DEAL_II_DEPRECATED
- Interface(Process<T1, T2> &process, const MPI_Comm &comm);
+ Interface(Process<RequestType, AnswerType> &process,
+ const MPI_Comm & comm);
/**
* Destructor. Made `virtual` to ensure that one can work with
* that takes a number of `std::function` arguments.
*/
std::vector<unsigned int>
- run(Process<T1, T2> &process, const MPI_Comm &comm);
+ run(Process<RequestType, AnswerType> &process, const MPI_Comm &comm);
/**
* Run the consensus algorithm and return a vector of process ranks
*/
virtual std::vector<unsigned int>
run(const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- & answer_request,
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
const std::function<void(const unsigned int,
- const std::vector<T2> &)> &process_answer,
- const MPI_Comm & comm) = 0;
+ const std::vector<AnswerType> &)>
+ & process_answer,
+ const MPI_Comm &comm) = 0;
private:
/**
* otherwise
*/
DEAL_II_DEPRECATED
- Process<T1, T2> *process;
+ Process<RequestType, AnswerType> *process;
/**
* MPI communicator.
* @note This class closely follows @cite hoefler2010scalable, but our
* implementation also deals with payloads.
*
- * @tparam T1 The type of the elements of the vector to be sent.
- * @tparam T2 The type of the elements of the vector to be received.
+ * @tparam RequestType The type of the elements of the vector to be sent.
+ * @tparam AnswerType The type of the elements of the vector to be received.
*/
- template <typename T1, typename T2>
- class NBX : public Interface<T1, T2>
+ template <typename RequestType, typename AnswerType>
+ class NBX : public Interface<RequestType, AnswerType>
{
public:
/**
* function that takes an argument.
*/
DEAL_II_DEPRECATED
- NBX(Process<T1, T2> &process, const MPI_Comm &comm);
+ NBX(Process<RequestType, AnswerType> &process, const MPI_Comm &comm);
/**
* Destructor.
virtual ~NBX() = default;
// Import the declarations from the base class.
- using Interface<T1, T2>::run;
+ using Interface<RequestType, AnswerType>::run;
/**
* @copydoc Interface::run()
*/
virtual std::vector<unsigned int>
run(const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- & answer_request,
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
const std::function<void(const unsigned int,
- const std::vector<T2> &)> &process_answer,
- const MPI_Comm & comm) override;
+ const std::vector<AnswerType> &)>
+ & process_answer,
+ const MPI_Comm &comm) override;
private:
#ifdef DEAL_II_WITH_MPI
/**
* Buffers for sending requests.
*/
- std::vector<std::vector<T1>> send_buffers;
+ std::vector<std::vector<RequestType>> send_buffers;
/**
* Requests for sending requests.
* resized and consequently its elements (the pointers) are moved
* around.
*/
- std::vector<std::unique_ptr<std::vector<T2>>> request_buffers;
+ std::vector<std::unique_ptr<std::vector<AnswerType>>> request_buffers;
/**
* Requests for sending answers to requests.
*/
bool
all_locally_originated_receives_are_completed(
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm);
*/
void
maybe_answer_one_request(
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- & answer_request,
- const MPI_Comm &comm);
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const MPI_Comm & comm);
/**
* Start to send all requests via ISend and post IRecvs for the incoming
void
start_communication(
const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
& create_request,
const MPI_Comm &comm);
* @note This class closely follows @cite hoefler2010scalable, but our
* implementation also deals with payloads.
*
- * @tparam T1 The type of the elements of the vector to be sent.
- * @tparam T2 The type of the elements of the vector to be received.
+ * @tparam RequestType The type of the elements of the vector to be sent.
+ * @tparam AnswerType The type of the elements of the vector to be received.
*/
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
nbx(const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- &answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm);
* in the ConsensusAlgorithms::NBX class (a sister class to the
* current one).
*
- * @tparam T1 The type of the elements of the vector to be sent.
- * @tparam T2 The type of the elements of the vector to be received.
+ * @tparam RequestType The type of the elements of the vector to be sent.
+ * @tparam AnswerType The type of the elements of the vector to be received.
*/
- template <typename T1, typename T2>
- class PEX : public Interface<T1, T2>
+ template <typename RequestType, typename AnswerType>
+ class PEX : public Interface<RequestType, AnswerType>
{
public:
/**
* function that takes an argument.
*/
DEAL_II_DEPRECATED
- PEX(Process<T1, T2> &process, const MPI_Comm &comm);
+ PEX(Process<RequestType, AnswerType> &process, const MPI_Comm &comm);
/**
* Destructor.
virtual ~PEX() = default;
// Import the declarations from the base class.
- using Interface<T1, T2>::run;
+ using Interface<RequestType, AnswerType>::run;
/**
* @copydoc Interface::run()
*/
virtual std::vector<unsigned int>
run(const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- & answer_request,
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
const std::function<void(const unsigned int,
- const std::vector<T2> &)> &process_answer,
- const MPI_Comm & comm) override;
+ const std::vector<AnswerType> &)>
+ & process_answer,
+ const MPI_Comm &comm) override;
private:
#ifdef DEAL_II_WITH_MPI
/**
* Buffers for sending requests.
*/
- std::vector<std::vector<T1>> send_buffers;
+ std::vector<std::vector<RequestType>> send_buffers;
/**
* Buffers for receiving answers to requests.
*/
- std::vector<std::vector<T2>> recv_buffers;
+ std::vector<std::vector<AnswerType>> recv_buffers;
/**
* MPI request objects for sending request messages.
/**
* Buffers for sending answers to requests.
*/
- std::vector<std::vector<T2>> requests_buffers;
+ std::vector<std::vector<AnswerType>> requests_buffers;
/**
* Requests for sending answers to requests.
unsigned int
start_communication(
const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
& create_request,
const MPI_Comm &comm);
* process the request and send an answer.
*/
void
- answer_one_request(
- const unsigned int index,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- & answer_request,
- const MPI_Comm &comm);
+ answer_one_request(const unsigned int index,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const MPI_Comm & comm);
/**
* Receive and process all of the incoming responses to the
void
process_incoming_answers(
const unsigned int n_targets,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm);
* in the ConsensusAlgorithms::NBX class (a sister class to the
* current one).
*
- * @tparam T1 The type of the elements of the vector to be sent.
- * @tparam T2 The type of the elements of the vector to be received.
+ * @tparam RequestType The type of the elements of the vector to be sent.
+ * @tparam AnswerType The type of the elements of the vector to be received.
*/
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
pex(const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- &answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm);
* A serial fall back for the above classes to allow programming
* independently of whether MPI is used or not.
*/
- template <typename T1, typename T2>
- class Serial : public Interface<T1, T2>
+ template <typename RequestType, typename AnswerType>
+ class Serial : public Interface<RequestType, AnswerType>
{
public:
/**
* function that takes an argument.
*/
DEAL_II_DEPRECATED
- Serial(Process<T1, T2> &process, const MPI_Comm &comm);
+ Serial(Process<RequestType, AnswerType> &process, const MPI_Comm &comm);
// Import the declarations from the base class.
- using Interface<T1, T2>::run;
+ using Interface<RequestType, AnswerType>::run;
/**
* @copydoc Interface::run()
*/
virtual std::vector<unsigned int>
run(const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- & answer_request,
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
const std::function<void(const unsigned int,
- const std::vector<T2> &)> &process_answer,
- const MPI_Comm & comm) override;
+ const std::vector<AnswerType> &)>
+ & process_answer,
+ const MPI_Comm &comm) override;
};
* where the communicator provided has only one rank (or when
* MPI is simply not used at all).
*
- * @tparam T1 The type of the elements of the vector to be sent.
- * @tparam T2 The type of the elements of the vector to be received.
+ * @tparam RequestType The type of the elements of the vector to be sent.
+ * @tparam AnswerType The type of the elements of the vector to be received.
*/
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
pex(const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- &answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm);
* goal is to always use the most efficient algorithm for however many
* processes participate in the communication.
*
- * @tparam T1 The type of the elements of the vector to be sent.
- * @tparam T2 The type of the elements of the vector to be received.
+ * @tparam RequestType The type of the elements of the vector to be sent.
+ * @tparam AnswerType The type of the elements of the vector to be received.
*/
- template <typename T1, typename T2>
- class Selector : public Interface<T1, T2>
+ template <typename RequestType, typename AnswerType>
+ class Selector : public Interface<RequestType, AnswerType>
{
public:
/**
* function that takes an argument.
*/
DEAL_II_DEPRECATED
- Selector(Process<T1, T2> &process, const MPI_Comm &comm);
+ Selector(Process<RequestType, AnswerType> &process,
+ const MPI_Comm & comm);
/**
* Destructor.
virtual ~Selector() = default;
// Import the declarations from the base class.
- using Interface<T1, T2>::run;
+ using Interface<RequestType, AnswerType>::run;
/**
* @copydoc Interface::run()
*/
virtual std::vector<unsigned int>
run(const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- & answer_request,
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
const std::function<void(const unsigned int,
- const std::vector<T2> &)> &process_answer,
- const MPI_Comm & comm) override;
+ const std::vector<AnswerType> &)>
+ & process_answer,
+ const MPI_Comm &comm) override;
private:
// Pointer to the actual ConsensusAlgorithms::Interface implementation.
- std::shared_ptr<Interface<T1, T2>> consensus_algo;
+ std::shared_ptr<Interface<RequestType, AnswerType>> consensus_algo;
};
* goal is to always use the most efficient algorithm for however many
* processes participate in the communication.
*
- * @tparam T1 The type of the elements of the vector to be sent.
- * @tparam T2 The type of the elements of the vector to be received.
+ * @tparam RequestType The type of the elements of the vector to be sent.
+ * @tparam AnswerType The type of the elements of the vector to be received.
*/
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
- selector(
- const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- &answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
- & process_answer,
- const MPI_Comm &comm);
+ selector(const std::vector<unsigned int> &targets,
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
+ & process_answer,
+ const MPI_Comm &comm);
* The advantage of this class is that users do not have to write their
* own implementation but can register lambda functions directly.
*/
- template <typename T1, typename T2>
- class AnonymousProcess : public Process<T1, T2>
+ template <typename RequestType, typename AnswerType>
+ class AnonymousProcess : public Process<RequestType, AnswerType>
{
public:
/**
AnonymousProcess(
const std::function<std::vector<unsigned int>()>
&function_compute_targets,
- const std::function<void(const unsigned int, std::vector<T1> &)>
+ const std::function<void(const unsigned int,
+ std::vector<RequestType> &)>
&function_create_request = {},
const std::function<void(const unsigned int,
- const std::vector<T1> &,
- std::vector<T2> &)>
+ const std::vector<RequestType> &,
+ std::vector<AnswerType> &)>
&function_answer_request = {},
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
&function_read_answer = {});
/**
* @copydoc Process::create_request()
*/
void
- create_request(const unsigned int other_rank,
- std::vector<T1> & send_buffer) override;
+ create_request(const unsigned int other_rank,
+ std::vector<RequestType> &send_buffer) override;
/**
* @copydoc Process::answer_request()
*/
void
- answer_request(const unsigned int other_rank,
- const std::vector<T1> &buffer_recv,
- std::vector<T2> & request_buffer) override;
+ answer_request(const unsigned int other_rank,
+ const std::vector<RequestType> &buffer_recv,
+ std::vector<AnswerType> & request_buffer) override;
/**
* @copydoc Process::read_answer()
*/
void
- read_answer(const unsigned int other_rank,
- const std::vector<T2> &recv_buffer) override;
+ read_answer(const unsigned int other_rank,
+ const std::vector<AnswerType> &recv_buffer) override;
private:
const std::function<std::vector<unsigned int>()>
function_compute_targets;
- const std::function<void(const int, std::vector<T1> &)>
+ const std::function<void(const int, std::vector<RequestType> &)>
function_create_request;
- const std::function<
- void(const unsigned int, const std::vector<T1> &, std::vector<T2> &)>
+ const std::function<void(const unsigned int,
+ const std::vector<RequestType> &,
+ std::vector<AnswerType> &)>
function_answer_request;
- const std::function<void(const int, const std::vector<T2> &)>
+ const std::function<void(const int, const std::vector<AnswerType> &)>
function_read_answer;
};
#ifndef DOXYGEN
// Implementation of the functions in this namespace.
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
nbx(const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- &answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm)
{
- return NBX<T1, T2>().run(
+ return NBX<RequestType, AnswerType>().run(
targets, create_request, answer_request, process_answer, comm);
}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
pex(const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- &answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm)
{
- return PEX<T1, T2>().run(
+ return PEX<RequestType, AnswerType>().run(
targets, create_request, answer_request, process_answer, comm);
}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
serial(const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- & answer_request,
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
const std::function<void(const unsigned int,
- const std::vector<T2> &)> &process_answer,
- const MPI_Comm & comm)
+ const std::vector<AnswerType> &)>
+ & process_answer,
+ const MPI_Comm &comm)
{
- return Serial<T1, T2>().run(
+ return Serial<RequestType, AnswerType>().run(
targets, create_request, answer_request, process_answer, comm);
}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
- selector(
- const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- &answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
- & process_answer,
- const MPI_Comm &comm)
+ selector(const std::vector<unsigned int> &targets,
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
+ & process_answer,
+ const MPI_Comm &comm)
{
- return Selector<T1, T2>().run(
+ return Selector<RequestType, AnswerType>().run(
targets, create_request, answer_request, process_answer, comm);
}
- template <typename T1, typename T2>
- AnonymousProcess<T1, T2>::AnonymousProcess(
+ template <typename RequestType, typename AnswerType>
+ AnonymousProcess<RequestType, AnswerType>::AnonymousProcess(
const std::function<std::vector<unsigned int>()>
&function_compute_targets,
- const std::function<void(const unsigned int, std::vector<T1> &)>
- & function_create_request,
const std::function<void(const unsigned int,
- const std::vector<T1> &,
- std::vector<T2> &)> &function_answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ std::vector<RequestType> &)>
+ &function_create_request,
+ const std::function<void(const unsigned int,
+ const std::vector<RequestType> &,
+ std::vector<AnswerType> &)>
+ &function_answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
&function_read_answer)
: function_compute_targets(function_compute_targets)
, function_create_request(function_create_request)
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
- AnonymousProcess<T1, T2>::compute_targets()
+ AnonymousProcess<RequestType, AnswerType>::compute_targets()
{
return function_compute_targets();
}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- AnonymousProcess<T1, T2>::create_request(const unsigned int other_rank,
- std::vector<T1> & send_buffer)
+ AnonymousProcess<RequestType, AnswerType>::create_request(
+ const unsigned int other_rank,
+ std::vector<RequestType> &send_buffer)
{
if (function_create_request)
function_create_request(other_rank, send_buffer);
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- AnonymousProcess<T1, T2>::answer_request(
- const unsigned int other_rank,
- const std::vector<T1> &buffer_recv,
- std::vector<T2> & request_buffer)
+ AnonymousProcess<RequestType, AnswerType>::answer_request(
+ const unsigned int other_rank,
+ const std::vector<RequestType> &buffer_recv,
+ std::vector<AnswerType> & request_buffer)
{
if (function_answer_request)
function_answer_request(other_rank, buffer_recv, request_buffer);
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- AnonymousProcess<T1, T2>::read_answer(const unsigned int other_rank,
- const std::vector<T2> &recv_buffer)
+ AnonymousProcess<RequestType, AnswerType>::read_answer(
+ const unsigned int other_rank,
+ const std::vector<AnswerType> &recv_buffer)
{
if (function_read_answer)
function_read_answer(other_rank, recv_buffer);
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- Process<T1, T2>::answer_request(const unsigned int,
- const std::vector<T1> &,
- std::vector<T2> &)
+ Process<RequestType, AnswerType>::answer_request(
+ const unsigned int,
+ const std::vector<RequestType> &,
+ std::vector<AnswerType> &)
{
// nothing to do
}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- Process<T1, T2>::create_request(const unsigned int, std::vector<T1> &)
+ Process<RequestType, AnswerType>::create_request(
+ const unsigned int,
+ std::vector<RequestType> &)
{
// nothing to do
}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- Process<T1, T2>::read_answer(const unsigned int, const std::vector<T2> &)
+ Process<RequestType, AnswerType>::read_answer(
+ const unsigned int,
+ const std::vector<AnswerType> &)
{
// nothing to do
}
- template <typename T1, typename T2>
- Interface<T1, T2>::Interface(Process<T1, T2> &process,
- const MPI_Comm & comm)
+ template <typename RequestType, typename AnswerType>
+ Interface<RequestType, AnswerType>::Interface(
+ Process<RequestType, AnswerType> &process,
+ const MPI_Comm & comm)
: process(&process)
, comm(comm)
{}
- template <typename T1, typename T2>
- Interface<T1, T2>::Interface()
+ template <typename RequestType, typename AnswerType>
+ Interface<RequestType, AnswerType>::Interface()
: process(nullptr)
, comm(MPI_COMM_NULL)
{}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
- Interface<T1, T2>::run()
+ Interface<RequestType, AnswerType>::run()
{
Assert(process != nullptr,
ExcMessage("This function can only be called if the "
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
- Interface<T1, T2>::run(Process<T1, T2> &process, const MPI_Comm &comm)
+ Interface<RequestType, AnswerType>::run(
+ Process<RequestType, AnswerType> &process,
+ const MPI_Comm & comm)
{
// Unpack the 'process' object and call the function that takes
// function objects for all operations.
process.compute_targets(),
/* create_request: */
[&process](const unsigned int target) {
- std::vector<T1> request;
+ std::vector<RequestType> request;
process.create_request(target, request);
return request;
},
/* answer_request: */
- [&process](const unsigned int source,
- const std::vector<T1> &request) {
- std::vector<T2> answer;
+ [&process](const unsigned int source,
+ const std::vector<RequestType> &request) {
+ std::vector<AnswerType> answer;
process.answer_request(source, request, answer);
return answer;
},
/* process_answer: */
- [&process](const unsigned int target, const std::vector<T2> &answer) {
+ [&process](const unsigned int target,
+ const std::vector<AnswerType> &answer) {
process.read_answer(target, answer);
},
comm);
- template <typename T1, typename T2>
- NBX<T1, T2>::NBX(Process<T1, T2> &process, const MPI_Comm &comm)
- : Interface<T1, T2>(process, comm)
+ template <typename RequestType, typename AnswerType>
+ NBX<RequestType, AnswerType>::NBX(
+ Process<RequestType, AnswerType> &process,
+ const MPI_Comm & comm)
+ : Interface<RequestType, AnswerType>(process, comm)
{}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
- NBX<T1, T2>::run(
+ NBX<RequestType, AnswerType>::run(
const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- &answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm)
{
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- NBX<T1, T2>::start_communication(
+ NBX<RequestType, AnswerType>::start_communication(
const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
& create_request,
const MPI_Comm &comm)
{
AssertIndexRange(rank, Utilities::MPI::n_mpi_processes(comm));
auto &send_buffer = send_buffers[index];
- send_buffer =
- (create_request ? create_request(rank) : std::vector<T1>());
+ send_buffer = (create_request ? create_request(rank) :
+ std::vector<RequestType>());
// Post a request to send data
auto ierr = MPI_Isend(send_buffer.data(),
- send_buffer.size() * sizeof(T1),
+ send_buffer.size() * sizeof(RequestType),
MPI_BYTE,
rank,
tag_request,
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
bool
- NBX<T1, T2>::all_locally_originated_receives_are_completed(
- const std::function<void(const unsigned int, const std::vector<T2> &)>
- & process_answer,
- const MPI_Comm &comm)
+ NBX<RequestType, AnswerType>::
+ all_locally_originated_receives_are_completed(
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
+ & process_answer,
+ const MPI_Comm &comm)
{
#ifdef DEAL_II_WITH_MPI
// We know that all requests have come in when we have pending
MPI_Get_count(&status, MPI_BYTE, &message_size);
AssertThrowMPI(ierr);
}
- Assert(message_size % sizeof(T2) == 0, ExcInternalError());
- std::vector<T2> recv_buffer(message_size / sizeof(T2));
+ Assert(message_size % sizeof(AnswerType) == 0,
+ ExcInternalError());
+ std::vector<AnswerType> recv_buffer(message_size /
+ sizeof(AnswerType));
{
const int tag_deliver = Utilities::MPI::internal::Tags::
consensus_algorithm_nbx_process_deliver;
- const int ierr = MPI_Recv(recv_buffer.data(),
- recv_buffer.size() * sizeof(T2),
- MPI_BYTE,
- target,
- tag_deliver,
- comm,
- MPI_STATUS_IGNORE);
+ const int ierr =
+ MPI_Recv(recv_buffer.data(),
+ recv_buffer.size() * sizeof(AnswerType),
+ MPI_BYTE,
+ target,
+ tag_deliver,
+ comm,
+ MPI_STATUS_IGNORE);
AssertThrowMPI(ierr);
}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- NBX<T1, T2>::maybe_answer_one_request(
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- & answer_request,
- const MPI_Comm &comm)
+ NBX<RequestType, AnswerType>::maybe_answer_one_request(
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const MPI_Comm & comm)
{
#ifdef DEAL_II_WITH_MPI
AssertThrowMPI(ierr);
// allocate memory for incoming message
- Assert(number_amount % sizeof(T1) == 0, ExcInternalError());
- std::vector<T1> buffer_recv(number_amount / sizeof(T1));
+ Assert(number_amount % sizeof(RequestType) == 0,
+ ExcInternalError());
+ std::vector<RequestType> buffer_recv(number_amount /
+ sizeof(RequestType));
ierr = MPI_Recv(buffer_recv.data(),
number_amount,
MPI_BYTE,
// Allocate memory for an answer message to the current request,
// and ask the 'process' object to produce an answer:
- request_buffers.emplace_back(std::make_unique<std::vector<T2>>());
+ request_buffers.emplace_back(
+ std::make_unique<std::vector<AnswerType>>());
auto &request_buffer = *request_buffers.back();
if (answer_request)
request_buffer = answer_request(other_rank, buffer_recv);
// Then initiate sending the answer back to the requester.
request_requests.emplace_back(std::make_unique<MPI_Request>());
ierr = MPI_Isend(request_buffer.data(),
- request_buffer.size() * sizeof(T2),
+ request_buffer.size() * sizeof(AnswerType),
MPI_BYTE,
other_rank,
tag_deliver,
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- NBX<T1, T2>::signal_finish(const MPI_Comm &comm)
+ NBX<RequestType, AnswerType>::signal_finish(const MPI_Comm &comm)
{
#ifdef DEAL_II_WITH_MPI
const auto ierr = MPI_Ibarrier(comm, &barrier_request);
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
bool
- NBX<T1, T2>::all_remotely_originated_receives_are_completed()
+ NBX<RequestType,
+ AnswerType>::all_remotely_originated_receives_are_completed()
{
#ifdef DEAL_II_WITH_MPI
int all_ranks_reached_barrier;
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- NBX<T1, T2>::clean_up_and_end_communication(const MPI_Comm &comm)
+ NBX<RequestType, AnswerType>::clean_up_and_end_communication(
+ const MPI_Comm &comm)
{
(void)comm;
#ifdef DEAL_II_WITH_MPI
- template <typename T1, typename T2>
- PEX<T1, T2>::PEX(Process<T1, T2> &process, const MPI_Comm &comm)
- : Interface<T1, T2>(process, comm)
+ template <typename RequestType, typename AnswerType>
+ PEX<RequestType, AnswerType>::PEX(
+ Process<RequestType, AnswerType> &process,
+ const MPI_Comm & comm)
+ : Interface<RequestType, AnswerType>(process, comm)
{}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
- PEX<T1, T2>::run(
+ PEX<RequestType, AnswerType>::run(
const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- &answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm)
{
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
unsigned int
- PEX<T1, T2>::start_communication(
+ PEX<RequestType, AnswerType>::start_communication(
const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
& create_request,
const MPI_Comm &comm)
{
// pack data which should be sent
auto &send_buffer = send_buffers[i];
- send_buffer =
- (create_request ? create_request(rank) : std::vector<T1>());
+ send_buffer = (create_request ? create_request(rank) :
+ std::vector<RequestType>());
// start to send data
auto ierr = MPI_Isend(send_buffer.data(),
- send_buffer.size() * sizeof(T1),
+ send_buffer.size() * sizeof(RequestType),
MPI_BYTE,
rank,
tag_request,
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- PEX<T1, T2>::answer_one_request(
- const unsigned int index,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- & answer_request,
- const MPI_Comm &comm)
+ PEX<RequestType, AnswerType>::answer_one_request(
+ const unsigned int index,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const MPI_Comm & comm)
{
#ifdef DEAL_II_WITH_MPI
const int tag_request = Utilities::MPI::internal::Tags::
"received. This algorithm does not expect this to happen."));
requesting_processes.insert(other_rank);
- std::vector<T1> buffer_recv;
+ std::vector<RequestType> buffer_recv;
// Actually get the incoming message:
int number_amount;
ierr = MPI_Get_count(&status, MPI_BYTE, &number_amount);
AssertThrowMPI(ierr);
- Assert(number_amount % sizeof(T1) == 0, ExcInternalError());
+ Assert(number_amount % sizeof(RequestType) == 0, ExcInternalError());
- buffer_recv.resize(number_amount / sizeof(T1));
+ buffer_recv.resize(number_amount / sizeof(RequestType));
ierr = MPI_Recv(buffer_recv.data(),
number_amount,
MPI_BYTE,
auto &request_buffer = requests_buffers[index];
request_buffer =
(answer_request ? answer_request(other_rank, buffer_recv) :
- std::vector<T2>());
+ std::vector<AnswerType>());
ierr = MPI_Isend(request_buffer.data(),
- request_buffer.size() * sizeof(T2),
+ request_buffer.size() * sizeof(AnswerType),
MPI_BYTE,
other_rank,
tag_deliver,
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- PEX<T1, T2>::process_incoming_answers(
+ PEX<RequestType, AnswerType>::process_incoming_answers(
const unsigned int n_targets,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm)
{
const int ierr = MPI_Get_count(&status, MPI_BYTE, &message_size);
AssertThrowMPI(ierr);
}
- Assert(message_size % sizeof(T2) == 0, ExcInternalError());
- std::vector<T2> recv_buffer(message_size / sizeof(T2));
+ Assert(message_size % sizeof(AnswerType) == 0, ExcInternalError());
+ std::vector<AnswerType> recv_buffer(message_size /
+ sizeof(AnswerType));
// Now actually receive the answer. Because the MPI_Probe
// above blocks until we have a message, we know that the
// following MPI_Recv call will immediately succeed.
{
const int ierr = MPI_Recv(recv_buffer.data(),
- recv_buffer.size() * sizeof(T2),
+ recv_buffer.size() * sizeof(AnswerType),
MPI_BYTE,
other_rank,
tag_deliver,
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
void
- PEX<T1, T2>::clean_up_and_end_communication()
+ PEX<RequestType, AnswerType>::clean_up_and_end_communication()
{
#ifdef DEAL_II_WITH_MPI
// Finalize all MPI_Request objects for both the
- template <typename T1, typename T2>
- Serial<T1, T2>::Serial(Process<T1, T2> &process, const MPI_Comm &comm)
- : Interface<T1, T2>(process, comm)
+ template <typename RequestType, typename AnswerType>
+ Serial<RequestType, AnswerType>::Serial(
+ Process<RequestType, AnswerType> &process,
+ const MPI_Comm & comm)
+ : Interface<RequestType, AnswerType>(process, comm)
{}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
- Serial<T1, T2>::run(
+ Serial<RequestType, AnswerType>::run(
const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- &answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm)
{
// Since the caller indicates that there is a target, and since we
// know that it is the current process, let the process send
// something to itself.
- const std::vector<T1> request =
- (create_request ? create_request(0) : std::vector<T1>());
- const std::vector<T2> answer =
- (answer_request ? answer_request(0, request) : std::vector<T2>());
+ const std::vector<RequestType> request =
+ (create_request ? create_request(0) : std::vector<RequestType>());
+ const std::vector<AnswerType> answer =
+ (answer_request ? answer_request(0, request) :
+ std::vector<AnswerType>());
if (process_answer)
process_answer(0, answer);
- template <typename T1, typename T2>
- Selector<T1, T2>::Selector(Process<T1, T2> &process, const MPI_Comm &comm)
- : Interface<T1, T2>(process, comm)
+ template <typename RequestType, typename AnswerType>
+ Selector<RequestType, AnswerType>::Selector(
+ Process<RequestType, AnswerType> &process,
+ const MPI_Comm & comm)
+ : Interface<RequestType, AnswerType>(process, comm)
{}
- template <typename T1, typename T2>
+ template <typename RequestType, typename AnswerType>
std::vector<unsigned int>
- Selector<T1, T2>::run(
+ Selector<RequestType, AnswerType>::run(
const std::vector<unsigned int> &targets,
- const std::function<std::vector<T1>(const unsigned int)>
- &create_request,
- const std::function<std::vector<T2>(const unsigned int,
- const std::vector<T1> &)>
- &answer_request,
- const std::function<void(const unsigned int, const std::vector<T2> &)>
+ const std::function<std::vector<RequestType>(const unsigned int)>
+ & create_request,
+ const std::function<std::vector<AnswerType>(
+ const unsigned int,
+ const std::vector<RequestType> &)> &answer_request,
+ const std::function<void(const unsigned int,
+ const std::vector<AnswerType> &)>
& process_answer,
const MPI_Comm &comm)
{
# else
if (n_procs > 99)
# endif
- consensus_algo.reset(new NBX<T1, T2>());
+ consensus_algo.reset(new NBX<RequestType, AnswerType>());
else
#endif
if (n_procs > 1)
- consensus_algo.reset(new PEX<T1, T2>());
+ consensus_algo.reset(new PEX<RequestType, AnswerType>());
else
- consensus_algo.reset(new Serial<T1, T2>());
+ consensus_algo.reset(new Serial<RequestType, AnswerType>());
return consensus_algo->run(
targets, create_request, answer_request, process_answer, comm);