-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathfalse_sharing.cpp
147 lines (122 loc) · 3.7 KB
/
false_sharing.cpp
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
#include "common.h"
#include <omp.h>
int validated_result;
volatile int output_buffer;
int *a, *b;
int sa, sb;
const int ELEMENT_COUNT = 1 * 1024 * 1024;
void SetupValues() {
// fill with data
pcg32_random_t rng;
pcg32_srandom_r(&rng, 1234, 5678);
sa = sb = 0;
for( int i = 0; i < ELEMENT_COUNT; ++i ) {
sa += a[i] = pcg32_random_r_range(&rng, 0, 255 );
sb += b[i] = pcg32_random_r_range(&rng, 0, 65535 );
}
}
void Setup() {
Timer t;
// allocate arrays
a = (int*)aligned_alloc( 64, sizeof(int) * ELEMENT_COUNT );
b = (int*)aligned_alloc( 64, sizeof(int) * ELEMENT_COUNT );
SetupValues();
printf( "Setup took %fms\n", t.elapsed() );
}
inline int CalcValue( int i ) {
return a[i] + b[i];
}
template<int NUM_THREADS>
void TestFalseSharing() {
int sum=0;
int aligned_sum_store[NUM_THREADS] __attribute__((aligned(64)));
#pragma omp parallel num_threads(NUM_THREADS)
{
int me = omp_get_thread_num();
aligned_sum_store[me] = 0;
//#pragma omp for
for (int i = me; i < ELEMENT_COUNT; i += NUM_THREADS ) {
aligned_sum_store[me] += CalcValue( i );
}
#pragma omp atomic
sum += aligned_sum_store[me];
}
output_buffer = sum;
}
template<int NUM_THREADS>
void TestLocalAccumulator() {
int sum=0;
#pragma omp parallel num_threads(NUM_THREADS)
{
int me = omp_get_thread_num();
int local_accumulator = 0;
//#pragma omp for
for (int i = me; i < ELEMENT_COUNT; i += NUM_THREADS ) {
local_accumulator += CalcValue( i );
}
#pragma omp atomic
sum += local_accumulator;
}
output_buffer = sum;
}
template<int NUM_THREADS>
void TestSplitLoad() {
int sum=0;
const int WORK_LOAD = ELEMENT_COUNT / NUM_THREADS;
#pragma omp parallel num_threads(NUM_THREADS)
{
int me = omp_get_thread_num();
int local_accumulator = 0;
const int start = WORK_LOAD * me;
const int end = WORK_LOAD * (me+1);
//#pragma omp for
for (int i = start; i < end; ++i ) {
local_accumulator += CalcValue( i );
}
#pragma omp atomic
sum += local_accumulator;
}
output_buffer = sum;
}
void TestSinglethreaded() {
int sum=0;
// just one thread
{
int local_accumulator = 0;
for (int i = 0; i < ELEMENT_COUNT; i++) {
local_accumulator += CalcValue( i );
}
sum += local_accumulator;
}
output_buffer = sum;
}
int main() {
Setup();
Test tests[] = {
(Test){ TestSinglethreaded, "Single threaded" },
(Test){ TestFalseSharing<2>, "False sharing (2 threads)" },
(Test){ TestLocalAccumulator<2>, "Local accumulator (2 threads)" },
(Test){ TestSplitLoad<2>, "Split load (2 threads)" },
(Test){ TestFalseSharing<4>, "False sharing (4 threads)" },
(Test){ TestLocalAccumulator<4>, "Local accumulator (4 threads)" },
(Test){ TestSplitLoad<4>, "Split load (4 threads)" },
(Test){ TestFalseSharing<8>, "False sharing (8 threads)" },
(Test){ TestLocalAccumulator<8>, "Local accumulator (8 threads)" },
(Test){ TestSplitLoad<8>, "Split load (8 threads)" },
(Test){ TestFalseSharing<16>, "False sharing (16 threads)" },
(Test){ TestLocalAccumulator<16>, "Local accumulator (16 threads)" },
(Test){ TestSplitLoad<16>, "Split load (16 threads)" },
};
// create a valid result
TestSinglethreaded();
validated_result = output_buffer;
printf( "output_buffer should read %i\n", validated_result );
TestFalseSharing<4>();
printf( "Test FalseSharing [%s] output_buffer = %i\n", validated_result==output_buffer ? "PASSED" : "FAILED", output_buffer );
TestLocalAccumulator<4>();
printf( "Test LocalAccumul [%s] output_buffer = %i\n", validated_result==output_buffer ? "PASSED" : "FAILED", output_buffer );
TestSplitLoad<4>();
printf( "Test SplitLoad [%s] output_buffer = %i\n", validated_result==output_buffer ? "PASSED" : "FAILED", output_buffer );
RunTests( tests );
return validated_result == output_buffer ? 0 : 1;
}