| 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 |