GCC Code Coverage Report


Directory: gridformat/
File: gridformat/parallel/helpers.hpp
Date: 2026-10-18 00:09:19
Exec Total Coverage
Lines: 22 23 95.7%
Functions: 139 144 96.5%
Branches: 22 33 66.7%

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 45621 decltype(auto) access_gathered(R&& values, const C& comm, const Index& index) {
34
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 23070 times.
45621 if (std::ranges::size(values) != N*size(comm))
35
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 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 12625 auto access_gathered(R&& values, const C& comm, int rank) {
42
3/4
✓ Branch 2 taken 1456 times.
✓ Branch 3 taken 4961 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1456 times.
12625 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 17792 times.
✓ Branch 1 taken 6417 times.
47791 for (std::size_t i = 0; i < N; ++i)
46 35166 result[i] = std::ranges::data(std::forward<R>(values))[rank*N + i];
47 12625 return result;
48 }
49
50 //! Return a range over all ranks of the given communicator
51 template<Concepts::Communicator C>
52 4293 std::ranges::view auto ranks(const C& comm) {
53
3/5
✓ Branch 1 taken 4285 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4285 times.
✗ Branch 5 not taken.
4293 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 44153 void invoke_collectively(const C& comm, Action&& action, const std::string& operation) {
63 44153 std::exception_ptr error;
64 try {
65
2/2
✓ Branch 1 taken 21570 times.
✓ Branch 2 taken 509 times.
44153 action();
66 1018 } catch (...) {
67
1/2
✓ Branch 4 taken 509 times.
✗ Branch 5 not taken.
1018 error = std::current_exception();
68 }
69 44153 const int root = 0;
70
4/6
✓ Branch 3 taken 22079 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 22079 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 522 times.
✓ Branch 10 taken 21557 times.
44153 if (broadcast(comm, max(comm, static_cast<int>(error != nullptr), root), root)) {
71
2/2
✓ Branch 1 taken 509 times.
✓ Branch 2 taken 13 times.
1044 if (error)
72 2036 std::rethrow_exception(error);
73
2/4
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
26 throw IOError(operation + " failed on another rank");
74 }
75 44153 }
76
77 //! \} group Parallel
78
79 } // namespace GridFormat::Parallel
80
81 #endif // GRIDFORMAT_PARALLEL_HELPERS_HPP_
82