149 lines
No EOL
4.7 KiB
C++
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;
|
|
} |