Program Listing for File matrix_cpu.c¶
↰ Return to documentation for file (software/scripts/matrix_cpu.c)
/*
* Matrix Multiplication - CPU Implementation
* Naïve O(n³) algorithm for CUDA vs CPU comparison
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#define DEFAULT_SIZE 512
// Get elapsed time in milliseconds
double get_time_ms(struct timeval* start, struct timeval* end)
{
return (end->tv_sec - start->tv_sec) * 1000.0 +
(end->tv_usec - start->tv_usec) / 1000.0;
}
// Initialize matrix with random values
void init_matrix(float* M, int n)
{
for (int i = 0; i < n * n; i++)
{
M[i] = (float)(rand() % 100) / 100.0f;
}
}
// Naïve O(n³) matrix multiplication: C = A * B
void matrix_multiply(float* A, float* B, float* C, int n, int stream_mode)
{
struct timeval start, now;
gettimeofday(&start, NULL);
int total_rows = n;
int last_percent = -1;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
float sum = 0.0f;
for (int k = 0; k < n; k++)
{
sum += A[i * n + k] * B[k * n + j];
}
C[i * n + j] = sum;
}
if (stream_mode)
{
int percent = ((i + 1) * 100) / total_rows;
if (percent != last_percent)
{
gettimeofday(&now, NULL);
printf("PROGRESS:%d|%.1f\n", percent, get_time_ms(&start, &now));
fflush(stdout);
last_percent = percent;
}
}
}
}
// Verify result (compute checksum)
float checksum(float* M, int n)
{
float sum = 0.0f;
for (int i = 0; i < n * n; i++)
{
sum += M[i];
}
return sum;
}
void print_usage(const char* prog_name)
{
printf("Usage: %s [OPTIONS]\n", prog_name);
printf("\nOptions:\n");
printf(" -n, --size N Matrix size NxN (default: %d)\n", DEFAULT_SIZE);
printf(" -s, --stream Stream progress updates (for race mode)\n");
printf(" -t, --timing-only Only output timing (for benchmarks)\n");
printf(" --help Show this help message\n");
}
int main(int argc, char* argv[])
{
int n = DEFAULT_SIZE;
int stream_mode = 0;
int timing_only = 0;
// Parse command line arguments
for (int i = 1; i < argc; i++)
{
if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--size") == 0)
{
if (i + 1 < argc)
n = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--stream") == 0)
{
stream_mode = 1;
}
else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--timing-only") == 0)
{
timing_only = 1;
}
else if (strcmp(argv[i], "--help") == 0)
{
print_usage(argv[0]);
return 0;
}
}
// Allocate matrices
float* A = (float*)malloc(n * n * sizeof(float));
float* B = (float*)malloc(n * n * sizeof(float));
float* C = (float*)malloc(n * n * sizeof(float));
if (!A || !B || !C)
{
fprintf(stderr, "Error: Failed to allocate memory for %dx%d matrices\n", n, n);
return 1;
}
// Initialize with deterministic seed for reproducibility
srand(42);
init_matrix(A, n);
init_matrix(B, n);
struct timeval start, end;
gettimeofday(&start, NULL);
// Perform multiplication
matrix_multiply(A, B, C, n, stream_mode);
gettimeofday(&end, NULL);
double elapsed = get_time_ms(&start, &end);
if (stream_mode || timing_only)
{
printf("TIME_MS:%.2f\n", elapsed);
printf("CHECKSUM:%.2f\n", checksum(C, n));
}
else
{
printf("Matrix size: %d x %d\n", n, n);
printf("Operations: %.2f million (n³)\n", (double)n * n * n / 1000000.0);
printf("Time: %.2f ms\n", elapsed);
printf("GFLOPS: %.2f\n", (2.0 * n * n * n) / (elapsed * 1000000.0));
printf("TIME_MS:%.2f\n", elapsed);
printf("Checksum: %.2f\n", checksum(C, n));
}
free(A);
free(B);
free(C);
return 0;
}