GCC Code Coverage Report


Directory: ./
File: tasks/likhanov_m_hypercube/mpi/src/ops_mpi.cpp
Date: 2026-02-23 23:20:07
Exec Total Coverage
Lines: 0 49 0.0%
Functions: 0 7 0.0%
Branches: 0 32 0.0%

Line Branch Exec Source
1 #include "likhanov_m_hypercube/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cmath>
6 #include <cstdint>
7
8 #include "likhanov_m_hypercube/common/include/common.hpp"
9
10 namespace likhanov_m_hypercube {
11
12 LikhanovMHypercubeMPI::LikhanovMHypercubeMPI(const InType &in) {
13 SetTypeOfTask(GetStaticTypeOfTask());
14 GetInput() = in;
15 GetOutput() = 0;
16 }
17
18 bool LikhanovMHypercubeMPI::ValidationImpl() {
19 int size = 0;
20 MPI_Comm_size(MPI_COMM_WORLD, &size);
21
22 return size > 0 && ((size & (size - 1)) == 0);
23 }
24
25 bool LikhanovMHypercubeMPI::PreProcessingImpl() {
26 GetOutput() = 0;
27 return true;
28 }
29
30 bool LikhanovMHypercubeMPI::RunImpl() {
31 int rank = 0;
32 int size = 0;
33
34 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
35 MPI_Comm_size(MPI_COMM_WORLD, &size);
36
37 if (!IsPowerOfTwo(size)) {
38 return false;
39 }
40
41 const int dimension = static_cast<int>(std::log2(size));
42 const InType n = GetInput();
43
44 const std::uint64_t vertices = static_cast<std::uint64_t>(1) << n;
45
46 const auto u_rank = static_cast<std::uint64_t>(rank);
47 const auto u_size = static_cast<std::uint64_t>(size);
48
49 const std::uint64_t chunk = vertices / u_size;
50 const std::uint64_t remainder = vertices % u_size;
51
52 const std::uint64_t start = (u_rank * chunk) + (u_rank < remainder ? u_rank : remainder);
53
54 const std::uint64_t local_size = chunk + (u_rank < remainder ? 1ULL : 0ULL);
55
56 const std::uint64_t end = start + local_size;
57
58 std::uint64_t local_edges = ComputeLocalEdges(start, end, n);
59
60 std::uint64_t sum = local_edges;
61
62 for (int k = 0; k < dimension; ++k) {
63 int partner = rank ^ (1 << k);
64
65 if ((rank & (1 << k)) != 0) {
66 MPI_Send(&sum, 1, MPI_UINT64_T, partner, 0, MPI_COMM_WORLD);
67 break;
68 }
69 if (partner < size) {
70 std::uint64_t received = 0;
71 MPI_Recv(&received, 1, MPI_UINT64_T, partner, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
72 sum += received;
73 }
74 }
75
76 MPI_Bcast(&sum, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD);
77
78 GetOutput() = static_cast<OutType>(sum);
79
80 return true;
81 }
82
83 bool LikhanovMHypercubeMPI::IsPowerOfTwo(int value) {
84 return value > 0 && ((value & (value - 1)) == 0);
85 }
86
87 std::uint64_t LikhanovMHypercubeMPI::ComputeLocalEdges(std::uint64_t start, std::uint64_t end, InType n) {
88 std::uint64_t local_edges = 0;
89
90 for (std::uint64_t vertex = start; vertex < end; ++vertex) {
91 for (InType bit = 0; bit < n; ++bit) {
92 const std::uint64_t neighbor = vertex ^ (1ULL << bit);
93 if (vertex < neighbor) {
94 ++local_edges;
95 }
96 }
97 }
98
99 return local_edges;
100 }
101
102 bool LikhanovMHypercubeMPI::PostProcessingImpl() {
103 return true;
104 }
105
106 } // namespace likhanov_m_hypercube
107