GCC Code Coverage Report


Directory: ./
File: tasks/konstantinov_s_elem_vec_sign_change_count/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 53 55 96.4%
Functions: 5 6 83.3%
Branches: 30 44 68.2%

Line Branch Exec Source
1 #include "konstantinov_s_elem_vec_sign_change_count/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4 // #include <numeric>
5 #include <cstring>
6 #include <vector>
7 // #include<iostream>
8
9 #include "konstantinov_s_elem_vec_sign_change_count/common/include/common.hpp"
10 // #include "util/include/util.hpp"
11
12 namespace konstantinov_s_elem_vec_sign_change_count {
13
14
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 KonstantinovSElemVecSignChangeMPI::KonstantinovSElemVecSignChangeMPI(const InType &in) {
15 SetTypeOfTask(GetStaticTypeOfTask());
16
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 GetInput() = in;
17 20 GetOutput() = 0;
18 20 }
19
20 20 bool KonstantinovSElemVecSignChangeMPI::ValidationImpl() {
21 // std::cout << "\t\tValidation mpi\n";
22 20 return !GetInput().empty();
23 }
24
25 20 bool KonstantinovSElemVecSignChangeMPI::PreProcessingImpl() {
26 20 return true;
27 }
28
29 void KonstantinovSElemVecSignChangeMPI::CountSignChange(int &res, const EType *data, int start, int iterations) {
30
4/6
✓ Branch 0 taken 1250028 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 1250034 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2500082 for (int i = start; i < iterations; i++) {
31 // std::cout<<"C "<<data[i] << " | "<< data[i + 1]<<std::endl;
32 2500062 res += static_cast<int>((data[i] > 0) != (data[i + 1] > 0));
33 }
34
35 // for (int i = elemcount - rem; i < elemcount - 1; i++) {
36 // // std::cout<<sendbuf[i];
37 // local_res += static_cast<int>((sendbuf[i] > 0) != (sendbuf[i + 1] > 0));
38 // }
39
40 // for (int i = 0; i < step; i++) {
41 // local_res += static_cast<int>((recbuf[i] > 0) != (recbuf[i + 1] > 0));
42 // }
43 }
44
45 20 bool KonstantinovSElemVecSignChangeMPI::RunImpl() {
46 20 int pcount = 0;
47 20 MPI_Comm_size(MPI_COMM_WORLD, &pcount);
48 20 int rank = 0;
49 20 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
50 20 int step = 0; // chunk size = step+1
51 EType *sendbuf = nullptr;
52 int rem = 0;
53 int elemcount = 0; // не пересылается, известен только корню
54
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank == 0) {
55 10 auto input = GetInput(); // получаем только на нулевом процессе - корне
56 10 elemcount = static_cast<int>(input.size());
57 // sendbuf = input.data(); //input инвалидируется позже????
58
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
10 sendbuf = new EType[elemcount];
59 10 std::memcpy(sendbuf, input.data(), input.size() * sizeof(EType));
60 // нужно для перекрывающихся областей pcount= 3 [5] 6/3=2 -> 012 234 4
61 10 step = elemcount / pcount;
62 10 rem = elemcount - (step * (pcount - 1));
63 }
64
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (step < 2) {
65 10 step = 0;
66 rem = elemcount;
67 }
68
69 20 MPI_Bcast(&step, 1, MPI_INT, 0, MPI_COMM_WORLD); // корень отправляет, остальные получают
70 20 int chunksz = step + 1;
71 int *sendcounts = nullptr;
72 int *displs = nullptr;
73 EType *recbuf = nullptr;
74
75
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank == 0) {
76 // std::cout<<"elems "<<elemcount<<" step "<<step<<" full "<<step*(pcount-1)<<" rem "<<rem<<std::endl;
77
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 sendcounts = new int[pcount];
78
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 displs = new int[pcount];
79 10 sendcounts[0] = 0; // на корень не шлём
80 10 displs[0] = 0;
81 // обозначаем перекрывающиеся области (последний элемент = первый в следующем куске)
82
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int i = 1; i < pcount; i++) {
83 10 sendcounts[i] = chunksz;
84 10 displs[i] = (i - 1) * step;
85
86 // std::cout<<"R "<<i<<" > "<<sendbuf[displs[i]]<<std::endl;
87 }
88 } else {
89
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 recbuf = new EType[chunksz]; // только некорни выыделяют буфер
90 }
91
92 // существуют только буферы нужные получателям/отправителю, ненужные = nullptr (например sendbuf у некорней)
93 // rank0: sendbuf, sendcounts, displs
94 // rank1+: recbuf
95
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
30 MPI_Scatterv(sendbuf, sendcounts, displs, MPI_DOUBLE, recbuf, rank == 0 ? 0 : chunksz, MPI_DOUBLE, 0, MPI_COMM_WORLD);
96
97 // if(rank!=0){
98 // std::cout<<"RANK "<<rank<<" got: ";
99 // for(int i=0;i<chunksz;i++)
100 // {
101 // std::cout<<recbuf[i]<<" ";
102 // }
103 // std::cout<<"\n\n";
104 // }else{
105 // std::cout<<"INPUT: ";
106 // for(int i=0;i<elemcount;i++)
107 // std::cout<<sendbuf[i]<<" ";
108 // std::cout<<"\n";
109 // std::cout<<"ROOT "<<rank<<" got: ";
110 // for(int i=elemcount-rem;i<elemcount;i++)
111 // std::cout<<sendbuf[i]<<" ";
112 // std::cout<<"\n";
113
114 // }
115
116 20 int local_res = 0;
117
118
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank == 0) {
119
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 delete[] sendcounts;
120
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 delete[] displs;
121
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (rem > 1) {
122 10 CountSignChange(local_res, sendbuf, elemcount - rem, elemcount - 1);
123 }
124
125 } else {
126 10 CountSignChange(local_res, recbuf, 0, step);
127 }
128 // std::cout<<"RANK "<<rank<<" counted "<<local_res<<std::endl;
129
130 // rank0: sendbuf
131 // rank1+: recbuf
132
133
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank == 0) {
134
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 delete[] sendbuf;
135 } else {
136
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 delete[] recbuf;
137 }
138
139 // all memory deleted
140
141 20 int global_res = 0;
142 20 MPI_Allreduce(&local_res, &global_res, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
143
144 // std::cout<<"MPI result: "<<global_res<<" from rank "<<rank<<"\n";
145 20 GetOutput() = global_res;
146 20 return true;
147 }
148
149 20 bool KonstantinovSElemVecSignChangeMPI::PostProcessingImpl() {
150 20 return true;
151 }
152
153 } // namespace konstantinov_s_elem_vec_sign_change_count
154