217 lines
6.3 KiB
C
217 lines
6.3 KiB
C
// Source: https://github.com/ivanbgd/Matrix-Multiplication-MatMul-C/blob/master/matmul_1d_seq.c
|
|
#define MATMUL_1D
|
|
#ifdef MATMUL_1D
|
|
|
|
/* Matrices are represented as 1-D arrays in memory.
|
|
* That means they are contiguous in memory.
|
|
* Minimum dimension is 1, not 0, and internal dimensions must match. */
|
|
|
|
// #include <math.h>
|
|
// #include <omp.h>
|
|
// #include <stdio.h>
|
|
// #include <stdlib.h>
|
|
// #include <string.h>
|
|
// #include <time.h>
|
|
#include <cheriintrin.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
void free(void * __capability ptr);
|
|
void * __capability malloc(size_t size);
|
|
|
|
/* Initializes vector or matrix, sequentially, with indices. */
|
|
void init_seq(int * __capability a, const unsigned n_rows_a, const unsigned n_cols_a) {
|
|
for (size_t i = 0; i < n_rows_a; i++) {
|
|
for (size_t j = 0; j < n_cols_a; j++) {
|
|
a[i*n_cols_a + j] = 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
// static unsigned int seed = 123456789; // must be initialized somehow
|
|
|
|
// unsigned int rand_test(void)
|
|
// {
|
|
// seed = (1103515245 * seed + 12345);
|
|
// return (seed >> 16) & 0x7FFF; // 15-bit result
|
|
// }
|
|
|
|
// /* Initializes vector or matrix, randomly. */
|
|
// void init_rand(double *a, const unsigned n_rows_a, const unsigned n_cols_a) {
|
|
// for (size_t i = 0; i < n_rows_a; i++) {
|
|
// for (size_t j = 0; j < n_cols_a; j++) {
|
|
// a[i*n_cols_a + j] = rand_test() / 32767.0;
|
|
// // rand_test() / (double)RAND_MAX;
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
/* Takes and returns a new matrix, t, which is a transpose of the original one, m.
|
|
It's also flat in memory, i.e., 1-D, but it should be looked at as a transpose
|
|
of m, meaning, n_rows_t == n_cols_m, and n_cols_t == n_rows_m.
|
|
The original matrix m stays intact. */
|
|
int __capability * transpose(const int __capability *m, const unsigned n_rows_m, const unsigned n_cols_m, int __capability *t) {
|
|
for (size_t i = 0; i < n_rows_m; i++) {
|
|
for (size_t j = 0; j < n_cols_m; j++) {
|
|
t[j*n_rows_m + i] = m[i*n_cols_m + j];
|
|
}
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
/* Dot product of two arrays, or matrix product
|
|
* Allocates and returns an array.
|
|
* This variant doesn't transpose matrix b, and it's a lot slower. */
|
|
int * __capability dot_simple(const int * __capability a, const unsigned n_rows_a, const unsigned n_cols_a,\
|
|
const int * __capability b, const unsigned n_rows_b, const unsigned n_cols_b) {
|
|
|
|
if (n_cols_a != n_rows_b) {
|
|
// printf("#columns A must be equal to #rows B!\n");
|
|
// system("pause");
|
|
// exit(-2);
|
|
while(1);
|
|
}
|
|
|
|
int * __capability c = malloc(n_rows_a * n_cols_b * sizeof(*c));
|
|
if (c == NULL) {
|
|
// printf("Couldn't allocate memory!\n");
|
|
// system("pause");
|
|
// exit(-1);
|
|
while(1);
|
|
}
|
|
|
|
for (size_t i = 0; i < n_rows_a; i++) {
|
|
for (size_t k = 0; k < n_cols_b; k++) {
|
|
int sum = 0;
|
|
for (size_t j = 0; j < n_cols_a; j++) {
|
|
sum += a[i*n_cols_a + j] * b[j*n_cols_b + k];
|
|
}
|
|
c[i*n_cols_b + k] = sum;
|
|
}
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
/* Dot product of two arrays, or matrix product
|
|
* Allocates and returns an array.
|
|
* This variant transposes matrix b, and it's a lot faster. */
|
|
int * __capability dot(const int * __capability a, const unsigned n_rows_a, const unsigned n_cols_a, \
|
|
const int * __capability b, const unsigned n_rows_b, const unsigned n_cols_b) {
|
|
|
|
if (n_cols_a != n_rows_b) {
|
|
// printf("#columns A must be equal to #rows B!\n");
|
|
// system("pause");
|
|
// exit(-2);
|
|
}
|
|
|
|
int * __capability bt = malloc(n_rows_b * n_cols_b * sizeof(*b));
|
|
|
|
int * __capability c = malloc(n_rows_a * n_cols_b * sizeof(*c));
|
|
|
|
if ((c == NULL) || (bt == NULL)) {
|
|
// printf("Couldn't allocate memory!\n");
|
|
// system("pause");
|
|
// exit(-1);
|
|
}
|
|
|
|
bt = transpose(b, n_rows_b, n_cols_b, bt);
|
|
|
|
for (size_t i = 0; i < n_rows_a; i++) {
|
|
for (size_t k = 0; k < n_cols_b; k++) {
|
|
int sum = 0;
|
|
for (size_t j = 0; j < n_cols_a; j++) {
|
|
sum += a[i*n_cols_a + j] * bt[k*n_rows_b + j];
|
|
}
|
|
c[i*n_cols_b + k] = sum;
|
|
}
|
|
}
|
|
|
|
free(bt);
|
|
|
|
return c;
|
|
}
|
|
|
|
/* Prints vector, or matrix. */
|
|
// void print(const double *a, const unsigned n_rows_a, const unsigned n_cols_a) {
|
|
// for (size_t i = 0; i < n_rows_a; i++) {
|
|
// for (size_t j = 0; j < n_cols_a; j++) {
|
|
// printf("%8.3f ", a[i*n_cols_a + j]);
|
|
// }
|
|
// printf("\n");
|
|
// }
|
|
// printf("\n");
|
|
// }
|
|
|
|
int main(void) {
|
|
/* Intializes random number generator */
|
|
// time_t t;
|
|
// srand((unsigned)time(&t));
|
|
// srand(0);
|
|
|
|
/* For measuring time */
|
|
int t0, t1;
|
|
|
|
const unsigned scale = 20;
|
|
const unsigned n_rows_a = 4 * scale;
|
|
const unsigned n_cols_a = 3 * scale;
|
|
const unsigned n_rows_b = 3 * scale;
|
|
const unsigned n_cols_b = 2 * scale;
|
|
|
|
int __capability *a = malloc(n_rows_a * n_cols_a * sizeof(*a));
|
|
int __capability *b = malloc(n_rows_b * n_cols_b * sizeof(*b));
|
|
int __capability *c = NULL;
|
|
int __capability *d = NULL;
|
|
|
|
if (!a || !b) {
|
|
// printf("Couldn't allocate memory!\n");
|
|
while(1);
|
|
// system("pause");
|
|
// exit(-1);
|
|
}
|
|
|
|
// init_rand(a, n_rows_a, n_cols_a);
|
|
// init_rand(b, n_rows_b, n_cols_b);
|
|
|
|
init_seq(a, n_rows_a, n_cols_a);
|
|
init_seq(b, n_rows_b, n_cols_b);
|
|
|
|
// for (size_t i = 0; i < n_rows_a; i++) {
|
|
// for (size_t j = 0; j < n_cols_a; j++) {
|
|
// a[i*n_cols_a + j] = i*n_cols_a + j;
|
|
// }
|
|
// }
|
|
|
|
// t0 = omp_get_wtime();
|
|
c = dot_simple(a, n_rows_a, n_cols_a, b, n_rows_b, n_cols_b);
|
|
// t1 = omp_get_wtime();
|
|
// printf("Dot Simple: Elapsed time %.3f s\n", t1 - t0);
|
|
|
|
// // t0 = omp_get_wtime();
|
|
d = dot(a, n_rows_a, n_cols_a, b, n_rows_b, n_cols_b);
|
|
// t1 = omp_get_wtime();
|
|
// printf("Dot: Elapsed time %.3f s\n", t1 - t0);
|
|
|
|
// if (scale == 1) {
|
|
// // printf("Matrix A:\n");
|
|
// // print(a, n_rows_a, n_cols_a);
|
|
// // // printf("Matrix B:\n");
|
|
// // print(b, n_rows_b, n_cols_b);
|
|
// // // printf("Matrix C:\n");
|
|
// // print(c, n_rows_a, n_cols_b);
|
|
// // // printf("Matrix D:\n");
|
|
// // print(d, n_rows_a, n_cols_b);
|
|
// }
|
|
|
|
free(a);
|
|
free(b);
|
|
free(c);
|
|
free(d);
|
|
|
|
// system("pause");
|
|
|
|
return(0);
|
|
}
|
|
|
|
#endif // MATMUL_1D
|