Merge branch 'kais_try'
This commit is contained in:
28
lab10/jacobi/comp.py
Normal file
28
lab10/jacobi/comp.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import csv
|
||||
import math
|
||||
|
||||
def compare_csv(file1, file2):
|
||||
with open(file1, newline='') as f1, open(file2, newline='') as f2:
|
||||
reader1 = list(csv.reader(f1))
|
||||
reader2 = list(csv.reader(f2))
|
||||
|
||||
if len(reader1) != len(reader2):
|
||||
print(f"Unterschiedliche Zeilenzahl: {len(reader1)} vs {len(reader2)}")
|
||||
return
|
||||
|
||||
for row_idx, (row1, row2) in enumerate(zip(reader1, reader2), start=1):
|
||||
if len(row1) != len(row2):
|
||||
print(f"Zeile {row_idx}: unterschiedliche Spaltenanzahl")
|
||||
continue
|
||||
for col_idx, (cell1, cell2) in enumerate(zip(row1, row2), start=1):
|
||||
try:
|
||||
if not math.isclose(float(cell1), float(cell2), abs_tol=1e-7):
|
||||
print(f"Unterschied in Zeile {row_idx}, Spalte {col_idx}: {cell1} ≠ {cell2} diff: {abs(float(cell1) - float(cell2))}")
|
||||
except ValueError:
|
||||
# print(f"{cell1}: {cell2}")
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
compare_csv("result_parallel.asc", "result_serial.asc")
|
||||
|
||||
32
lab10/jacobi/creator.py
Normal file
32
lab10/jacobi/creator.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import math
|
||||
import subprocess
|
||||
|
||||
core_counts = [1, 2, 4, 6, 8, 12, 16, 18, 24, 32, 36, 48]
|
||||
cores_per_node = 12
|
||||
max_nodes = 4
|
||||
|
||||
for y in core_counts:
|
||||
x = math.ceil(y / cores_per_node)
|
||||
if x > max_nodes:
|
||||
print(f"Skipping {y} cores: requires more than {max_nodes} nodes.")
|
||||
continue
|
||||
|
||||
filename = f"slurm_{y}.sh"
|
||||
script = f"""#!/bin/bash
|
||||
#SBATCH --job-name=mpi_g5_{y}
|
||||
#SBATCH --output=jacobi_{y}.txt
|
||||
#SBATCH --nodes={x}
|
||||
#SBATCH --ntasks={y}
|
||||
|
||||
srun --mpi=pmix ./jacobi
|
||||
"""
|
||||
|
||||
with open(filename, "w") as f:
|
||||
f.write(script)
|
||||
|
||||
# Submit the job
|
||||
result = subprocess.run(["sbatch", filename], capture_output=True, text=True)
|
||||
if result.returncode == 0:
|
||||
print(f"Submitted {filename}: {result.stdout.strip()}")
|
||||
else:
|
||||
print(f"Failed to submit {filename}: {result.stderr.strip()}")
|
||||
6
lab10/jacobi/do_all.sh
Executable file
6
lab10/jacobi/do_all.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
git pull
|
||||
make
|
||||
python3 creator.py
|
||||
sleep 0.5
|
||||
squeue
|
||||
BIN
lab10/jacobi/efficiency_plot.png
Normal file
BIN
lab10/jacobi/efficiency_plot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -41,7 +41,7 @@ Matrix getCompleteInitialCondition(int n) {
|
||||
return getInitialCondition(n, 0, 1);
|
||||
}
|
||||
|
||||
Matrix run(Jacobi& jacobi, const Matrix& init, double eps, int maxNumIter) {
|
||||
Matrix run(Jacobi &jacobi, const Matrix &init, double eps, int maxNumIter) {
|
||||
auto [m, dist, nIter] = jacobi.run(init, eps, maxNumIter);
|
||||
int rank;
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
|
||||
@@ -52,9 +52,7 @@ Matrix run(Jacobi& jacobi, const Matrix& init, double eps, int maxNumIter) {
|
||||
return m;
|
||||
}
|
||||
|
||||
double benchmark(Jacobi& jacobi,
|
||||
const Matrix& init,
|
||||
double eps,
|
||||
double benchmark(Jacobi &jacobi, const Matrix &init, double eps,
|
||||
int maxNumIter) {
|
||||
auto start = std::chrono::system_clock::now();
|
||||
jacobi.run(init, eps, maxNumIter);
|
||||
@@ -142,7 +140,7 @@ void runParallel(int n, double eps, int maxNumIter) {
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main(int argc, char *argv[]) {
|
||||
MPI_Init(&argc, &argv);
|
||||
|
||||
int rank, numProc;
|
||||
@@ -158,26 +156,24 @@ int main(int argc, char* argv[]) {
|
||||
// Result is saved to file.
|
||||
// Use this to graphically verify the correctness of the parallel
|
||||
// implementation.
|
||||
//runSerial(n, eps, maxNumIter);
|
||||
runSerial(n, eps, maxNumIter);
|
||||
|
||||
runParallel(n, eps, maxNumIter);
|
||||
|
||||
|
||||
// Run the benchmark
|
||||
//double serialTime = 0;
|
||||
double serialTime = 0;
|
||||
double parallelTime = 0;
|
||||
|
||||
//serialTime = serialBenchmark(n, eps, maxNumIter);
|
||||
serialTime = serialBenchmark(n, eps, maxNumIter);
|
||||
parallelTime = parallelBenchmark(n, eps, maxNumIter);
|
||||
|
||||
if (rank == 0) {
|
||||
//std::cout << "Serial time: " << serialTime << "ms" << std::endl;
|
||||
std::cout << "Serial time: ms" << std::endl;
|
||||
std::cout << "Serial time: " << serialTime << "ms" << std::endl;
|
||||
std::cout << "Parallel time: " << parallelTime << "ms" << std::endl;
|
||||
//std::cout << "Speedup: " << serialTime / parallelTime << std::endl;
|
||||
std::cout << "Speedup: " << serialTime / parallelTime << std::endl;
|
||||
std::ofstream fout("benchmark.txt", std::ios::app);
|
||||
fout << numProc << "\t" << parallelTime << "\n";
|
||||
}
|
||||
|
||||
MPI_Finalize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,27 @@
|
||||
#include "jacobi.h"
|
||||
#include "jacobi_main.h"
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
std::vector<double> getFilledBuffer(const Matrix &matrix, int row)
|
||||
{
|
||||
std::vector<double> getFilledBuffer(const Matrix &matrix, int row) {
|
||||
int numCols = matrix.cols();
|
||||
std::vector<double> rowBuffer(numCols);
|
||||
|
||||
// Extract the row (matrix is column-major)
|
||||
for (int j = 0; j < numCols; ++j)
|
||||
{
|
||||
for (int j = 0; j < numCols; ++j) {
|
||||
rowBuffer[j] = matrix(row, j);
|
||||
}
|
||||
return rowBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a matrix and an index indexRowLocal which defines which row of the local matrix has to be sent.
|
||||
*
|
||||
* Sends data of that row via MPI_Send to process with rank receiverRank.
|
||||
*
|
||||
* indexRowGlobal identifies row in the view of the whole matrix, used from receiving process
|
||||
* to identify if lower or upper halo by comparing against rowHaloUpperIndex and rowHaloLowerIndex.
|
||||
*/
|
||||
void sendLocalRow(MPI_Request &request, std::vector<double> &row, const Matrix &matrix, const int indexRowLocal, const int receiverRank, const int indexRowGlobal)
|
||||
{
|
||||
row = getFilledBuffer(matrix, indexRowLocal);
|
||||
MPI_Isend(row.data(), row.size(), MPI_DOUBLE, receiverRank, indexRowGlobal, MPI_COMM_WORLD, &request);
|
||||
}
|
||||
|
||||
Jacobi::Result JacobiMPI::run(const Matrix &init, double epsilon, int maxNumIter)
|
||||
{
|
||||
Jacobi::Result JacobiMPI::run(const Matrix &init, double epsilon,
|
||||
int maxNumIter) {
|
||||
int rank, numProc;
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &numProc);
|
||||
// std::cout << "rank: " << rank << std::endl;
|
||||
// std::cout << "numProc: " << numProc << std::endl;
|
||||
|
||||
std::vector<Matrix> phi(2, init);
|
||||
|
||||
@@ -42,6 +31,8 @@ Jacobi::Result JacobiMPI::run(const Matrix &init, double epsilon, int maxNumIter
|
||||
const int neighborUpper = rank - 1;
|
||||
const int neighborLower = rank + 1;
|
||||
|
||||
// std::cout << neighborUpper << ":" << neighborLower << std::endl;
|
||||
|
||||
const int indexRowGlobalStart = (rank * numRows);
|
||||
const int indexRowGlobalEnd = (rank * numRows) + (numRows - 1);
|
||||
|
||||
@@ -56,28 +47,27 @@ Jacobi::Result JacobiMPI::run(const Matrix &init, double epsilon, int maxNumIter
|
||||
|
||||
int t0 = 0; // array index of current timestep
|
||||
int t1 = 1; // array index of next timestep
|
||||
while (dist > epsilon && nIter < maxNumIter)
|
||||
{
|
||||
while (dist > epsilon && nIter < maxNumIter) {
|
||||
dist = 0;
|
||||
|
||||
if (rank == 0)
|
||||
{
|
||||
std::vector<double> row;
|
||||
MPI_Request request;
|
||||
sendLocalRow(request, row, phi[t0], numRows - 1, neighborLower, indexRowGlobalEnd);
|
||||
MPI_Wait(&request, MPI_STATUS_IGNORE);
|
||||
if (rank == 0) {
|
||||
MPI_Request send_lower;
|
||||
std::vector<double> send_vec_low = phi[t0].get_row(numRows - 1);
|
||||
MPI_Isend(send_vec_low.data(), numCols, MPI_DOUBLE, neighborLower,
|
||||
indexRowGlobalEnd, MPI_COMM_WORLD, &send_lower);
|
||||
|
||||
MPI_Request requestLower;
|
||||
MPI_Irecv(haloLower.data(), haloLower.size(), MPI_DOUBLE,
|
||||
neighborLower, rowHaloLowerIndex, MPI_COMM_WORLD, &requestLower);
|
||||
MPI_Irecv(haloLower.data(), numCols, MPI_DOUBLE, neighborLower,
|
||||
rowHaloLowerIndex, MPI_COMM_WORLD, &requestLower);
|
||||
|
||||
MPI_Wait(&send_lower, MPI_STATUS_IGNORE);
|
||||
MPI_Wait(&requestLower, MPI_STATUS_IGNORE);
|
||||
|
||||
for (int i = 1; i < numRows; ++i)
|
||||
{
|
||||
for (int j = 1; j < numCols - 1; ++j)
|
||||
{
|
||||
for (int i = 1; i < numRows; ++i) {
|
||||
for (int j = 1; j < numCols - 1; ++j) {
|
||||
double valueBottom;
|
||||
(i == numRows - 1) ? valueBottom = haloLower[j] : valueBottom = phi[t0](i + 1, j);
|
||||
(i == numRows - 1) ? valueBottom = haloLower[j]
|
||||
: valueBottom = phi[t0](i + 1, j);
|
||||
phi[t1](i, j) = .25 * (valueBottom + phi[t0](i - 1, j) +
|
||||
phi[t0](i, j + 1) + phi[t0](i, j - 1));
|
||||
const double diff = phi[t1](i, j) - phi[t0](i, j);
|
||||
@@ -86,23 +76,21 @@ Jacobi::Result JacobiMPI::run(const Matrix &init, double epsilon, int maxNumIter
|
||||
}
|
||||
}
|
||||
|
||||
else if (rank == (numProc - 1))
|
||||
{
|
||||
std::vector<double> row;
|
||||
else if (rank == (numProc - 1)) {
|
||||
MPI_Request send_upper;
|
||||
std::vector<double> send_vec_up = phi[t0].get_row(0);
|
||||
MPI_Isend(send_vec_up.data(), numCols, MPI_DOUBLE, neighborUpper,
|
||||
indexRowGlobalStart, MPI_COMM_WORLD, &send_upper);
|
||||
|
||||
MPI_Request request;
|
||||
sendLocalRow(request, row, phi[t0], 0, neighborUpper, indexRowGlobalStart);
|
||||
MPI_Wait(&request, MPI_STATUS_IGNORE);
|
||||
MPI_Request request_upper;
|
||||
MPI_Irecv(haloUpper.data(), numCols, MPI_DOUBLE, neighborUpper,
|
||||
rowHaloUpperIndex, MPI_COMM_WORLD, &request_upper);
|
||||
|
||||
MPI_Request requestUpper;
|
||||
MPI_Irecv(haloUpper.data(), haloUpper.size(), MPI_DOUBLE,
|
||||
neighborUpper, rowHaloUpperIndex, MPI_COMM_WORLD, &requestUpper);
|
||||
MPI_Wait(&requestUpper, MPI_STATUS_IGNORE);
|
||||
MPI_Wait(&send_upper, MPI_STATUS_IGNORE);
|
||||
MPI_Wait(&request_upper, MPI_STATUS_IGNORE);
|
||||
|
||||
for (int i = 0; i < numRows - 1; ++i)
|
||||
{
|
||||
for (int j = 1; j < numCols - 1; ++j)
|
||||
{
|
||||
for (int i = 0; i < numRows - 1; ++i) {
|
||||
for (int j = 1; j < numCols - 1; ++j) {
|
||||
double valueTop;
|
||||
(i == 0) ? valueTop = haloUpper[j] : valueTop = phi[t0](i - 1, j);
|
||||
phi[t1](i, j) = .25 * (phi[t0](i + 1, j) + valueTop +
|
||||
@@ -113,51 +101,45 @@ Jacobi::Result JacobiMPI::run(const Matrix &init, double epsilon, int maxNumIter
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
std::vector<double> rowUpper;
|
||||
std::vector<double> rowLower;
|
||||
else {
|
||||
MPI_Request send_upper;
|
||||
MPI_Request send_lower;
|
||||
|
||||
MPI_Request requestSendUpper;
|
||||
MPI_Request requestSendLower;
|
||||
sendLocalRow(requestSendUpper, rowUpper, phi[t0], 0, neighborUpper, indexRowGlobalStart);
|
||||
sendLocalRow(requestSendLower, rowLower, phi[t0], numRows - 1, neighborLower, indexRowGlobalEnd);
|
||||
std::vector<double> send_vec_up = phi[t0].get_row(0);
|
||||
MPI_Isend(send_vec_up.data(), numCols, MPI_DOUBLE, neighborUpper,
|
||||
indexRowGlobalStart, MPI_COMM_WORLD, &send_upper);
|
||||
|
||||
MPI_Request sendRequests[2] = {requestSendUpper, requestSendLower};
|
||||
MPI_Waitall(2, sendRequests, MPI_STATUSES_IGNORE);
|
||||
std::vector<double> send_vec_low = phi[t0].get_row(numRows - 1);
|
||||
MPI_Isend(send_vec_low.data(), numCols, MPI_DOUBLE, neighborLower,
|
||||
indexRowGlobalEnd, MPI_COMM_WORLD, &send_lower);
|
||||
|
||||
MPI_Request requestUpper;
|
||||
MPI_Irecv(haloUpper.data(), haloUpper.size(), MPI_DOUBLE,
|
||||
neighborUpper, rowHaloUpperIndex, MPI_COMM_WORLD, &requestUpper);
|
||||
MPI_Request requestLower;
|
||||
MPI_Irecv(haloLower.data(), haloLower.size(), MPI_DOUBLE,
|
||||
neighborLower, rowHaloLowerIndex, MPI_COMM_WORLD, &requestLower);
|
||||
MPI_Request request_upper;
|
||||
MPI_Request request_lower;
|
||||
MPI_Irecv(haloUpper.data(), numCols, MPI_DOUBLE, neighborUpper,
|
||||
rowHaloUpperIndex, MPI_COMM_WORLD, &request_upper);
|
||||
MPI_Irecv(haloLower.data(), numCols, MPI_DOUBLE, neighborLower,
|
||||
rowHaloLowerIndex, MPI_COMM_WORLD, &request_lower);
|
||||
|
||||
MPI_Request requests[2] = {requestUpper, requestLower};
|
||||
MPI_Waitall(2, requests, MPI_STATUSES_IGNORE);
|
||||
MPI_Wait(&send_upper, MPI_STATUS_IGNORE);
|
||||
MPI_Wait(&send_lower, MPI_STATUS_IGNORE);
|
||||
MPI_Wait(&request_upper, MPI_STATUS_IGNORE);
|
||||
MPI_Wait(&request_lower, MPI_STATUS_IGNORE);
|
||||
|
||||
for (int i = 0; i < numRows; ++i)
|
||||
{
|
||||
for (int j = 1; j < numCols - 1; ++j)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
for (int i = 0; i < numRows; ++i) {
|
||||
for (int j = 1; j < numCols - 1; ++j) {
|
||||
if (i == 0) {
|
||||
double valueTop = haloUpper[j];
|
||||
phi[t1](i, j) = .25 * (phi[t0](i + 1, j) + valueTop +
|
||||
phi[t0](i, j + 1) + phi[t0](i, j - 1));
|
||||
const double diff = phi[t1](i, j) - phi[t0](i, j);
|
||||
dist = std::max(dist, std::abs(diff));
|
||||
}
|
||||
else if (i == numRows - 1)
|
||||
{
|
||||
} else if (i == numRows - 1) {
|
||||
double valueBottom = haloLower[j];
|
||||
phi[t1](i, j) = .25 * (valueBottom + phi[t0](i - 1, j) +
|
||||
phi[t0](i, j + 1) + phi[t0](i, j - 1));
|
||||
const double diff = phi[t1](i, j) - phi[t0](i, j);
|
||||
dist = std::max(dist, std::abs(diff));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
phi[t1](i, j) = .25 * (phi[t0](i + 1, j) + phi[t0](i - 1, j) +
|
||||
phi[t0](i, j + 1) + phi[t0](i, j - 1));
|
||||
const double diff = phi[t1](i, j) - phi[t0](i, j);
|
||||
@@ -167,16 +149,17 @@ Jacobi::Result JacobiMPI::run(const Matrix &init, double epsilon, int maxNumIter
|
||||
}
|
||||
}
|
||||
|
||||
// if (nIter % 1000 == 0) {
|
||||
// std::cout << "Iteration " << nIter << ", dist=" << dist << "\n";
|
||||
// }
|
||||
double globalDist;
|
||||
double globalDist = 0;
|
||||
MPI_Allreduce(&dist, &globalDist, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
|
||||
dist = globalDist;
|
||||
|
||||
nIter++;
|
||||
std::swap(t0, t1);
|
||||
// if (nIter == 100) {
|
||||
// std::cout << phi[t1] << std::endl;
|
||||
// }
|
||||
}
|
||||
|
||||
// std::cout << phi[t1] << std::endl;
|
||||
return Jacobi::Result{phi[t0], dist, nIter};
|
||||
}
|
||||
|
||||
@@ -16,14 +16,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MATRIX_H
|
||||
#define MATRIX_H
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Matrix class
|
||||
@@ -40,7 +39,7 @@
|
||||
*
|
||||
*/
|
||||
class Matrix {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Create a matrix of size m x n and initialize all entries to zero.
|
||||
* @param rows number of rows
|
||||
@@ -79,19 +78,19 @@ class Matrix {
|
||||
*/
|
||||
static Matrix uninit(std::pair<int, int> dim);
|
||||
|
||||
Matrix(const Matrix& other);
|
||||
Matrix(Matrix&& other);
|
||||
Matrix(const Matrix &other);
|
||||
Matrix(Matrix &&other);
|
||||
~Matrix();
|
||||
Matrix& operator=(const Matrix& other);
|
||||
Matrix& operator=(Matrix&& other);
|
||||
Matrix &operator=(const Matrix &other);
|
||||
Matrix &operator=(Matrix &&other);
|
||||
|
||||
// Access element a_ij of the matrix
|
||||
double& operator()(int i, int j);
|
||||
const double& operator()(int i, int j) const;
|
||||
double &operator()(int i, int j);
|
||||
const double &operator()(int i, int j) const;
|
||||
|
||||
// Obtain a pointer to the underlying data
|
||||
double* data();
|
||||
const double* data() const;
|
||||
double *data();
|
||||
const double *data() const;
|
||||
|
||||
// Getter functions for the dimensions
|
||||
std::pair<int, int> dim() const;
|
||||
@@ -100,44 +99,55 @@ class Matrix {
|
||||
int numEntries() const;
|
||||
|
||||
// Comparison operators
|
||||
bool operator==(const Matrix& b);
|
||||
bool operator!=(const Matrix& b);
|
||||
bool operator==(const Matrix &b);
|
||||
bool operator!=(const Matrix &b);
|
||||
|
||||
// addition
|
||||
Matrix& operator+=(const Matrix& b);
|
||||
Matrix &operator+=(const Matrix &b);
|
||||
|
||||
// subtraction
|
||||
Matrix& operator-=(const Matrix& b);
|
||||
Matrix &operator-=(const Matrix &b);
|
||||
|
||||
// scalar multiplication
|
||||
Matrix& operator*=(double x);
|
||||
Matrix &operator*=(double x);
|
||||
|
||||
// scalar division
|
||||
Matrix& operator/=(double x);
|
||||
Matrix &operator/=(double x);
|
||||
|
||||
private:
|
||||
std::vector<double> get_row(int i) {
|
||||
std::vector<double> row(0);
|
||||
int start = this->cols() * i;
|
||||
int end = this->cols() * i + cols();
|
||||
|
||||
for (int j = start; j < end; j++) {
|
||||
row.push_back(this->data()[j]);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
private:
|
||||
// Constructor is private to prevent creating an uninitialized matrix
|
||||
// accidentally. Use Matrix::zeros() or Matrix::uninit() instead
|
||||
Matrix(int m, int n);
|
||||
|
||||
int numRows_; // number of rows
|
||||
int numCols_; // number of columns
|
||||
double* data_; // the matrix' entries
|
||||
int numRows_; // number of rows
|
||||
int numCols_; // number of columns
|
||||
double *data_; // the matrix' entries
|
||||
};
|
||||
|
||||
/**
|
||||
* Vector class
|
||||
*
|
||||
*
|
||||
* This class implements a vector of size n. The vector is stored in a
|
||||
* Matrix of size n x 1.
|
||||
*
|
||||
*
|
||||
* Constructors are provided to create a vector of zeros or an uninitialized
|
||||
* vector. The uninitialized vector is not initialized, i.e. the entries are
|
||||
* not set to zero. This is useful for performance reasons, e.g. to control
|
||||
* the placement of vector entries in locality-domain memory.
|
||||
*/
|
||||
class Vector {
|
||||
public:
|
||||
public:
|
||||
static Vector zeros(int n) {
|
||||
Vector vec;
|
||||
vec.data_ = Matrix::zeros(n, 1);
|
||||
@@ -150,19 +160,19 @@ class Vector {
|
||||
return vec;
|
||||
}
|
||||
|
||||
bool operator==(const Vector& b) { return data_ == b.data_; }
|
||||
bool operator!=(const Vector& b) { return !operator==(b); }
|
||||
double& operator()(int i) { return data_(i, 0); }
|
||||
const double& operator()(int i) const { return data_(i, 0); }
|
||||
double* data() { return data_.data(); }
|
||||
const double* data() const { return data_.data(); }
|
||||
bool operator==(const Vector &b) { return data_ == b.data_; }
|
||||
bool operator!=(const Vector &b) { return !operator==(b); }
|
||||
double &operator()(int i) { return data_(i, 0); }
|
||||
const double &operator()(int i) const { return data_(i, 0); }
|
||||
double *data() { return data_.data(); }
|
||||
const double *data() const { return data_.data(); }
|
||||
|
||||
Vector operator+=(const Vector& b) {
|
||||
Vector operator+=(const Vector &b) {
|
||||
data_ += b.data_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector operator-=(const Vector& b) {
|
||||
Vector operator-=(const Vector &b) {
|
||||
data_ -= b.data_;
|
||||
return *this;
|
||||
}
|
||||
@@ -177,7 +187,7 @@ class Vector {
|
||||
|
||||
int size() const { return data_.rows(); }
|
||||
|
||||
private:
|
||||
private:
|
||||
Matrix data_ = Matrix::zeros(0, 0);
|
||||
};
|
||||
|
||||
@@ -193,27 +203,21 @@ inline Matrix Matrix::zeros(int m, int n) {
|
||||
return mat;
|
||||
}
|
||||
|
||||
inline Matrix Matrix::zeros(int n) {
|
||||
return zeros(n, n);
|
||||
}
|
||||
inline Matrix Matrix::zeros(int n) { return zeros(n, n); }
|
||||
|
||||
inline Matrix Matrix::zeros(std::pair<int, int> dim) {
|
||||
return zeros(dim.first, dim.second);
|
||||
}
|
||||
|
||||
inline Matrix Matrix::uninit(int m, int n) {
|
||||
return Matrix(m, n);
|
||||
}
|
||||
inline Matrix Matrix::uninit(int m, int n) { return Matrix(m, n); }
|
||||
|
||||
inline Matrix Matrix::uninit(int n) {
|
||||
return uninit(n, n);
|
||||
}
|
||||
inline Matrix Matrix::uninit(int n) { return uninit(n, n); }
|
||||
|
||||
inline Matrix Matrix::uninit(std::pair<int, int> dim) {
|
||||
return uninit(dim.first, dim.second);
|
||||
}
|
||||
|
||||
inline Matrix::Matrix(const Matrix& other) {
|
||||
inline Matrix::Matrix(const Matrix &other) {
|
||||
numRows_ = other.numRows_;
|
||||
numCols_ = other.numCols_;
|
||||
if (numRows_ == 0 || numCols_ == 0) {
|
||||
@@ -228,7 +232,7 @@ inline Matrix::Matrix(const Matrix& other) {
|
||||
}
|
||||
}
|
||||
|
||||
inline Matrix::Matrix(Matrix&& other) {
|
||||
inline Matrix::Matrix(Matrix &&other) {
|
||||
numRows_ = other.numRows_;
|
||||
numCols_ = other.numCols_;
|
||||
data_ = other.data_;
|
||||
@@ -244,7 +248,7 @@ inline Matrix::~Matrix() {
|
||||
}
|
||||
}
|
||||
|
||||
inline Matrix& Matrix::operator=(const Matrix& other) {
|
||||
inline Matrix &Matrix::operator=(const Matrix &other) {
|
||||
if (this != &other) {
|
||||
if (data_ != nullptr) {
|
||||
delete[] data_;
|
||||
@@ -261,7 +265,7 @@ inline Matrix& Matrix::operator=(const Matrix& other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Matrix::operator=(Matrix&& other) {
|
||||
inline Matrix &Matrix::operator=(Matrix &&other) {
|
||||
if (this != &other) {
|
||||
if (data_ != nullptr) {
|
||||
delete[] data_;
|
||||
@@ -276,39 +280,29 @@ inline Matrix& Matrix::operator=(Matrix&& other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline double& Matrix::operator()(int i, int j) {
|
||||
inline double &Matrix::operator()(int i, int j) {
|
||||
return data_[i * numCols_ + j];
|
||||
}
|
||||
|
||||
inline const double& Matrix::operator()(int i, int j) const {
|
||||
inline const double &Matrix::operator()(int i, int j) const {
|
||||
return data_[i * numCols_ + j];
|
||||
}
|
||||
|
||||
inline double* Matrix::data() {
|
||||
return data_;
|
||||
}
|
||||
inline double *Matrix::data() { return data_; }
|
||||
|
||||
inline const double* Matrix::data() const {
|
||||
return data_;
|
||||
}
|
||||
inline const double *Matrix::data() const { return data_; }
|
||||
|
||||
inline std::pair<int, int> Matrix::dim() const {
|
||||
return std::pair<int, int>(numRows_, numCols_);
|
||||
}
|
||||
|
||||
inline int Matrix::rows() const {
|
||||
return numRows_;
|
||||
}
|
||||
inline int Matrix::rows() const { return numRows_; }
|
||||
|
||||
inline int Matrix::cols() const {
|
||||
return numCols_;
|
||||
}
|
||||
inline int Matrix::cols() const { return numCols_; }
|
||||
|
||||
inline int Matrix::numEntries() const {
|
||||
return numRows_ * numCols_;
|
||||
}
|
||||
inline int Matrix::numEntries() const { return numRows_ * numCols_; }
|
||||
|
||||
inline bool Matrix::operator==(const Matrix& b) {
|
||||
inline bool Matrix::operator==(const Matrix &b) {
|
||||
const double eps = 1e-12;
|
||||
if (numRows_ != b.numRows_ || numCols_ != b.numCols_) {
|
||||
return false;
|
||||
@@ -323,11 +317,9 @@ inline bool Matrix::operator==(const Matrix& b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool Matrix::operator!=(const Matrix& b) {
|
||||
return !operator==(b);
|
||||
}
|
||||
inline bool Matrix::operator!=(const Matrix &b) { return !operator==(b); }
|
||||
|
||||
inline Matrix& Matrix::operator+=(const Matrix& b) {
|
||||
inline Matrix &Matrix::operator+=(const Matrix &b) {
|
||||
for (int i = 0; i < numRows_; ++i) {
|
||||
for (int j = 0; j < numCols_; ++j) {
|
||||
operator()(i, j) += b(i, j);
|
||||
@@ -336,7 +328,7 @@ inline Matrix& Matrix::operator+=(const Matrix& b) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Matrix::operator-=(const Matrix& b) {
|
||||
inline Matrix &Matrix::operator-=(const Matrix &b) {
|
||||
for (int i = 0; i < numRows_; ++i) {
|
||||
for (int j = 0; j < numCols_; ++j) {
|
||||
operator()(i, j) -= b(i, j);
|
||||
@@ -345,7 +337,7 @@ inline Matrix& Matrix::operator-=(const Matrix& b) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Matrix::operator*=(double x) {
|
||||
inline Matrix &Matrix::operator*=(double x) {
|
||||
for (int i = 0; i < numRows_; ++i) {
|
||||
for (int j = 0; j < numCols_; ++j) {
|
||||
operator()(i, j) *= x;
|
||||
@@ -354,7 +346,7 @@ inline Matrix& Matrix::operator*=(double x) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Matrix::operator/=(double x) {
|
||||
inline Matrix &Matrix::operator/=(double x) {
|
||||
for (int i = 0; i < numRows_; ++i) {
|
||||
for (int j = 0; j < numCols_; ++j) {
|
||||
operator()(i, j) /= x;
|
||||
@@ -370,7 +362,7 @@ inline Matrix::Matrix(int m, int n) : numRows_(m), numCols_(n) {
|
||||
}
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const Matrix& a) {
|
||||
inline std::ostream &operator<<(std::ostream &os, const Matrix &a) {
|
||||
const int width = 10;
|
||||
const int precision = 4;
|
||||
|
||||
@@ -389,8 +381,7 @@ inline std::ostream& operator<<(std::ostream& os, const Matrix& a) {
|
||||
return os;
|
||||
}
|
||||
|
||||
inline bool equalWithinRange(const Matrix& a,
|
||||
const Matrix& b,
|
||||
inline bool equalWithinRange(const Matrix &a, const Matrix &b,
|
||||
double eps = 1e-12) {
|
||||
if (a.rows() != b.rows() || a.cols() != b.cols())
|
||||
return false;
|
||||
@@ -408,4 +399,4 @@ inline bool equalWithinRange(const Matrix& a,
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // MATRIX_H
|
||||
#endif // MATRIX_H
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#include "matrix_io.h"
|
||||
#include "matrix.h"
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <mpi.h>
|
||||
#include <exception>
|
||||
#include "matrix.h"
|
||||
#include "matrix_io.h"
|
||||
|
||||
MatrixIO::MatrixIO() {
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &rank_);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &numProc_);
|
||||
}
|
||||
|
||||
void MatrixIO::saveDistributed(const Matrix& distributedMatrix,
|
||||
const std::string& filename) {
|
||||
void MatrixIO::saveDistributed(const Matrix &distributedMatrix,
|
||||
const std::string &filename) {
|
||||
Matrix mat = gatherMatrixOnRoot(distributedMatrix);
|
||||
|
||||
if (rank_ == 0) {
|
||||
@@ -18,7 +18,7 @@ void MatrixIO::saveDistributed(const Matrix& distributedMatrix,
|
||||
}
|
||||
}
|
||||
|
||||
void MatrixIO::saveSerial(const Matrix& m, const std::string& filename) {
|
||||
void MatrixIO::saveSerial(const Matrix &m, const std::string &filename) {
|
||||
std::ofstream fout(filename);
|
||||
const int numRows = m.rows();
|
||||
const int numCols = m.cols();
|
||||
@@ -31,7 +31,7 @@ void MatrixIO::saveSerial(const Matrix& m, const std::string& filename) {
|
||||
}
|
||||
}
|
||||
|
||||
Matrix MatrixIO::loadDistributed(const std::string& filename) {
|
||||
Matrix MatrixIO::loadDistributed(const std::string &filename) {
|
||||
Matrix matrixOnRoot = Matrix::zeros(0, 0);
|
||||
if (rank_ == 0) {
|
||||
matrixOnRoot = loadSerial(filename);
|
||||
@@ -41,7 +41,7 @@ Matrix MatrixIO::loadDistributed(const std::string& filename) {
|
||||
return distributedMatrix;
|
||||
}
|
||||
|
||||
Matrix MatrixIO::loadSerial(const std::string& filename) {
|
||||
Matrix MatrixIO::loadSerial(const std::string &filename) {
|
||||
std::ifstream fin(filename);
|
||||
|
||||
// Check first character (has to be #)
|
||||
@@ -66,7 +66,7 @@ Matrix MatrixIO::loadSerial(const std::string& filename) {
|
||||
return mat;
|
||||
}
|
||||
|
||||
Matrix MatrixIO::gatherMatrixOnRoot(const Matrix& distributedMatrix) {
|
||||
Matrix MatrixIO::gatherMatrixOnRoot(const Matrix &distributedMatrix) {
|
||||
const int numRowsLocal = distributedMatrix.rows();
|
||||
const int numCols = distributedMatrix.cols();
|
||||
const int numRowsTotal = numRowsLocal * numProc_;
|
||||
@@ -84,7 +84,7 @@ Matrix MatrixIO::gatherMatrixOnRoot(const Matrix& distributedMatrix) {
|
||||
return matrixOnRoot;
|
||||
}
|
||||
|
||||
Matrix MatrixIO::scatterMatrixFromRoot(const Matrix& matrixOnRoot) {
|
||||
Matrix MatrixIO::scatterMatrixFromRoot(const Matrix &matrixOnRoot) {
|
||||
int numRowsTotal = matrixOnRoot.rows();
|
||||
int numCols = matrixOnRoot.cols();
|
||||
|
||||
|
||||
BIN
lab10/jacobi/performance_plot.png
Normal file
BIN
lab10/jacobi/performance_plot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
55
lab10/jacobi/plot_res.py
Normal file
55
lab10/jacobi/plot_res.py
Normal file
@@ -0,0 +1,55 @@
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# Pfad zum Verzeichnis mit den Dateien
|
||||
data_dir = "resluts/" # ggf. anpassen
|
||||
|
||||
threads = [1, 2, 4, 6, 8, 12, 16, 18, 24, 32, 36, 48]
|
||||
times = [
|
||||
175246,
|
||||
89030.8,
|
||||
45182.7,
|
||||
30198.1,
|
||||
22710.1,
|
||||
15256.1,
|
||||
13512.1,
|
||||
13073.2,
|
||||
10036.8,
|
||||
9845.38,
|
||||
8423.65,
|
||||
7676.71,
|
||||
]
|
||||
speedups = [
|
||||
1,
|
||||
1.96838,
|
||||
3.90997,
|
||||
5.8091,
|
||||
7.73292,
|
||||
11.4934,
|
||||
13.0374,
|
||||
13.4461,
|
||||
17.4421,
|
||||
17.9058,
|
||||
20.8097,
|
||||
22.8728,
|
||||
]
|
||||
|
||||
efficiency = [speedup / thread for speedup, thread in zip(speedups, threads)]
|
||||
|
||||
# plt.figure(figsize=(10, 5))
|
||||
plt.plot(threads, efficiency, marker="o", label="Speedup")
|
||||
plt.title("Efficiency")
|
||||
plt.xlabel("Threads")
|
||||
plt.ylabel("Efficiency")
|
||||
plt.grid(True)
|
||||
# plt.legend()
|
||||
# plt.tight_layout()
|
||||
plt.savefig("efficiency_plot.png")
|
||||
|
||||
plt.clf()
|
||||
# --- Plot 2: Performance ---
|
||||
plt.plot(threads, times, marker="o")
|
||||
plt.title("Performance")
|
||||
plt.xlabel("Threads")
|
||||
plt.ylabel("Performance (ms)")
|
||||
plt.grid(True)
|
||||
plt.savefig("performance_plot.png")
|
||||
6
lab10/jacobi/results/jacobi_12.txt
Normal file
6
lab10/jacobi/results/jacobi_12.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Starting serial benchmark
|
||||
Serial benchmark finished, time=175344ms
|
||||
Parallel benchmark finished, time=15256.1ms
|
||||
Serial time: 175344ms
|
||||
Parallel time: 15256.1ms
|
||||
Speedup: 11.4934
|
||||
6
lab10/jacobi/results/jacobi_16.txt
Normal file
6
lab10/jacobi/results/jacobi_16.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Starting serial benchmark
|
||||
Serial benchmark finished, time=176163ms
|
||||
Parallel benchmark finished, time=13512.1ms
|
||||
Serial time: 176163ms
|
||||
Parallel time: 13512.1ms
|
||||
Speedup: 13.0374
|
||||
6
lab10/jacobi/results/jacobi_18.txt
Normal file
6
lab10/jacobi/results/jacobi_18.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Starting serial benchmark
|
||||
Serial benchmark finished, time=175784ms
|
||||
Parallel benchmark finished, time=13073.2ms
|
||||
Serial time: 175784ms
|
||||
Parallel time: 13073.2ms
|
||||
Speedup: 13.4461
|
||||
6
lab10/jacobi/results/jacobi_2.txt
Normal file
6
lab10/jacobi/results/jacobi_2.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Starting serial benchmark
|
||||
Serial benchmark finished, time=175246ms
|
||||
Parallel benchmark finished, time=89030.8ms
|
||||
Serial time: 175246ms
|
||||
Parallel time: 89030.8ms
|
||||
Speedup: 1.96838
|
||||
6
lab10/jacobi/results/jacobi_24.txt
Normal file
6
lab10/jacobi/results/jacobi_24.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Starting serial benchmark
|
||||
Serial benchmark finished, time=175063ms
|
||||
Parallel benchmark finished, time=10036.8ms
|
||||
Serial time: 175063ms
|
||||
Parallel time: 10036.8ms
|
||||
Speedup: 17.4421
|
||||
6
lab10/jacobi/results/jacobi_32.txt
Normal file
6
lab10/jacobi/results/jacobi_32.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Starting serial benchmark
|
||||
Serial benchmark finished, time=176290ms
|
||||
Parallel benchmark finished, time=9845.38ms
|
||||
Serial time: 176290ms
|
||||
Parallel time: 9845.38ms
|
||||
Speedup: 17.9058
|
||||
6
lab10/jacobi/results/jacobi_36.txt
Normal file
6
lab10/jacobi/results/jacobi_36.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Starting serial benchmark
|
||||
Serial benchmark finished, time=175294ms
|
||||
Parallel benchmark finished, time=8423.65ms
|
||||
Serial time: 175294ms
|
||||
Parallel time: 8423.65ms
|
||||
Speedup: 20.8097
|
||||
6
lab10/jacobi/results/jacobi_4.txt
Normal file
6
lab10/jacobi/results/jacobi_4.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Starting serial benchmark
|
||||
Serial benchmark finished, time=176663ms
|
||||
Parallel benchmark finished, time=45182.7ms
|
||||
Serial time: 176663ms
|
||||
Parallel time: 45182.7ms
|
||||
Speedup: 3.90997
|
||||
6
lab10/jacobi/results/jacobi_48.txt
Normal file
6
lab10/jacobi/results/jacobi_48.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Starting serial benchmark
|
||||
Serial benchmark finished, time=175588ms
|
||||
Parallel benchmark finished, time=7676.71ms
|
||||
Serial time: 175588ms
|
||||
Parallel time: 7676.71ms
|
||||
Speedup: 22.8728
|
||||
6
lab10/jacobi/results/jacobi_6.txt
Normal file
6
lab10/jacobi/results/jacobi_6.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Starting serial benchmark
|
||||
Serial benchmark finished, time=175424ms
|
||||
Parallel benchmark finished, time=30198.1ms
|
||||
Serial time: 175424ms
|
||||
Parallel time: 30198.1ms
|
||||
Speedup: 5.8091
|
||||
6
lab10/jacobi/results/jacobi_8.txt
Normal file
6
lab10/jacobi/results/jacobi_8.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Starting serial benchmark
|
||||
Serial benchmark finished, time=175615ms
|
||||
Parallel benchmark finished, time=22710.1ms
|
||||
Serial time: 175615ms
|
||||
Parallel time: 22710.1ms
|
||||
Speedup: 7.73292
|
||||
Reference in New Issue
Block a user