split c11_atomics_benchmarks.cpp up in an attempt to improve compile time
authorJacob Lifshay <programmerjake@gmail.com>
Wed, 27 Jul 2022 01:57:29 +0000 (18:57 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Wed, 27 Jul 2022 01:57:29 +0000 (18:57 -0700)
src/common/c11_atomics/c11_atomics_benchmarks.cpp
src/common/c11_atomics/i16.cpp [new file with mode: 0644]
src/common/c11_atomics/i32.cpp [new file with mode: 0644]
src/common/c11_atomics/i64.cpp [new file with mode: 0644]
src/common/c11_atomics/i8.cpp [new file with mode: 0644]
src/common/c11_atomics/internals.h [new file with mode: 0644]
src/common/c11_atomics/u16.cpp [new file with mode: 0644]
src/common/c11_atomics/u32.cpp [new file with mode: 0644]
src/common/c11_atomics/u64.cpp [new file with mode: 0644]
src/common/c11_atomics/u8.cpp [new file with mode: 0644]

index 20d02b0ac18708627f678e49d33d86998e59537d..e6d18fbcf98d9ae01f63ead43f7090727ccc73d8 100644 (file)
@@ -1,216 +1,9 @@
 #include "c11_atomics_benchmarks.h"
-#include <atomic>
-#include <cstdint>
-#include <memory>
-#include <sstream>
-#include <string_view>
-#include <type_traits>
-
-template <typename T> struct IntTypeName;
-
-template <typename T>
-inline constexpr std::string_view int_type_name = IntTypeName<T>::name;
-
-#define INT_TYPE_NAME(sz, ui, uint)                                           \
-    template <> struct IntTypeName<std::uint##sz##_t> final                   \
-    {                                                                         \
-        static constexpr std::string_view name = #ui #sz;                     \
-    };
-
-INT_TYPE_NAME(8, u, uint)
-INT_TYPE_NAME(16, u, uint)
-INT_TYPE_NAME(32, u, uint)
-INT_TYPE_NAME(64, u, uint)
-INT_TYPE_NAME(8, i, int)
-INT_TYPE_NAME(16, i, int)
-INT_TYPE_NAME(32, i, int)
-INT_TYPE_NAME(64, i, int)
-
-template <std::memory_order order> struct MemoryOrderName;
-
-template <std::memory_order order>
-inline constexpr std::string_view memory_order_name =
-    MemoryOrderName<order>::name;
-
-#define MEMORY_ORDER_NAME(order)                                              \
-    template <> struct MemoryOrderName<std::memory_order_##order> final       \
-    {                                                                         \
-        static constexpr std::string_view name = #order;                      \
-    };
-
-MEMORY_ORDER_NAME(relaxed)
-MEMORY_ORDER_NAME(acquire)
-MEMORY_ORDER_NAME(release)
-MEMORY_ORDER_NAME(acq_rel)
-MEMORY_ORDER_NAME(seq_cst)
-
-template <typename T> using Buf = std::shared_ptr<std::vector<std::atomic<T>>>;
-
-template <typename Fn, typename T, typename... NameParts>
-static void push_atomic_bench(std::vector<Benchmark> &benches,
-                              const Config &config, Buf<T> buf, Fn fn,
-                              NameParts &&...name_parts)
-{
-    auto log2_stride = config.log2_stride;
-    std::size_t index_mask = 1;
-    index_mask <<= config.log2_stride;
-    index_mask <<= config.log2_memory_location_count;
-    index_mask--;
-    push_bench(
-        benches,
-        [buf, fn, index_mask, log2_stride](T input, std::uint64_t iteration,
-                                           std::uint32_t thread_num) {
-            std::size_t index = iteration;
-            index ^= static_cast<std::size_t>(thread_num) * 0x12345;
-            index <<= log2_stride;
-            index &= index_mask;
-            std::atomic<T> *atomic = &(*buf)[index];
-            input ^= static_cast<T>(iteration);
-            return fn(input, atomic, iteration ^ thread_num);
-        },
-        T{}, name_parts...);
-}
-
-template <typename T, std::memory_order order>
-static void rmw_benchmarks(std::vector<Benchmark> &benches,
-                           const Config &config, Buf<T> buf)
-{
-    push_atomic_bench(
-        benches, config, buf,
-        [](T input, std::atomic<T> *atomic, std::uint64_t) {
-            return std::atomic_exchange_explicit(atomic, input, order);
-        },
-        "atomic_exchange_", int_type_name<T>, "_", memory_order_name<order>);
-    push_atomic_bench(
-        benches, config, buf,
-        [](T input, std::atomic<T> *atomic, std::uint64_t) {
-            return std::atomic_fetch_add_explicit(atomic, input, order);
-        },
-        "atomic_fetch_add_", int_type_name<T>, "_", memory_order_name<order>);
-    push_atomic_bench(
-        benches, config, buf,
-        [](T input, std::atomic<T> *atomic, std::uint64_t) {
-            return std::atomic_fetch_sub_explicit(atomic, input, order);
-        },
-        "atomic_fetch_sub_", int_type_name<T>, "_", memory_order_name<order>);
-    push_atomic_bench(
-        benches, config, buf,
-        [](T input, std::atomic<T> *atomic, std::uint64_t) {
-            return std::atomic_fetch_and_explicit(atomic, input, order);
-        },
-        "atomic_fetch_and_", int_type_name<T>, "_", memory_order_name<order>);
-    push_atomic_bench(
-        benches, config, buf,
-        [](T input, std::atomic<T> *atomic, std::uint64_t) {
-            return std::atomic_fetch_or_explicit(atomic, input, order);
-        },
-        "atomic_fetch_or_", int_type_name<T>, "_", memory_order_name<order>);
-    push_atomic_bench(
-        benches, config, buf,
-        [](T input, std::atomic<T> *atomic, std::uint64_t) {
-            return std::atomic_fetch_xor_explicit(atomic, input, order);
-        },
-        "atomic_fetch_xor_", int_type_name<T>, "_", memory_order_name<order>);
-}
-
-template <typename T, std::memory_order order>
-static void load_benchmarks(std::vector<Benchmark> &benches,
-                            const Config &config, Buf<T> buf)
-{
-    push_atomic_bench(
-        benches, config, buf,
-        [](T, std::atomic<T> *atomic, std::uint64_t) {
-            return std::atomic_load_explicit(atomic, order);
-        },
-        "atomic_load_", int_type_name<T>, "_", memory_order_name<order>);
-}
-
-template <typename T, std::memory_order order>
-static void store_benchmarks(std::vector<Benchmark> &benches,
-                             const Config &config, Buf<T> buf)
-{
-    push_atomic_bench(
-        benches, config, buf,
-        [](T input, std::atomic<T> *atomic, std::uint64_t) {
-            return std::atomic_store_explicit(atomic, input, order);
-        },
-        "atomic_store_", int_type_name<T>, "_", memory_order_name<order>);
-}
-
-template <typename T, std::memory_order succ, std::memory_order fail>
-static void cmp_xchg_benchmarks(std::vector<Benchmark> &benches,
-                                const Config &config, Buf<T> buf)
-{
-    push_atomic_bench(
-        benches, config, buf,
-        [](T input, std::atomic<T> *atomic, std::uint64_t state) {
-            T expected = state;
-            bool succeeded = std::atomic_compare_exchange_weak_explicit(
-                atomic, &expected, input, succ, fail);
-            return std::pair(expected, succeeded);
-        },
-        "atomic_compare_exchange_weak_", int_type_name<T>, "_",
-        memory_order_name<succ>, "_", memory_order_name<fail>);
-    push_atomic_bench(
-        benches, config, buf,
-        [](T input, std::atomic<T> *atomic, std::uint64_t state) {
-            T expected = state;
-            bool succeeded = std::atomic_compare_exchange_strong_explicit(
-                atomic, &expected, input, succ, fail);
-            return std::pair(expected, succeeded);
-        },
-        "atomic_compare_exchange_strong_", int_type_name<T>, "_",
-        memory_order_name<succ>, "_", memory_order_name<fail>);
-}
-
-template <typename T>
-static void benchmarks(std::vector<Benchmark> &benches, const Config &config)
-{
-    std::size_t buf_size = 1;
-    buf_size <<= config.log2_memory_location_count;
-    buf_size <<= config.log2_stride;
-    Buf<T> buf = std::make_shared<std::vector<std::atomic<T>>>(buf_size);
-
-    rmw_benchmarks<T, std::memory_order_relaxed>(benches, config, buf);
-    rmw_benchmarks<T, std::memory_order_acquire>(benches, config, buf);
-    rmw_benchmarks<T, std::memory_order_release>(benches, config, buf);
-    rmw_benchmarks<T, std::memory_order_acq_rel>(benches, config, buf);
-    rmw_benchmarks<T, std::memory_order_seq_cst>(benches, config, buf);
-
-    load_benchmarks<T, std::memory_order_relaxed>(benches, config, buf);
-    load_benchmarks<T, std::memory_order_acquire>(benches, config, buf);
-    load_benchmarks<T, std::memory_order_seq_cst>(benches, config, buf);
-
-    store_benchmarks<T, std::memory_order_relaxed>(benches, config, buf);
-    store_benchmarks<T, std::memory_order_release>(benches, config, buf);
-    store_benchmarks<T, std::memory_order_seq_cst>(benches, config, buf);
-
-    cmp_xchg_benchmarks<T, std::memory_order_relaxed,
-                        std::memory_order_relaxed>(benches, config, buf);
-
-    cmp_xchg_benchmarks<T, std::memory_order_acquire,
-                        std::memory_order_relaxed>(benches, config, buf);
-    cmp_xchg_benchmarks<T, std::memory_order_acquire,
-                        std::memory_order_acquire>(benches, config, buf);
-
-    cmp_xchg_benchmarks<T, std::memory_order_release,
-                        std::memory_order_relaxed>(benches, config, buf);
-
-    cmp_xchg_benchmarks<T, std::memory_order_acq_rel,
-                        std::memory_order_relaxed>(benches, config, buf);
-    cmp_xchg_benchmarks<T, std::memory_order_acq_rel,
-                        std::memory_order_acquire>(benches, config, buf);
-
-    cmp_xchg_benchmarks<T, std::memory_order_seq_cst,
-                        std::memory_order_relaxed>(benches, config, buf);
-    cmp_xchg_benchmarks<T, std::memory_order_seq_cst,
-                        std::memory_order_acquire>(benches, config, buf);
-    cmp_xchg_benchmarks<T, std::memory_order_seq_cst,
-                        std::memory_order_seq_cst>(benches, config, buf);
-}
+#include "internals.h"
 
 std::vector<Benchmark> c11_atomics_benchmarks(const Config &config)
 {
+    using namespace c11_atomics;
     std::vector<Benchmark> benches;
     benchmarks<std::uint8_t>(benches, config);
     benchmarks<std::uint16_t>(benches, config);
diff --git a/src/common/c11_atomics/i16.cpp b/src/common/c11_atomics/i16.cpp
new file mode 100644 (file)
index 0000000..a84f360
--- /dev/null
@@ -0,0 +1,4 @@
+#include "internals.h"
+
+template void c11_atomics::benchmarks<std::int16_t>(
+    std::vector<Benchmark> &benches, const Config &config);
diff --git a/src/common/c11_atomics/i32.cpp b/src/common/c11_atomics/i32.cpp
new file mode 100644 (file)
index 0000000..5cf88db
--- /dev/null
@@ -0,0 +1,4 @@
+#include "internals.h"
+
+template void c11_atomics::benchmarks<std::int32_t>(
+    std::vector<Benchmark> &benches, const Config &config);
diff --git a/src/common/c11_atomics/i64.cpp b/src/common/c11_atomics/i64.cpp
new file mode 100644 (file)
index 0000000..30bc0f7
--- /dev/null
@@ -0,0 +1,4 @@
+#include "internals.h"
+
+template void c11_atomics::benchmarks<std::int64_t>(
+    std::vector<Benchmark> &benches, const Config &config);
diff --git a/src/common/c11_atomics/i8.cpp b/src/common/c11_atomics/i8.cpp
new file mode 100644 (file)
index 0000000..6cf1c42
--- /dev/null
@@ -0,0 +1,4 @@
+#include "internals.h"
+
+template void c11_atomics::benchmarks<std::int8_t>(
+    std::vector<Benchmark> &benches, const Config &config);
diff --git a/src/common/c11_atomics/internals.h b/src/common/c11_atomics/internals.h
new file mode 100644 (file)
index 0000000..7640ee6
--- /dev/null
@@ -0,0 +1,232 @@
+#pragma once
+
+#include "../../harness.h"
+#include <atomic>
+#include <cstdint>
+
+namespace c11_atomics
+{
+
+template <typename T> struct IntTypeName;
+
+template <typename T>
+inline constexpr std::string_view int_type_name = IntTypeName<T>::name;
+
+#define INT_TYPE_NAME(sz, ui, uint)                                           \
+    template <> struct IntTypeName<std::uint##sz##_t> final                   \
+    {                                                                         \
+        static constexpr std::string_view name = #ui #sz;                     \
+    };
+
+INT_TYPE_NAME(8, u, uint)
+INT_TYPE_NAME(16, u, uint)
+INT_TYPE_NAME(32, u, uint)
+INT_TYPE_NAME(64, u, uint)
+INT_TYPE_NAME(8, i, int)
+INT_TYPE_NAME(16, i, int)
+INT_TYPE_NAME(32, i, int)
+INT_TYPE_NAME(64, i, int)
+
+template <std::memory_order order> struct MemoryOrderName;
+
+template <std::memory_order order>
+inline constexpr std::string_view memory_order_name =
+    MemoryOrderName<order>::name;
+
+#define MEMORY_ORDER_NAME(order)                                              \
+    template <> struct MemoryOrderName<std::memory_order_##order> final       \
+    {                                                                         \
+        static constexpr std::string_view name = #order;                      \
+    };
+
+MEMORY_ORDER_NAME(relaxed)
+MEMORY_ORDER_NAME(acquire)
+MEMORY_ORDER_NAME(release)
+MEMORY_ORDER_NAME(acq_rel)
+MEMORY_ORDER_NAME(seq_cst)
+
+template <typename T> using Buf = std::shared_ptr<std::vector<std::atomic<T>>>;
+
+template <typename Fn, typename T, typename... NameParts>
+static void push_atomic_bench(std::vector<Benchmark> &benches,
+                              const Config &config, Buf<T> buf, Fn fn,
+                              NameParts &&...name_parts)
+{
+    auto log2_stride = config.log2_stride;
+    std::size_t index_mask = 1;
+    index_mask <<= config.log2_stride;
+    index_mask <<= config.log2_memory_location_count;
+    index_mask--;
+    push_bench(
+        benches,
+        [buf, fn, index_mask, log2_stride](T input, std::uint64_t iteration,
+                                           std::uint32_t thread_num) {
+            std::size_t index = iteration;
+            index ^= static_cast<std::size_t>(thread_num) * 0x12345;
+            index <<= log2_stride;
+            index &= index_mask;
+            std::atomic<T> *atomic = &(*buf)[index];
+            input ^= static_cast<T>(iteration);
+            return fn(input, atomic, iteration ^ thread_num);
+        },
+        T{}, name_parts...);
+}
+
+template <typename T, std::memory_order order>
+static void rmw_benchmarks(std::vector<Benchmark> &benches,
+                           const Config &config, Buf<T> buf)
+{
+    push_atomic_bench(
+        benches, config, buf,
+        [](T input, std::atomic<T> *atomic, std::uint64_t) {
+            return std::atomic_exchange_explicit(atomic, input, order);
+        },
+        "atomic_exchange_", int_type_name<T>, "_", memory_order_name<order>);
+    push_atomic_bench(
+        benches, config, buf,
+        [](T input, std::atomic<T> *atomic, std::uint64_t) {
+            return std::atomic_fetch_add_explicit(atomic, input, order);
+        },
+        "atomic_fetch_add_", int_type_name<T>, "_", memory_order_name<order>);
+    push_atomic_bench(
+        benches, config, buf,
+        [](T input, std::atomic<T> *atomic, std::uint64_t) {
+            return std::atomic_fetch_sub_explicit(atomic, input, order);
+        },
+        "atomic_fetch_sub_", int_type_name<T>, "_", memory_order_name<order>);
+    push_atomic_bench(
+        benches, config, buf,
+        [](T input, std::atomic<T> *atomic, std::uint64_t) {
+            return std::atomic_fetch_and_explicit(atomic, input, order);
+        },
+        "atomic_fetch_and_", int_type_name<T>, "_", memory_order_name<order>);
+    push_atomic_bench(
+        benches, config, buf,
+        [](T input, std::atomic<T> *atomic, std::uint64_t) {
+            return std::atomic_fetch_or_explicit(atomic, input, order);
+        },
+        "atomic_fetch_or_", int_type_name<T>, "_", memory_order_name<order>);
+    push_atomic_bench(
+        benches, config, buf,
+        [](T input, std::atomic<T> *atomic, std::uint64_t) {
+            return std::atomic_fetch_xor_explicit(atomic, input, order);
+        },
+        "atomic_fetch_xor_", int_type_name<T>, "_", memory_order_name<order>);
+}
+
+template <typename T, std::memory_order order>
+static void load_benchmarks(std::vector<Benchmark> &benches,
+                            const Config &config, Buf<T> buf)
+{
+    push_atomic_bench(
+        benches, config, buf,
+        [](T, std::atomic<T> *atomic, std::uint64_t) {
+            return std::atomic_load_explicit(atomic, order);
+        },
+        "atomic_load_", int_type_name<T>, "_", memory_order_name<order>);
+}
+
+template <typename T, std::memory_order order>
+static void store_benchmarks(std::vector<Benchmark> &benches,
+                             const Config &config, Buf<T> buf)
+{
+    push_atomic_bench(
+        benches, config, buf,
+        [](T input, std::atomic<T> *atomic, std::uint64_t) {
+            return std::atomic_store_explicit(atomic, input, order);
+        },
+        "atomic_store_", int_type_name<T>, "_", memory_order_name<order>);
+}
+
+template <typename T, std::memory_order succ, std::memory_order fail>
+static void cmp_xchg_benchmarks(std::vector<Benchmark> &benches,
+                                const Config &config, Buf<T> buf)
+{
+    push_atomic_bench(
+        benches, config, buf,
+        [](T input, std::atomic<T> *atomic, std::uint64_t state) {
+            T expected = state;
+            bool succeeded = std::atomic_compare_exchange_weak_explicit(
+                atomic, &expected, input, succ, fail);
+            return std::pair(expected, succeeded);
+        },
+        "atomic_compare_exchange_weak_", int_type_name<T>, "_",
+        memory_order_name<succ>, "_", memory_order_name<fail>);
+    push_atomic_bench(
+        benches, config, buf,
+        [](T input, std::atomic<T> *atomic, std::uint64_t state) {
+            T expected = state;
+            bool succeeded = std::atomic_compare_exchange_strong_explicit(
+                atomic, &expected, input, succ, fail);
+            return std::pair(expected, succeeded);
+        },
+        "atomic_compare_exchange_strong_", int_type_name<T>, "_",
+        memory_order_name<succ>, "_", memory_order_name<fail>);
+}
+
+template <typename T>
+void benchmarks(std::vector<Benchmark> &benches, const Config &config)
+{
+    std::size_t buf_size = 1;
+    buf_size <<= config.log2_memory_location_count;
+    buf_size <<= config.log2_stride;
+    Buf<T> buf = std::make_shared<std::vector<std::atomic<T>>>(buf_size);
+
+    rmw_benchmarks<T, std::memory_order_relaxed>(benches, config, buf);
+    rmw_benchmarks<T, std::memory_order_acquire>(benches, config, buf);
+    rmw_benchmarks<T, std::memory_order_release>(benches, config, buf);
+    rmw_benchmarks<T, std::memory_order_acq_rel>(benches, config, buf);
+    rmw_benchmarks<T, std::memory_order_seq_cst>(benches, config, buf);
+
+    load_benchmarks<T, std::memory_order_relaxed>(benches, config, buf);
+    load_benchmarks<T, std::memory_order_acquire>(benches, config, buf);
+    load_benchmarks<T, std::memory_order_seq_cst>(benches, config, buf);
+
+    store_benchmarks<T, std::memory_order_relaxed>(benches, config, buf);
+    store_benchmarks<T, std::memory_order_release>(benches, config, buf);
+    store_benchmarks<T, std::memory_order_seq_cst>(benches, config, buf);
+
+    cmp_xchg_benchmarks<T, std::memory_order_relaxed,
+                        std::memory_order_relaxed>(benches, config, buf);
+
+    cmp_xchg_benchmarks<T, std::memory_order_acquire,
+                        std::memory_order_relaxed>(benches, config, buf);
+    cmp_xchg_benchmarks<T, std::memory_order_acquire,
+                        std::memory_order_acquire>(benches, config, buf);
+
+    cmp_xchg_benchmarks<T, std::memory_order_release,
+                        std::memory_order_relaxed>(benches, config, buf);
+
+    cmp_xchg_benchmarks<T, std::memory_order_acq_rel,
+                        std::memory_order_relaxed>(benches, config, buf);
+    cmp_xchg_benchmarks<T, std::memory_order_acq_rel,
+                        std::memory_order_acquire>(benches, config, buf);
+
+    cmp_xchg_benchmarks<T, std::memory_order_seq_cst,
+                        std::memory_order_relaxed>(benches, config, buf);
+    cmp_xchg_benchmarks<T, std::memory_order_seq_cst,
+                        std::memory_order_acquire>(benches, config, buf);
+    cmp_xchg_benchmarks<T, std::memory_order_seq_cst,
+                        std::memory_order_seq_cst>(benches, config, buf);
+}
+
+#define C11_ATOMICS_TYPES                                                     \
+    C11_ATOMICS_TYPE(std::uint8_t)                                            \
+    C11_ATOMICS_TYPE(std::uint16_t)                                           \
+    C11_ATOMICS_TYPE(std::uint32_t)                                           \
+    C11_ATOMICS_TYPE(std::uint64_t)                                           \
+    C11_ATOMICS_TYPE(std::int8_t)                                             \
+    C11_ATOMICS_TYPE(std::int16_t)                                            \
+    C11_ATOMICS_TYPE(std::int32_t)                                            \
+    C11_ATOMICS_TYPE(std::int64_t)                                            \
+    //
+
+#define C11_ATOMICS_TYPE(T)                                                   \
+    extern template void benchmarks<T>(std::vector<Benchmark> & benches,      \
+                                       const Config &config);
+
+C11_ATOMICS_TYPES
+
+#undef C11_ATOMICS_TYPE
+
+} // namespace c11_atomics
\ No newline at end of file
diff --git a/src/common/c11_atomics/u16.cpp b/src/common/c11_atomics/u16.cpp
new file mode 100644 (file)
index 0000000..f2b4f2f
--- /dev/null
@@ -0,0 +1,4 @@
+#include "internals.h"
+
+template void c11_atomics::benchmarks<std::uint16_t>(
+    std::vector<Benchmark> &benches, const Config &config);
diff --git a/src/common/c11_atomics/u32.cpp b/src/common/c11_atomics/u32.cpp
new file mode 100644 (file)
index 0000000..3f4dca2
--- /dev/null
@@ -0,0 +1,4 @@
+#include "internals.h"
+
+template void c11_atomics::benchmarks<std::uint32_t>(
+    std::vector<Benchmark> &benches, const Config &config);
diff --git a/src/common/c11_atomics/u64.cpp b/src/common/c11_atomics/u64.cpp
new file mode 100644 (file)
index 0000000..7596bc5
--- /dev/null
@@ -0,0 +1,4 @@
+#include "internals.h"
+
+template void c11_atomics::benchmarks<std::uint64_t>(
+    std::vector<Benchmark> &benches, const Config &config);
diff --git a/src/common/c11_atomics/u8.cpp b/src/common/c11_atomics/u8.cpp
new file mode 100644 (file)
index 0000000..1553065
--- /dev/null
@@ -0,0 +1,4 @@
+#include "internals.h"
+
+template void c11_atomics::benchmarks<std::uint8_t>(
+    std::vector<Benchmark> &benches, const Config &config);