* @brief Fetches the cache line size using OS-specific APIs. * Supports Linux, macOS, and Windows. * * It's easier to use the @b `std::hardware_destructive_interference_size` * in C++ 17 and newer, if the `__cpp_lib_hardware_interference_size` feature * macro is defined. But this will be incorrect, if the compilation platform * is different from the runtime platform. * * A
| 2780 | * between Intel and AMD! |
| 2781 | */ |
| 2782 | std::size_t fetch_cache_line_width() { |
| 2783 | |
| 2784 | #if defined(__linux__) |
| 2785 | // On Linux, we can read the cache line size and the L2 cache size from the |
| 2786 | // "sysfs" virtual filesystem. It can provide the properties of each individual |
| 2787 | // CPU core. |
| 2788 | std::string file_contents = read_file_contents("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size"); |
| 2789 | std::size_t cache_line_size = std::stoull(file_contents); |
| 2790 | return cache_line_size; |
| 2791 | |
| 2792 | #elif defined(__APPLE__) |
| 2793 | // On macOS, we can use the `sysctlbyname` function to read the |
| 2794 | // `hw.cachelinesize` and `hw.l2cachesize` values into unsigned integers. |
| 2795 | // You can achieve the same by using the `sysctl -a` command-line utility. |
| 2796 | size_t size; |
| 2797 | size_t len = sizeof(size); |
| 2798 | if (sysctlbyname("hw.cachelinesize", &size, &len, nullptr, 0) == 0) return size; |
| 2799 | |
| 2800 | #elif defined(_WIN32) |
| 2801 | SYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer[256]; |
| 2802 | DWORD len = sizeof(buffer); |
| 2803 | if (GetLogicalProcessorInformation(buffer, &len)) |
| 2804 | for (size_t i = 0; i < len / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++i) |
| 2805 | if (buffer[i].Relationship == RelationCache && buffer[i].Cache.Level == 1) return buffer[i].Cache.LineSize; |
| 2806 | #endif |
| 2807 | |
| 2808 | return 0; |
| 2809 | } |
| 2810 | |
| 2811 | /** |
| 2812 | * @brief A minimalistic pointer with non-unit stride/step. |
no test coverage detected