GCC Code Coverage Report


Directory: ./
File: tasks/korolev_k_string_word_count/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 60 60 100.0%
Functions: 6 6 100.0%
Branches: 36 52 69.2%

Line Branch Exec Source
1 #include "korolev_k_string_word_count/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cctype>
7 #include <cstddef>
8 #include <cstdint>
9 #include <string>
10
11 #include "korolev_k_string_word_count/common/include/common.hpp"
12
13 namespace korolev_k_string_word_count {
14
15 namespace {
16
17 22 int CountWordsChunk(const std::string &s, std::size_t begin, std::size_t end, bool prev_is_space) {
18
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (begin >= end) {
19 return 0;
20 }
21 int count = 0;
22 bool in_word = false;
23
24 22 auto first = static_cast<unsigned char>(s[begin]);
25 22 bool first_is_space = std::isspace(first) != 0;
26
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
22 if (!first_is_space && prev_is_space) {
27 ++count;
28 }
29 in_word = !first_is_space;
30
31
2/2
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 22 times.
227 for (std::size_t i = begin + 1; i < end; ++i) {
32 205 auto c = static_cast<unsigned char>(s[i]);
33 205 bool is_space = std::isspace(c) != 0;
34
2/2
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 33 times.
205 if (!is_space) {
35
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 157 times.
172 if (!in_word) {
36 15 ++count;
37 in_word = true;
38 }
39 } else {
40 in_word = false;
41 }
42 }
43 return count;
44 }
45
46 } // namespace
47
48
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 KorolevKStringWordCountMPI::KorolevKStringWordCountMPI(const InType &in) {
49 SetTypeOfTask(GetStaticTypeOfTask());
50 GetInput() = in;
51 24 GetOutput() = 0;
52 24 }
53
54 24 bool KorolevKStringWordCountMPI::ValidationImpl() {
55 // Any string is valid.
56 24 return GetOutput() == 0;
57 }
58
59 24 bool KorolevKStringWordCountMPI::PreProcessingImpl() {
60 24 GetOutput() = 0;
61 24 return true;
62 }
63
64 24 bool KorolevKStringWordCountMPI::RunImpl() {
65 24 int rank = 0;
66 24 int size = 1;
67 24 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
68 24 MPI_Comm_size(MPI_COMM_WORLD, &size);
69
70 std::string s;
71 24 uint64_t n = 0;
72
73
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 if (rank == 0) {
74 s = GetInput();
75 12 n = static_cast<uint64_t>(s.size());
76 }
77
78
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 MPI_Bcast(&n, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD);
79
80
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (n == 0) {
81 2 GetOutput() = 0;
82 2 return true;
83 }
84
85 const auto n_size = static_cast<std::size_t>(n);
86 22 const auto size_z = static_cast<std::size_t>(size);
87 22 const std::size_t base = n_size / size_z;
88
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 const std::size_t rem = n_size % size_z;
89
90 std::string local_segment;
91 22 char prev_char = ' ';
92
93
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 if (rank == 0) {
94
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for (int dest = 1; dest < size; ++dest) {
95 11 auto dest_z = static_cast<std::size_t>(dest);
96
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 std::size_t begin_i = (dest_z * base) + std::min(dest_z, rem);
97
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 std::size_t end_i = begin_i + base + (dest_z < rem ? std::size_t{1} : std::size_t{0});
98 11 int segment_len = static_cast<int>(end_i - begin_i);
99
100
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 MPI_Send(&segment_len, 1, MPI_INT, dest, 0, MPI_COMM_WORLD);
101
102
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 char prev = (begin_i > 0) ? s[begin_i - 1] : ' ';
103
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 MPI_Send(&prev, 1, MPI_CHAR, dest, 1, MPI_COMM_WORLD);
104
105
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 MPI_Send(s.data() + begin_i, segment_len, MPI_CHAR, dest, 2, MPI_COMM_WORLD);
106 }
107
108 std::size_t begin_0 = 0;
109
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 std::size_t end_0 = base + (rem > 0 ? std::size_t{1} : std::size_t{0});
110
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 local_segment = s.substr(begin_0, end_0 - begin_0);
111 11 prev_char = ' ';
112 } else {
113 11 int segment_len = 0;
114
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 MPI_Recv(&segment_len, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
115
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 MPI_Recv(&prev_char, 1, MPI_CHAR, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
116
117
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 local_segment.resize(static_cast<std::size_t>(segment_len));
118
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 MPI_Recv(local_segment.data(), segment_len, MPI_CHAR, 0, 2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
119 }
120
121 22 bool prev_is_space = std::isspace(static_cast<unsigned char>(prev_char)) != 0;
122
123
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 int local_count = CountWordsChunk(local_segment, 0, local_segment.size(), prev_is_space);
124
125 22 int global_count = 0;
126
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 MPI_Allreduce(&local_count, &global_count, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
127
128 22 GetOutput() = global_count;
129
130 return true;
131 }
132
133 24 bool KorolevKStringWordCountMPI::PostProcessingImpl() {
134 // Nothing to post-process.
135 24 return true;
136 }
137
138 } // namespace korolev_k_string_word_count
139