-
Notifications
You must be signed in to change notification settings - Fork 0
/
bomb2.c
167 lines (121 loc) · 4.37 KB
/
bomb2.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint8_t u8;
#define NUM_ACCESSES 100000
#define L2_CACHE_SIZE 0x100000 // 1024KB => 1MB
#define CACHE_LINE_SIZE 64 // 64B
struct timespec start_time, end_time;
void read_cache_misses_sequential(volatile u8 *memory, u32 size)
{
int i;
for (i = 0; i < size; i += CACHE_LINE_SIZE)
{
u8 value = memory[i];
(void)value;
}
}
void read_cache_misses_random(volatile u8 *memory, u32 size)
{
int i;
// Random read
for (i = 0; i < size; i+= CACHE_LINE_SIZE)
{
int index = rand() % size;
u8 value = memory[index];
(void)value;
}
}
void write_cache_misses_sequential(volatile u8 *memory, u32 size)
{
int i;
for (i = 0; i < size; i += CACHE_LINE_SIZE)
{
memory[i] = 0;
}
}
void write_cache_misses_random(volatile u8 *memory, u32 size)
{
int i;
// Random access pattern
for (i = 0; i < size; i += CACHE_LINE_SIZE)
{
int rand_index = rand() % size;
memory[rand_index] = 0;
}
}
void* thread_function() {
volatile u8 *memory;
u32 size = L2_CACHE_SIZE;
int m_size = L2_CACHE_SIZE * 2;
double elapsed_time;
// Allocate a memory block that is larger than the L2 cache size
memory = malloc(m_size);
// Measure cache misses for sequential read
clock_gettime(CLOCK_MONOTONIC, &start_time); // start clock
for (int i = 0; i < NUM_ACCESSES; i++) {
read_cache_misses_sequential(memory, size);
}
clock_gettime(CLOCK_MONOTONIC, &end_time); // end clock
printf("\nSequential Read\n\nMalloc size: %d\nNum Access: %d\nElapsed time: %.6f seconds\n\n", m_size, NUM_ACCESSES, (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) / 1e9);
// Free the memory block
free((void *)memory);
// Allocate a memory block that is larger than the L2 cache size
memory = malloc(m_size);
// Measure cache misses for random read
clock_gettime(CLOCK_MONOTONIC, &start_time); // start clock
for (int i = 0; i < NUM_ACCESSES; i++) {
read_cache_misses_random(memory, size);
}
clock_gettime(CLOCK_MONOTONIC, &end_time); // end clock
printf("\nRandom Read\n\nMalloc size: %d\nNum Access: %d\nElapsed time: %.6f seconds\n\n", m_size, NUM_ACCESSES, (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) / 1e9);
// Free the memory block
free((void *)memory);
// Allocate a memory block that is larger than the L2 cache size
memory = malloc(m_size);
// Measure cache misses for sequential write
clock_gettime(CLOCK_MONOTONIC, &start_time); // start clock
for (int i = 0; i < NUM_ACCESSES; i++) {
write_cache_misses_sequential(memory, size);
}
clock_gettime(CLOCK_MONOTONIC, &end_time); // end clock
printf("\nSequential Write\n\nMalloc size: %d\nNum Access: %d\nElapsed time: %.6f seconds\n\n", m_size, NUM_ACCESSES, (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) / 1e9);
// Free the memory block
free((void *)memory);
// Allocate a memory block that is larger than the L2 cache size
memory = malloc(m_size);
// Measure cache misses for random write
clock_gettime(CLOCK_MONOTONIC, &start_time); // start clock
for (int i = 0; i < NUM_ACCESSES; i++) {
write_cache_misses_random(memory, size);
}
clock_gettime(CLOCK_MONOTONIC, &end_time); // end clock
printf("\nRandom Write\n\nMalloc size: %d\nNum Access: %d\nElapsed time: %.6f seconds\n\n", m_size, NUM_ACCESSES, (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) / 1e9);
// Free the memory block
free((void *)memory);
}
int main()
{
// process priority value
int niceValue = -20;
// set process priority
// nice(niceValue);
// Initialize random seed
srand(1234);
// Cortex-A72 Dual Core => 2 thread
pthread_t thread1, thread2; // thread identifiers
// Create thread 1
pthread_create(&thread1, NULL, thread_function, NULL);
// Create thread 2
pthread_create(&thread2, NULL, thread_function, NULL);
// Wait for thread 1 to finish
pthread_join(thread1, NULL);
// Wait for thread 2 to finish
pthread_join(thread2, NULL);
return 0;
}