/// /// @file aligned_vector.hpp /// /// Copyright (C) 2020 Kim Walisch, /// /// This file is distributed under the BSD License. See the COPYING /// file in the top level directory. /// #ifndef ALIGNED_VECTOR_HPP #define ALIGNED_VECTOR_HPP #include #include /// Maximum cache line size of current CPUs. /// Note that in 2019 all x86 CPU have a cache line size of 64 bytes. /// However there are CPUs out there that have much larger cache line /// sizes e.g. IBM z13 CPUs from 2015 have a cache line size of 256 /// bytes. Hence in order to be future-proof we set the maximum cache /// line size to 512 bytes. /// #ifndef CACHE_LINE_SIZE #define CACHE_LINE_SIZE (1 << 9) #endif namespace primecount { /// The aligned_vector class aligns each of its elements on a /// new cache line in order to avoid false sharing (cache /// trashing) when multiple threads write to adjacent elements. /// @warning: Does not default initialize memory. /// template class aligned_vector { static_assert(sizeof(T) < CACHE_LINE_SIZE, "sizeof(T) must be < CACHE_LINE_SIZE"); public: aligned_vector() = default; aligned_vector(std::size_t size) : vect_(size) { } void resize(std::size_t size) { vect_.resize(size); } std::size_t size() const { return vect_.size(); } T& operator[](std::size_t pos) { return vect_[pos].val; } char unused() { vect_[0].pad[0] = 123; return vect_[0].pad[0]; } private: struct CacheLine { T val; // We cannot use alignas(CACHE_LINE_SIZE) for the // CacheLine struct as GCC does not yet support // alignas(n) with n > 128. Also alignas(n) for // over-aligned data and dynamic memory allocation // is only supported since C++17. char pad[CACHE_LINE_SIZE - sizeof(T)]; }; pod_vector vect_; }; } // namespace #endif