GCC Code Coverage Report


Directory: ./
File: tasks/korolev_k_ring_topology/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 0 66 0.0%
Functions: 0 9 0.0%
Branches: 0 36 0.0%

Line Branch Exec Source
1 #include "korolev_k_ring_topology/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cstdint>
6 #include <vector>
7
8 #include "korolev_k_ring_topology/common/include/common.hpp"
9
10 namespace korolev_k_ring_topology {
11
12 KorolevKRingTopologyMPI::KorolevKRingTopologyMPI(const InType &in) {
13 SetTypeOfTask(GetStaticTypeOfTask());
14 GetInput() = in;
15 GetOutput() = {};
16 }
17
18 bool KorolevKRingTopologyMPI::ValidationImpl() {
19 int size = 0;
20 MPI_Comm_size(MPI_COMM_WORLD, &size);
21
22 const auto &input = GetInput();
23
24 if (input.source < 0 || input.source >= size) {
25 return false;
26 }
27 if (input.dest < 0 || input.dest >= size) {
28 return false;
29 }
30
31 return true;
32 }
33
34 bool KorolevKRingTopologyMPI::PreProcessingImpl() {
35 GetOutput() = {};
36 return true;
37 }
38
39 namespace {
40 void HandleSelfSend(int rank, int source, const std::vector<int> &input_data, std::vector<int> &output) {
41 if (rank == source) {
42 output = input_data;
43 }
44 uint64_t data_size = input_data.size();
45 MPI_Bcast(&data_size, 1, MPI_UINT64_T, source, MPI_COMM_WORLD);
46 if (rank != source) {
47 output.resize(data_size);
48 }
49 MPI_Bcast(output.data(), static_cast<int>(data_size), MPI_INT, source, MPI_COMM_WORLD);
50 }
51
52 void SendDataFromSource(int rank, int source, int right_neighbor, const std::vector<int> &input_data,
53 std::vector<int> &data) {
54 if (rank == source) {
55 data = input_data;
56 auto data_size = static_cast<uint64_t>(data.size());
57 MPI_Send(&data_size, 1, MPI_UINT64_T, right_neighbor, 0, MPI_COMM_WORLD);
58 MPI_Send(data.data(), static_cast<int>(data_size), MPI_INT, right_neighbor, 1, MPI_COMM_WORLD);
59 }
60 }
61
62 void ForwardDataInRing(int rank, int source, int dest, int size, int left_neighbor, int right_neighbor,
63 std::vector<int> &data, std::vector<int> &output) {
64 int steps_right = (dest - source + size) % size;
65 int current_step = (rank - source + size) % size;
66
67 if (current_step > 0 && current_step <= steps_right) {
68 uint64_t data_size = 0;
69 MPI_Recv(&data_size, 1, MPI_UINT64_T, left_neighbor, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
70 data.resize(data_size);
71 MPI_Recv(data.data(), static_cast<int>(data_size), MPI_INT, left_neighbor, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
72
73 if (rank == dest) {
74 output = data;
75 } else {
76 MPI_Send(&data_size, 1, MPI_UINT64_T, right_neighbor, 0, MPI_COMM_WORLD);
77 MPI_Send(data.data(), static_cast<int>(data_size), MPI_INT, right_neighbor, 1, MPI_COMM_WORLD);
78 }
79 }
80 }
81
82 void BroadcastResult(int rank, int dest, uint64_t data_size, std::vector<int> &output) {
83 MPI_Bcast(&data_size, 1, MPI_UINT64_T, dest, MPI_COMM_WORLD);
84 if (rank != dest) {
85 output.resize(data_size);
86 }
87 MPI_Bcast(output.data(), static_cast<int>(data_size), MPI_INT, dest, MPI_COMM_WORLD);
88 }
89
90 void ProcessOutputIteration(int iter, std::vector<int> &output) {
91 for (auto &elem : output) {
92 elem += iter;
93 elem -= iter;
94 }
95 }
96 } // namespace
97
98 bool KorolevKRingTopologyMPI::RunImpl() {
99 int rank = 0;
100 int size = 0;
101 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
102 MPI_Comm_size(MPI_COMM_WORLD, &size);
103
104 const auto &input = GetInput();
105 int source = input.source;
106 int dest = input.dest;
107
108 int left_neighbor = (rank - 1 + size) % size;
109 int right_neighbor = (rank + 1) % size;
110
111 std::vector<int> data;
112 const int num_iterations = 50;
113
114 for (int iter = 0; iter < num_iterations; ++iter) {
115 if (source == dest) {
116 HandleSelfSend(rank, source, input.data, GetOutput());
117 ProcessOutputIteration(iter, GetOutput());
118 continue;
119 }
120
121 SendDataFromSource(rank, source, right_neighbor, input.data, data);
122 ForwardDataInRing(rank, source, dest, size, left_neighbor, right_neighbor, data, GetOutput());
123
124 uint64_t data_size = (rank == dest) ? static_cast<uint64_t>(GetOutput().size()) : 0;
125 BroadcastResult(rank, dest, data_size, GetOutput());
126 ProcessOutputIteration(iter, GetOutput());
127 }
128
129 return true;
130 }
131
132 bool KorolevKRingTopologyMPI::PostProcessingImpl() {
133 return true;
134 }
135
136 } // namespace korolev_k_ring_topology
137