-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathQ1.c
More file actions
70 lines (60 loc) · 2.22 KB
/
Copy pathQ1.c
File metadata and controls
70 lines (60 loc) · 2.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
1. Cache Locality and Matrix Layout
CPUs don’t go to RAM to pick up the data byte-by-byte; rather they bring blocks of data into memory named cache lines (64 bytes in size). Since C keeps multi-dimensional arrays in row-major order, all of the elements that are adjacent in a row are physically close to each other in memory. */
#include <stdio.h>
#include <stdlib.h>
typedef enum {
MAT_SUCCESS = 0,
MAT_ERR_NULL_PTR = -1,
MAT_ERR_OUT_OF_MEMORY = -2,
MAT_ERR_DIM_MISMATCH = -3
} MatError;
typedef struct {
size_t rows;
size_t cols;
double* data;
} Matrix;
void matrix_destroy(Matrix* mat) {
if (mat != NULL) {
if (mat->data != NULL) {
free(mat->data);
mat->data = NULL; // Prevent dangling pointer
}
mat->rows = 0;
mat->cols = 0;
}
}
MatError matrix_create(Matrix* mat, size_t rows, size_t cols) {
if (mat == NULL) return MAT_ERR_NULL_PTR;
mat->rows = rows;
mat->cols = cols;
// Allocate contiguous block to prevent fragmentation and aid CPU prefetching
mat->data = (double*)calloc(rows * cols, sizeof(double));
if (mat->data == NULL) {
matrix_destroy(mat); // Cleanup on failure
return MAT_ERR_OUT_OF_MEMORY;
}
return MAT_SUCCESS;
}
MatError matrix_multiply_optimized(const Matrix* A, const Matrix* B, Matrix* C) {
// 1. "Exception" Handling: Validate inputs (Null pointer checks)
if (A == NULL || B == NULL || C == NULL) return MAT_ERR_NULL_PTR;
if (A->data == NULL || B->data == NULL || C->data == NULL) return MAT_ERR_NULL_PTR;
// 2. Memory Safety: Validate bounds/dimensions for math operation
if (A->cols != B->rows || C->rows != A->rows || C->cols != B->cols) {
return MAT_ERR_DIM_MISMATCH;
}
size_t N = A->rows;
size_t K = A->cols;
size_t M = B->cols;
for (size_t i = 0; i < N; ++i) {
for (size_t k = 0; k < K; ++k) {
double a_ik = A->data[i * K + k]; // Read once per inner loop
for (size_t j = 0; j < M; ++j) {
// Both C and B are accessed sequentially in memory (cache friendly)
C->data[i * M + j] += a_ik * B->data[k * M + j];
}
}
}
return MAT_SUCCESS;
}