-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSpMV.c
More file actions
225 lines (193 loc) · 7.39 KB
/
SpMV.c
File metadata and controls
225 lines (193 loc) · 7.39 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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#define ANSI_COLOR_BLUE "\x1b[34m" // Color blue for specified output
#define ANSI_COLOR_RESET "\x1b[0m" // Reset color for specified output
#define MATRIXZISE 10 // Size for each size of the square matrix
#define SPARSITY 0.1 // Percentage of sparsity in the matrix
#define RANDOMVALRANGE 10 // Range of random values contained in the matrix (starting from zero)
int nnz; // Amount of non-zero values contained in the sparse matrix
/**
* This methos print all values contained in a matrix, where:
* A: Is the matrix to print
* m: Is the number of rows of A
* n: Is the number of columns of A
**/
void printMatrix(int **A, int m, int n) {
for(int r = 0; r < m; r++) {
for(int c = 0; c < n; c++) {
if(c == 0)
printf("| %d ", A[r][c]);
else if(c == n-1)
printf("%d | \n", A[r][c]);
else
printf("%d ", A[r][c]);
}
}
}
/**
* This method takes an array A and prints all its values, where,
* A: Is the array to print
* length: Is the number of values of A
**/
void printArray(int *A, int length) {
for (int i = 0; i < length; i++) {
if (length == 1)
printf("[ %d ] \n", A[i]);
else if (i == 0)
printf("[ %d ", A[i]);
else if (i == (length - 1))
printf("%d ] \n", A[i]);
else
printf("%d ", A[i]);
}
}
/**
* This method generates random values for making a sparse matrix A, where:
* A: Is the matrix to fill up
* m: Is the number of rows of A
* n: Is the number of columns of A
* returns: nnz (number of nonzero values contained in A)
**/
int **genSparseMatrix(int m, int n) {
srand(time(NULL)); // Seed rand function
int **A = (int **)malloc(m * sizeof(int *));
for (int i = 0; i < m; i++)
A[i] = (int *)malloc(n * sizeof(int));
nnz = m * n * SPARSITY; // Amount of non-zero elements to be stored in A
printf("Non-zero values to be stored: %d\n", nnz); // Prints nnz
int randomValue, randomRow, randomCol, r, c;
// Initialize the matrix with zero values
for(r = 0; r < m; r++) {
for(c = 0; c < n; c++) {
A[r][c] = 0;
}
}
// Fills up matrix with nnz values ranging from zero to RANDOMVALRANGE
for(r = 0; r < nnz; r++) {
randomValue = (rand() % RANDOMVALRANGE) + 1;
randomRow = rand() % m;
randomCol = rand() % n;
A[randomRow][randomCol] = randomValue;
}
return A;
}
/**
* This method takes an array A and initialize all it values to zero, where:
* A: Is the array to initialize
* length: Is the length of A
**/
void initializeArray(int *A, int length) {
for (int i = 0; i < length; i++) {
A[i] = 0;
}
}
/**
* This method takes an array x and fills it up with random values ranging from 1 to RANDOMVALRANGE, where:
* x: Is the array to fill up with random values
* length: Is the length of x
**/
int *genDenseVector(int length) {
srand(time(NULL));
int *x = (int *)malloc(length * sizeof(int));
initializeArray(x, length); // Initialize array with all values being zero
for(int i = 0; i < length; i++) {
x[i] = (rand() % RANDOMVALRANGE) + 1;
}
return x;
}
/**
* This method takes sparse matrix A and checks the total non-zero values stored in it (nnz), where:
* A: Is the sparse matrix to analyze
* m: Is the number of rows of A
* n: Is the number of columns of A
* returns: Total nnz
**/
int checkNNZ(int **A, int m, int n) {
int realNNZ = 0;
for(int r = 0; r < m; r++) {
for(int c = 0; c < n; c++) {
if(A[r][c] != 0)
realNNZ++;
}
}
printf("Non-zero values stored in A: %d \n", realNNZ);
return realNNZ;
}
/**
* This method takes matrix A and separates all non-zero values information into three arrays, where:
* A: Is the matrix to compress
* values: Is the array containing all non-zero values of A
* colIndex: Is the array containing the column indices of the non-zero values in A
* rowIndex: Is the array containing the row indices of the non-zero values in A
* m: Is the row size of A
* n: Is the column size of A
**/
void compression(int **A, int *values, int *colIndex, int *rowIndex, int m, int n) {
int i = 0;
for(int r = 0; r < m; r++) {
for(int c = 0; c < n; c++) {
if(A[r][c] != 0){
values[i] = A[r][c];
colIndex[i] = c;
rowIndex[i] = r;
i++;
}
}
}
printf("Values: ");
printArray(values, nnz);
printf("Col Indices: ");
printArray(colIndex, nnz);
printf("Row Indices: ");
printArray(rowIndex, nnz);
}
/**
* This method takes the compressed information of A and computes SpMV (Sparse Matrix-Vector Multiplication), where:
* values: Is the array containing all non-zero values of A
* colIndex: Is the array containing the column indices of the non-zero values in A
* rowIndex: Is the array containing the row indices of the non-zero values in A
* x: Is the vector multiplying matrix A
* m: Is the row size of A
**/
int *solutionSpMV(int *values, int *colIndex, int *rowIndex, int *x, int m) {
int *solution = (int *)malloc(m * sizeof(int)); // Allocation of memory for solution array
// Initialize solution array with all values being zero
initializeArray(solution, m);
// Computes SpMV using the compressed information about A (values, colIndex, and rowIndex arrays)
for(int i = 0; i < nnz; i++) {
int val = (values[i] * x[colIndex[i]]);
solution[rowIndex[i]] += (values[i] * x[colIndex[i]]);
}
return solution;
}
/********************************** MAIN ***********************************/
int main() {
int m = MATRIXZISE; // Number of rows in matrix A
int n = MATRIXZISE; // Number of columns in matrix A
printf("Rows: %d \n", m);
printf("Columns: %d \n", n);
int **A = genSparseMatrix(m, n); // Creates sparse matrix A
printf("Matrix A: \n");
printMatrix(A, m, n); // Prints matrix A
int *x = genDenseVector(m); // Creates vector that multiplies matrix A
printf("Vector x: ");
printArray(x,m); // Prints vector x
int realNNZ = checkNNZ(A,m,n);
double sparsePercentage = (realNNZ * 100) / (double)(m*n);
printf("Sparse percentage: %f \n", sparsePercentage);
printf("\n");
// Arrays containing the compressed information of A
printf("Compressed information of A: \n");
int *values = (int *)malloc(nnz * sizeof(int)); // Non-zero values contained in A;
int *colIndex = (int *)malloc(nnz * sizeof(int)); // Column indices of the non-zero values located in A
int *rowIndex = (int *)malloc(nnz * sizeof(int)); // Row indicex of the non-zero values located in A
compression(A,values,colIndex,rowIndex,m,n); // Compress all valuable info about A's non-zero values in values, colIndex, and rowIndex
printf("\n");
int *y = solutionSpMV(values,colIndex,rowIndex,x,m); // Solves SpMV using the compressed information
printf("Solution: ");
printArray(y,m);
return 0;
}