scf_celebic/ex7/code/task3/main.cpp
dino.celebic 2467b9ae03 ex7
2025-12-26 20:26:31 +01:00

149 lines
No EOL
4.7 KiB
C++

#include <algorithm>
#include <iostream>
#include <mpi.h>
#include <vector>
using namespace std;
void DebugVector(const vector<double> &xin, MPI_Comm icomm) {
int rank, size;
MPI_Comm_rank(icomm, &rank);
MPI_Comm_size(icomm, &size);
int next_process = 0;
while (next_process != -1) {
// Print the local vector for each process
if (rank==next_process){
cout << "x_" << rank << " = ";
for (const auto& value : xin) {
cout << value << " ";
}
cout << endl;
}
MPI_Barrier(icomm);
if (rank == 0) {
cout << "Enter rank (0-" << size - 1 << ") or -1 to exit: ";
cin >> next_process;
}
MPI_Bcast(&next_process, 1, MPI_INT, 0, icomm);
MPI_Barrier(icomm);
}
}
double par_scalar(const vector<double>& x, const vector<double>& y, MPI_Comm icomm) {
double local_dot = 0.0;
for (size_t i = 0; i < x.size(); ++i) {
local_dot += x[i] * y[i];
}
double global_dot = 0.0;
MPI_Allreduce(&local_dot, &global_dot, 1, MPI_DOUBLE, MPI_SUM, icomm);
return global_dot;
}
tuple<double,double> find_global_minmax(const vector<double>& xin, MPI_Comm icomm) {
int rank, size;
MPI_Comm_rank(icomm, &rank);
MPI_Comm_size(icomm, &size);
// Find local min/max
double local_min = *min_element(xin.begin(), xin.end());
double local_max = *max_element(xin.begin(), xin.end());
// Gather local mins/maxs in vector
vector<double> local_min_vector(size);
vector<double> local_max_vector(size);
MPI_Gather(&local_min, 1, MPI_DOUBLE, local_min_vector.data(), 1, MPI_DOUBLE, 0, icomm);
MPI_Gather(&local_max, 1, MPI_DOUBLE, local_max_vector.data(), 1, MPI_DOUBLE, 0, icomm);
// Find global min/max
double global_min(0);
double global_max(0);
if (rank==0) {
global_min = *min_element(local_min_vector.begin(), local_min_vector.end());
global_max = *max_element(local_max_vector.begin(), local_max_vector.end());
}
// Broadcast global min/max
MPI_Bcast(&global_min, 1, MPI_DOUBLE, 0, icomm);
MPI_Bcast(&global_max, 1, MPI_DOUBLE, 0, icomm);
return make_tuple(global_min, global_max);
}
tuple<double,double> find_global_minmax_Allreduce(const vector<double>& xin, MPI_Comm icomm) {
double local_min = *min_element(xin.begin(), xin.end());
double local_max = *max_element(xin.begin(), xin.end());
double global_min(0);
double global_max(0);
MPI_Allreduce(&local_min, &global_min, 1, MPI_DOUBLE, MPI_MIN, icomm);
MPI_Allreduce(&local_max, &global_max, 1, MPI_DOUBLE, MPI_MAX, icomm);
return make_tuple(global_min, global_max);
}
int main(int argc, char *argv[]) {
MPI_Comm icomm = MPI_COMM_WORLD;
MPI_Init(&argc, &argv);
int rank, size;
MPI_Comm_rank(icomm, &rank);
MPI_Comm_size(icomm, &size);
if (rank==0) {
cout << "\n There are " << size << " processes running.\n";
}
// Create vectors
size_t n=20;
vector<double> local_vector(n);
vector<double> local_vector_inv(n);
for (size_t i=0; i<n; ++i) {
// local_vector[i] = rank*n + i+1;
// local_vector_inv[i] = 1.0/(local_vector[i]);
local_vector[i] = rank*100.0 + (i%5)*10.0 + i; // EX8
local_vector_inv[i] = 1.0/(local_vector[i]+1.0);
}
MPI_Barrier(icomm);
if (rank == 0) {printf("\n\n-------------- Task 5 --------------\n\n");}
DebugVector(local_vector, icomm);
MPI_Barrier(icomm);
if (rank == 0) {printf("\n\n-------------- Task 6 --------------\n\n");}
double result = par_scalar(local_vector, local_vector_inv, icomm);
if (rank == 0) {printf("Global scalar product: %f\n", result);}
MPI_Barrier(icomm);
if (rank == 0) {printf("\n\n-------------- Task 7 --------------\n\n");}
auto [min, max] = find_global_minmax(local_vector, icomm);
if (rank == 0) {printf("Global min: %.0f | global max: %.0f\n\n", min, max);}
MPI_Barrier(icomm);
tuple(min, max) = find_global_minmax_Allreduce(local_vector, icomm);
if (rank == 0) {printf("Global min: %.0f | global max: %.0f\n", min, max);}
MPI_Barrier(icomm);
if (rank == 0) {printf("\n\n-------------- Task 8 --------------\n\n");}
if (rank == 0) {printf("\n---- MPI_Alltoall ----\n");}
vector<double> recv(n);
MPI_Alltoall(local_vector.data(), 5, MPI_DOUBLE, recv.data(), 5, MPI_DOUBLE, icomm);
DebugVector(recv, icomm);
MPI_Barrier(icomm);
if (rank == 0) {printf("\n---- MPI_Alltoall using MPI_IN_PLACE ----\n");}
MPI_Alltoall(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, local_vector.data(), 5, MPI_DOUBLE, icomm);
DebugVector(local_vector, icomm);
MPI_Finalize();
return 0;
}