-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbenchmark.c
More file actions
124 lines (97 loc) · 4.02 KB
/
benchmark.c
File metadata and controls
124 lines (97 loc) · 4.02 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
/*
* CPU Cache Benchmark
* Computer Science XII - Computer Systems
*
* This program demonstrates how cache memory affects performance
* by comparing sequential vs random memory access patterns.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ITERATIONS 100000000
// Sequential access: read array elements in order (0, 1, 2, 3...)
// This is cache-friendly because the CPU can predict what you need next
double test_sequential(int* array, int size) {
clock_t start = clock();
long sum = 0;
for (int i = 0; i < ITERATIONS; i++) {
sum += array[i % size];
}
clock_t end = clock();
// Prevent compiler from optimizing away the sum
if (sum == -999999) printf("never prints");
return (double)(end - start) / CLOCKS_PER_SEC;
}
// Random access: read array elements in unpredictable order
// This is cache-unfriendly because the CPU can't predict what you need
double test_random(int* array, int* indices, int size) {
clock_t start = clock();
long sum = 0;
for (int i = 0; i < ITERATIONS; i++) {
sum += array[indices[i % size]];
}
clock_t end = clock();
if (sum == -999999) printf("never prints");
return (double)(end - start) / CLOCKS_PER_SEC;
}
// Shuffle array to create random access pattern
void shuffle(int* array, int size) {
for (int i = size - 1; i > 0; i--) {
int j = rand() % (i + 1);
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
int main() {
srand(42); // Fixed seed for reproducibility
printf("==============================================\n");
printf("CPU CACHE BENCHMARK\n");
printf("==============================================\n");
printf("Testing %d memory accesses per test\n\n", ITERATIONS);
// Test different array sizes
// Small arrays fit in L1 cache (~32KB = 8,000 ints)
// Medium arrays fit in L2 cache (~256KB = 64,000 ints)
// Large arrays fit in L3 cache (~8MB = 2,000,000 ints)
// Huge arrays exceed L3 cache
int sizes[] = {1000, 10000, 100000, 1000000, 10000000};
char* labels[] = {"1K (fits in L1)", "10K (fits in L2)", "100K (fits in L3)", "1M (exceeds L3)", "10M (much larger than L3)"};
int num_sizes = 5;
printf("%-25s %15s %15s %10s\n", "Array Size", "Sequential", "Random", "Ratio");
printf("----------------------------------------------------------------------\n");
for (int t = 0; t < num_sizes; t++) {
int size = sizes[t];
// Allocate and initialize array
int* array = (int*)malloc(size * sizeof(int));
int* indices = (int*)malloc(size * sizeof(int));
if (!array || !indices) {
printf("Failed to allocate memory for size %d\n", size);
continue;
}
for (int i = 0; i < size; i++) {
array[i] = i;
indices[i] = i;
}
shuffle(indices, size);
// Run tests
double seq_time = test_sequential(array, size);
double rand_time = test_random(array, indices, size);
double ratio = rand_time / seq_time;
printf("%-25s %12.3f sec %12.3f sec %9.2fx\n",
labels[t], seq_time, rand_time, ratio);
free(array);
free(indices);
}
printf("\n==============================================\n");
printf("WHAT THIS MEANS\n");
printf("==============================================\n");
printf("- Sequential access is faster because the CPU prefetches\n");
printf(" nearby memory into cache before you ask for it.\n");
printf("- Random access defeats prefetching - each access may\n");
printf(" require fetching from slower memory levels.\n");
printf("- As arrays grow beyond cache size, random access gets\n");
printf(" much slower relative to sequential access.\n");
printf("- The 'Ratio' column shows how many times slower random\n");
printf(" access is compared to sequential access.\n");
return 0;
}