Strassen Algorithmus, OMP Version
#pragma once
/* Matrix Datenstruktur */
typedef struct matrix{
int rows; /* Anzahl Zeilen/ rows (m) */
int cols; /* Anzahl Spalten / columns (n) */
double* data; /* m*n Array in Zeilen Ordnung / row-major */
} matrix_type;
/* Erstelle dynamische Zeilen * Spalten Matrix */
matrix_type* matrix_create(int rows, int cols);
/* Speicher freigeben */
void matrix_free(matrix_type* M);
/* Hilfsfunktionen */
/* Erstellen einer Zufallsmatrix */
void matrix_random(matrix_type* M);
/* Ausgabe Matrix */
void matrix_print(const matrix_type* M, const char* name);
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <omp.h>
#include "matrix_lib.h"
matrix_type* matrix_create(int rows, int cols) {
matrix_type* m = (matrix_type*)malloc(sizeof(matrix_type));
if (!m) {
fprintf(stderr, "Fehler: malloc matrix_create\n");
return NULL;
}
m->rows = rows;
m->cols = cols;
m->data = (double*)malloc(rows * cols * sizeof(double));
if (!m->data) {
fprintf(stderr, "Fehler: malloc matrix_create.data\n");
free(m);
return NULL;
}
return m;
}
void matrix_free(matrix_type* m) {
if (m) {
if (m->data) {
free(m->data);
m->data = NULL;
}
free(m);
}
}
void matrix_random(matrix_type* m) {
for (int i = 0; i < m->rows * m->cols; i++) {
m->data[i] = rand() / (double)RAND_MAX;
}
}
void matrix_print(const matrix_type* m, const char* name) {
printf("Matrix %s (%dx%d):\n", name, m->rows, m->cols);
for (int i = 0; i < m->rows; i++) {
for (int j = 0; j < m->cols; j++) {
printf("%8.3f ", m->data[i * m->cols + j]);
}
putchar('\n');
}
putchar('\n');
}
#pragma once
#include "matrix_lib.h"
/* Aufruf Strassen Algorithmus */
matrix_type* mul_matrix(const matrix_type* A, const matrix_type* B);
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <omp.h>
#include "strassen.h"
/* Deklaration */
matrix_type* omp_multiplikation(const matrix_type* A, const matrix_type* B);
matrix_type* mul_matrix(const matrix_type* A, const matrix_type* B)
{
assert(A->cols == B->rows);
int m = A->rows, k = A->cols, n = B->cols;
/** Groesste Zahl zur Potenz von 2 > max(m, n, k) ermitteln, und in sz speichern */
int sz = 1;
while (sz < m || sz < n || sz < k) sz <<= 1;
matrix_type* Apad = matrix_create(sz, sz);
matrix_type* Bpad = matrix_create(sz, sz);
for (int i = 0; i < m; i++) {
memcpy(Apad->data + i * sz, A->data + i * k, k * sizeof(double));
}
for (int i = 0; i < n; i++) {
memcpy(Bpad->data + i * sz, B->data + i * n, n * sizeof(double));
}
matrix_type* Cpad = omp_multiplikation(Apad, Bpad);
matrix_type* C = matrix_create(m, n);
for (int i = 0; i < m; i++) {
memcpy(C->data + i * n, Cpad->data + i * sz, n * sizeof(double));
}
matrix_free(Apad);
matrix_free(Bpad);
matrix_free(Cpad);
return C;
}
/* Strassen mit OMP */
matrix_type* omp_multiplikation(const matrix_type* A, const matrix_type* B)
{
int m = A->rows, k = A->cols, n = B->cols;
matrix_type* C = matrix_create(m, n);
#pragma omp parallel for schedule(static) collapse(2)
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
double sum = 0.0;
#pragma omp simd reduction(+:sum)
for (int p = 0; p < k; p++) {
sum += A->data[i * k + p] * B->data[p * n + j];
}
C->data[i * n + j] = sum;
}
}
return C;
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "matrix_lib.h"
#include "strassen.h"
/* Programm Strassen - Demo mit Zeitmessung */
int main(void)
{
int n = 512; /* Zahl mit der Potenz 2 */
matrix_type* A = matrix_create(n, n);
matrix_type* B = matrix_create(n, n);
matrix_random(A);
matrix_random(B);
#pragma omp parallel
{
double start = clock();
matrix_type* C = mul_matrix(A, B); /* Strassen Aufruf */
double end = clock();
printf("Strassen multiplication von %dx%d Matrizen benoetigt %.3f s\n",n, n, end - start);
matrix_free(C);
}
matrix_free(A);
matrix_free(B);
return 0;
}