#include #include #include #include #include #include #include // Matrizen erzeugen void generateRandomMatrices(int n, std::vector>& A, std::vector>& B, double min_val = 0.0, double max_val = 10.0) { std::srand(static_cast(std::time(nullptr))); A.resize(n, std::vector(n)); B.resize(n, std::vector(n)); for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) { double r1 = static_cast(std::rand()) / RAND_MAX; double r2 = static_cast(std::rand()) / RAND_MAX; A[i][j] = min_val + r1 * (max_val - min_val); B[i][j] = min_val + r2 * (max_val - min_val); } } // Seriell std::vector> matmul_serial(const std::vector>& A, const std::vector>& B) { int n = A.size(); int m = B[0].size(); int p = B.size(); std::vector> C(n, std::vector(m, 0.0)); for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) for (int k = 0; k < p; ++k) C[i][j] += A[i][k] * B[k][j]; return C; } // Parallele Zeilenzerlegung std::vector> matmul_parallel_rows(const std::vector>& A, const std::vector>& B, int numThreads) { int n = A.size(); int m = B[0].size(); int p = B.size(); std::vector> C(n, std::vector(m, 0.0)); #pragma omp parallel for num_threads(numThreads) for (int i = 0; i < n; ++i) { std::vector row(m, 0.0); for (int j = 0; j < m; ++j) { double sum = 0.0; for (int k = 0; k < p; ++k) sum += A[i][k] * B[k][j]; //verhindert überschreibuung row[j] = sum; } C[i] = row; } return C; } // Parallele Spaltenzerlegung std::vector> matmul_parallel_cols(const std::vector>& A, const std::vector>& B, int numThreads) { int n = A.size(); int m = B[0].size(); int p = B.size(); std::vector> C(n, std::vector(m, 0.0)); #pragma omp parallel for num_threads(numThreads) for (int j = 0; j < m; ++j) { for (int i = 0; i < n; ++i) { double sum = 0.0; for (int k = 0; k < p; ++k) sum += A[i][k] * B[k][j]; //Zwischengepeichert C[i][j] = sum; } } return C; } // Blockzerlegung std::vector> matmul_block(const std::vector>& A, const std::vector>& B, int blockSize, int numThreads) { int n = A.size(); int m = B[0].size(); int p = B.size(); std::vector> C(n, std::vector(m, 0.0)); #pragma omp parallel for collapse(2) num_threads(numThreads) for (int ii = 0; ii < n; ii += blockSize) for (int jj = 0; jj < m; jj += blockSize) { for (int i = ii; i < std::min(ii + blockSize, n); ++i) for (int j = jj; j < std::min(jj + blockSize, m); ++j) { double sum = 0.0; for (int k = 0; k < p; ++k) sum += A[i][k] * B[k][j]; C[i][j] = sum; } } return C; } // Matrix ausgeben void printMatrix(const std::vector>& M, const std::string& name) { std::cout << name << " (" << M.size() << "x" << (M.empty() ? 0 : M[0].size()) << "):\n"; for (const auto& row : M) { for (double val : row) std::cout << val << "\t"; std::cout << "\n"; } std::cout << "\n"; } //Matrix Vergleich (Komponentenweise) bool compareMatrices(const std::vector>& A, const std::vector>& B) { if (A.size() != B.size() || A[0].size() != B[0].size()) return false; for (size_t i = 0; i < A.size(); ++i) for (size_t j = 0; j < A[0].size(); ++j) if (std::abs(A[i][j] - B[i][j]) > 1e-9) return false; return true; } int main() { int N = 4; // für Ausgabe kleiner Matrizen <5 int numThreads = omp_get_max_threads(); if (numThreads == 0) numThreads = 4; std::vector> A, B; generateRandomMatrices(N, A, B); if (N < 5) { printMatrix(A, "Matrix A"); printMatrix(B, "Matrix B"); } // Serielle Berechnung auto start = std::chrono::steady_clock::now(); auto C_serial = matmul_serial(A, B); auto end = std::chrono::steady_clock::now(); double timeSerial = std::chrono::duration(end - start).count(); std::cout << "Seriell: " << timeSerial << " s\n"; if (N < 5) printMatrix(C_serial, "C_serial"); // Zeilenparallel start = std::chrono::steady_clock::now(); auto C_rows = matmul_parallel_rows(A, B, numThreads); end = std::chrono::steady_clock::now(); double timeRows = std::chrono::duration(end - start).count(); std::cout << "Parallel Zeilen: " << timeRows << " s | " << (compareMatrices(C_serial, C_rows) ? "Match" : "Mismatch") << "\n"; if (N < 5) printMatrix(C_rows, "C_rows"); // Spaltenparallel start = std::chrono::steady_clock::now(); auto C_cols = matmul_parallel_cols(A, B, numThreads); end = std::chrono::steady_clock::now(); double timeCols = std::chrono::duration(end - start).count(); std::cout << "Parallel Spalten: " << timeCols << " s | " << (compareMatrices(C_serial, C_cols) ? "Match" : "Mismatch") << "\n"; if (N < 5) printMatrix(C_cols, "C_cols"); // Blockparallel int blockSize = 2; // für kleine N passend start = std::chrono::steady_clock::now(); auto C_block = matmul_block(A, B, blockSize, numThreads); end = std::chrono::steady_clock::now(); double timeBlock = std::chrono::duration(end - start).count(); std::cout << "Parallel Block (" << blockSize << "x" << blockSize << "): " << timeBlock << " s | " << (compareMatrices(C_serial, C_block) ? "Match" : "Mismatch") << "\n"; if (N < 5) printMatrix(C_block, "C_block"); return 0; }