Last active
October 28, 2019 20:27
-
-
Save tomsmeding/62c28f05532d82c27524a921f2f3798c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include <thread> | |
#include <vector> | |
#include <algorithm> | |
#include <atomic> | |
using namespace std; | |
template <typename T> | |
T* new_align(size_t nelems, int bits_align) { | |
uintptr_t ptr = reinterpret_cast<uintptr_t>(new char[nelems * sizeof(T) + (1 << bits_align)]); | |
uintptr_t mask = (1 << bits_align) - 1; | |
if (ptr & mask) ptr = (ptr + (1 << bits_align)) & ~mask; | |
return reinterpret_cast<T*>(ptr); | |
} | |
int main() { | |
constexpr int cache_line_bits = 6; | |
constexpr size_t cache_line_size = 1 << cache_line_bits; | |
static_assert(cache_line_size == 64, ""); | |
constexpr size_t arr_size = 2 * cache_line_size + 1; | |
constexpr size_t num_iters = 0x1234; | |
// using int_array_type = unsigned; // Linux GCC: some number of times 0x1234, consistent | |
// using int_array_type = volatile unsigned; // Linux GCC: inconsistent, !! on 61 % 64 | |
using int_array_type = atomic<unsigned>; // Linux GCC: 8 times 0x1234, consistent | |
char *arr = new_align<char>(arr_size, cache_line_bits); | |
fill(arr, arr + arr_size, 0); | |
int_array_type *int_arr = reinterpret_cast<decltype(int_arr)>(arr + 1); | |
static_assert(sizeof(int_arr[0]) == sizeof(unsigned), ""); | |
constexpr size_t int_arr_size = 2 * cache_line_size / sizeof(int); | |
constexpr size_t num_threads = 8; | |
vector<thread> threads(num_threads); | |
for (thread &th : threads) { | |
th = thread([int_arr]() { | |
// __asm volatile ("// XXX start\n"); | |
for (size_t iter = 0; iter < num_iters; iter++) { | |
__asm volatile (""); | |
for (size_t i = 0; i < int_arr_size; i++) { | |
int_arr[i] += 0x00010001; | |
} | |
} | |
// __asm volatile ("// XXX end\n"); | |
}); | |
} | |
for (thread &th : threads) th.join(); | |
for (size_t i = 0; i < int_arr_size; i++) { | |
printf("%p (%%64: %2zu): 0x%08X", &int_arr[i], (uintptr_t)&int_arr[i] % 64, (unsigned)int_arr[i]); | |
if ((int_arr[i] >> 16) != (int_arr[i] & 0xffff)) printf(" !!"); | |
printf("\n"); | |
} | |
printf("%lf\n", static_cast<double>(int_arr[0] & 0xffff) / 0x1234); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment