GCC Code Coverage Report


Directory: gridformat/
File: gridformat/parallel/helpers.hpp
Date: 2026-10-12 17:50:57
Exec Total Coverage
Lines: 21 23 91.3%
Functions: 97 99 98.0%
Branches: 20 33 60.6%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de>
2 // SPDX-License-Identifier: MIT
3 /*!
4 * \file
5 * \ingroup Parallel
6 * \brief Helper functions for parallel computations.
7 */
8 #ifndef GRIDFORMAT_PARALLEL_HELPERS_HPP_
9 #define GRIDFORMAT_PARALLEL_HELPERS_HPP_
10
11 #include <array>
12 #include <ranges>
13 #include <string>
14 #include <concepts>
15 #include <exception>
16
17 #include <gridformat/common/exceptions.hpp>
18 #include <gridformat/parallel/concepts.hpp>
19 #include <gridformat/parallel/communication.hpp>
20
21 namespace GridFormat::Parallel {
22
23 //! \addtogroup Parallel
24 //! \{
25
26 struct Index {
27 std::size_t i;
28 int rank;
29 };
30
31 //! Access an entry in a vector containing N elements per process for the given rank and index
32 template<std::size_t N, Concepts::Communicator C, std::ranges::contiguous_range R>
33 45620 decltype(auto) access_gathered(R&& values, const C& comm, const Index& index) {
34
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 23070 times.
45620 if (std::ranges::size(values) != N*size(comm))
35 ✗ throw SizeError("Range size does not match number of processors times N");
36 45620 return std::ranges::data(std::forward<R>(values))[index.rank*N + index.i];
37 }
38
39 //! Get all entries from a vector containing N elements per process for the given rank
40 template<std::size_t N, Concepts::Communicator C, std::ranges::contiguous_range R>
41 12623 auto access_gathered(R&& values, const C& comm, int rank) {
42
3/4
✓ Branch 2 taken 1454 times.
✓ Branch 3 taken 4961 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1454 times.
12623 if (std::ranges::size(values) != N*size(comm))
43 ✗ throw SizeError("Range size does not match number of processors times N");
44 std::array<std::ranges::range_value_t<R>, N> result;
45
2/2
✓ Branch 0 taken 17788 times.
✓ Branch 1 taken 6415 times.
47785 for (std::size_t i = 0; i < N; ++i)
46 35162 result[i] = std::ranges::data(std::forward<R>(values))[rank*N + i];
47 12623 return result;
48 }
49
50 //! Return a range over all ranks of the given communicator
51 template<Concepts::Communicator C>
52 4292 std::ranges::view auto ranks(const C& comm) {
53
3/5
✓ Branch 1 taken 4284 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4284 times.
✗ Branch 5 not taken.
4292 return std::views::iota(0, size(comm));
54 }
55
56 /*!
57 * \brief Invoke the given action on all ranks and throw on all ranks if it threw on any of them.
58 * \details Must be called collectively. The exception is rethrown on the ranks where it occurred,
59 * and an IOError stating that the given operation failed is thrown on all other ranks.
60 */
61 template<Concepts::Communicator C, std::invocable Action>
62 26220 void invoke_collectively(const C& comm, Action&& action, const std::string& operation) {
63 26220 std::exception_ptr error;
64 try {
65
2/2
✓ Branch 1 taken 12610 times.
✓ Branch 2 taken 505 times.
26220 action();
66 1010 } catch (...) {
67
1/2
✓ Branch 4 taken 505 times.
✗ Branch 5 not taken.
1010 error = std::current_exception();
68 }
69 26220 const int root = 0;
70
4/6
✓ Branch 3 taken 13115 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 13115 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 516 times.
✓ Branch 10 taken 12599 times.
26220 if (broadcast(comm, max(comm, static_cast<int>(error != nullptr), root), root)) {
71
2/2
✓ Branch 1 taken 505 times.
✓ Branch 2 taken 11 times.
1032 if (error)
72 2020 std::rethrow_exception(error);
73
2/4
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
22 throw IOError(operation + " failed on another rank");
74 }
75 26220 }
76
77 //! \} group Parallel
78
79 } // namespace GridFormat::Parallel
80
81 #endif // GRIDFORMAT_PARALLEL_HELPERS_HPP_
82