This commit is contained in:
Lisa Pizzo 2026-01-09 13:21:08 +01:00
commit 321e250973
4 changed files with 220 additions and 0 deletions

23
Sheet7/Ex_5678/Makefile Normal file
View file

@ -0,0 +1,23 @@
#
# Compile with
# make 2>&1 | grep -v openmpi
# to avoid warnings caused by OpenMPI
# use GNU-Compiler tools
COMPILER=GCC_
# alternatively from the shell
# export COMPILER=GCC_
# or, alternatively from the shell
# make COMPILER=GCC_
MAIN = main
SOURCES = ${MAIN}.cpp VecFuncs.cpp
OBJECTS = $(SOURCES:.cpp=.o)
PROGRAM = ${MAIN}.${COMPILER}
# uncomment the next to lines for debugging and detailed performance analysis
CXXFLAGS += -g
LINKFLAGS +=
include ../${COMPILER}default.mk

117
Sheet7/Ex_5678/VecFuncs.cpp Normal file
View file

@ -0,0 +1,117 @@
#include "VecFuncs.h"
#include <vector>
#include <iostream>
#include <cassert>
#include <cfloat>
void DebugVector(const std::vector<double>& xin, MPI_Comm icomm)
{
int rank, size;
MPI_Comm_rank(icomm, &rank);
MPI_Comm_size(icomm, &size);
int ierr;
int active_rank = -1;
for (int step = 0; step < size; ++step)
{
if (rank == 0)
{
std::cout << "Enter rank to display vector: " << std::endl;
std::cin >> active_rank;
}
ierr = MPI_Bcast(&active_rank, 1, MPI_INT, 0, icomm);
assert(ierr == 0);
MPI_Barrier(icomm);
if (rank == active_rank)
{
std::cout << "Output from process " << rank << std::endl;
for (size_t i = 0; i < xin.size(); ++i)
{
std::cout << "xin[" << i << "] = " << xin[i] << std::endl;
}
std::cout << std::endl;
}
MPI_Barrier(icomm);
}
}
double par_scalar(const std::vector<double> &x, const std::vector<double> &y, const MPI_Comm &comm) {
assert(x.size()==y.size());
double local_sum = 0.0;
for (int k = 0; k < x.size(); ++k) {
local_sum += x[k] * y[k];
}
double global_sum = 0.0;
int mpi_error = MPI_Allreduce(&local_sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, comm);
assert(mpi_error == 0);
return global_sum;
}
void par_minmax(std::vector<double> &x, double &min_value, double &max_value, const MPI_Comm &icomm)
{
int myrank;
MPI_Comm_rank(icomm, &myrank);
int local_n = x.size();
int global_offset = myrank * local_n;
struct {double value; int idx;} local_min, local_max, global_min, global_max; // global index
local_min.value = local_max.value = x[0];
local_min.idx = local_max.idx = global_offset;
// finding local min/max with the corresponding global index
for (int i = 1; i < local_n; ++i) {
int global_idx = global_offset + i;
if (x[i] < local_min.value){
local_min.value = x[i];
local_min.idx = global_idx;
}
if (x[i] > local_max.value){
local_max.value = x[i];
local_max.idx = global_idx;
}
}
// reduction to the global one including the global index (need it later for interchanging)
MPI_Allreduce(&local_min, &global_min, 1, MPI_DOUBLE_INT, MPI_MINLOC, icomm);
MPI_Allreduce(&local_max, &global_max, 1, MPI_DOUBLE_INT, MPI_MAXLOC, icomm);
min_value = global_min.value;
max_value = global_max.value;
// calculating the process and the local index for interchanging the min and max value
int rank_min = global_min.idx / local_n;
int rank_max = global_max.idx / local_n;
int local_min_idx = global_min.idx % local_n;
int local_max_idx = global_max.idx % local_n;
// interchanging
if (rank_min == rank_max){
std::swap(x[local_min_idx], x[local_max_idx]);
}
else {
double recv_value;
if (myrank == rank_min){
MPI_Sendrecv(&x[local_min_idx], 1, MPI_DOUBLE, rank_max, 0, &recv_value, 1, MPI_DOUBLE, rank_max, 0, icomm, MPI_STATUS_IGNORE);
x[local_min_idx] = recv_value;
}
if (myrank == rank_max){
MPI_Sendrecv(&x[local_max_idx], 1, MPI_DOUBLE, rank_min, 0, &recv_value, 1, MPI_DOUBLE, rank_min, 0, icomm, MPI_STATUS_IGNORE);
x[local_max_idx] = recv_value;
}
}
return;
}

13
Sheet7/Ex_5678/VecFuncs.h Normal file
View file

@ -0,0 +1,13 @@
#pragma once
#include <vector>
#include <mpi.h>
#include <iostream>
#include <cassert>
#include <cfloat>
void DebugVector(const std::vector<double>& xin, MPI_Comm icomm);
double par_scalar(const std::vector<double> &x, const std::vector<double> &y, const MPI_Comm &icomm);
void par_minmax(std::vector<double> &x, double &min_val, double &max_val, const MPI_Comm &icomm);

67
Sheet7/Ex_5678/main.cpp Normal file
View file

@ -0,0 +1,67 @@
#include <iostream>
#include <mpi.h>
#include <vector>
#include "VecFuncs.h"
using namespace std;
int main(int argc, char** argv)
{
MPI_Init(&argc, &argv);
MPI_Comm icomm = MPI_COMM_WORLD;
int myrank;
MPI_Comm_rank(icomm, &myrank);
int n = 20;
vector<double> x(n);
vector<double> y = x;
for (int i = 0; i < n; ++i)
{
x[i] = myrank*100 + (i % 5)*10 + i;
y[i] = 1.0/(x[i]);
}
if(myrank == 0) // so scalar product is well defined (avoid division by 0)
y[0] = 0;
//E5
if (myrank == 0) cout << "E5" << endl;
DebugVector(x, icomm);
//E6
if (myrank == 0) cout << "E6" << endl;
double scalar_product = par_scalar(x, y, icomm);
if (myrank == 0)
{
cout << "<x,y> = " << scalar_product << endl << endl;
}
// E7
if (myrank == 0) cout << "E7" << endl;
double xmin, xmax;
par_minmax(x, xmin, xmax, icomm);
if (myrank == 0)
{
cout << "Global min: " << xmin << endl;
cout << "Global max: " << xmax << endl << endl;
}
// E8
if (myrank == 0) cout << "E8" << endl;
vector<double> x_new(n);
// All to all
if (myrank == 0) cout << "All to all" << endl;
MPI_Alltoall(x.data(), 5, MPI_DOUBLE, x_new.data(), 5, MPI_DOUBLE, icomm);
DebugVector(x_new, icomm);
if (myrank == 0) cout << "All to all (in place)" << endl;
MPI_Alltoall(MPI_IN_PLACE, 0, MPI_DOUBLE, x.data(), 5, MPI_DOUBLE, icomm);
DebugVector(x, icomm);
MPI_Finalize();
return 0;
}