Skip to content

Instantly share code, notes, and snippets.

@tomsmeding
Last active October 28, 2019 20:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomsmeding/62c28f05532d82c27524a921f2f3798c to your computer and use it in GitHub Desktop.
Save tomsmeding/62c28f05532d82c27524a921f2f3798c to your computer and use it in GitHub Desktop.
#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