[libcxx-commits] [libcxx] 0ead65c - [libc++][pstl] Add more benchmarks of the parallel algorithms (#225908)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Sep 26 10:52:40 PDT 2026


Author: Michael G. Kazakov
Date: 2026-09-26T18:52:34+01:00
New Revision: 0ead65c731fa09596fbcc9b5109e504e9e7adb7e

URL: https://github.com/llvm/llvm-project/commit/0ead65c731fa09596fbcc9b5109e504e9e7adb7e
DIFF: https://github.com/llvm/llvm-project/commit/0ead65c731fa09596fbcc9b5109e504e9e7adb7e.diff

LOG: [libc++][pstl] Add more benchmarks of the parallel algorithms (#225908)

This PR adds benchmarks of these 3 parallel algorithms:
- `std::find(policy, ...)`
- `std::sort(policy, ...)`
- `std::transform_reduce(policy, ...)`

---------

Co-authored-by: Louis Dionne <ldionne.2 at gmail.com>

Added: 
    libcxx/test/benchmarks/algorithms/nonmodifying/pstl.find.bench.cpp
    libcxx/test/benchmarks/algorithms/sorting/pstl.sort.bench.cpp
    libcxx/test/benchmarks/numeric/pstl.transform_reduce.bench.cpp

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/libcxx/test/benchmarks/algorithms/nonmodifying/pstl.find.bench.cpp b/libcxx/test/benchmarks/algorithms/nonmodifying/pstl.find.bench.cpp
new file mode 100644
index 0000000000000..98642ad7aa87e
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/nonmodifying/pstl.find.bench.cpp
@@ -0,0 +1,62 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <string>
+#include <vector>
+#include <execution>
+#include <utility>
+
+#include <benchmark/benchmark.h>
+#include "../../GenerateInput.h"
+
+int main(int argc, char** argv) {
+  auto bm = [](std::string name, auto&& policy, bool has_needle) {
+    benchmark::RegisterBenchmark(
+        name,
+        [&policy, has_needle](auto& st) mutable {
+          std::size_t size = st.range(0);
+          double x         = Generate<double>::random();
+          double y         = random_
diff erent_from({x});
+          std::vector<double> c(size, x);
+
+          if (has_needle) {
+            // put the element we're searching for at 25% of the sequence
+            *std::next(c.begin(), size / 4) = y;
+          }
+
+          for ([[maybe_unused]] auto _ : st) {
+            benchmark::DoNotOptimize(c);
+            benchmark::DoNotOptimize(y);
+            auto result = std::find(policy, c.begin(), c.end(), y);
+            benchmark::DoNotOptimize(result);
+          }
+        })
+        ->Arg(1 << 6)  // 64
+        ->Arg(1 << 16) // 65'536
+        ->Arg(1 << 26) // 67'108'864
+        ->UseRealTime();
+  };
+#if defined(TEST_PSTL_ENABLE_SEQ_BASELINES)
+  bm("std::find(std::execution::seq, vector<double>) (bail 25%)", std::execution::seq, true);
+  bm("std::find(std::execution::seq, vector<double>) (process all)", std::execution::seq, false);
+#endif
+  bm("std::find(std::execution::par, vector<double>) (bail 25%)", std::execution::par, true);
+  bm("std::find(std::execution::par, vector<double>) (process all)", std::execution::par, false);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}

diff  --git a/libcxx/test/benchmarks/algorithms/sorting/pstl.sort.bench.cpp b/libcxx/test/benchmarks/algorithms/sorting/pstl.sort.bench.cpp
new file mode 100644
index 0000000000000..e080deb5fa722
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/sorting/pstl.sort.bench.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+#include <algorithm>
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <string>
+#include <vector>
+#include <execution>
+#include <utility>
+
+#include <benchmark/benchmark.h>
+
+#include "common.h"
+#include "test_macros.h"
+
+int main(int argc, char** argv) {
+  auto bm = [](std::string name, auto&& policy, auto generate_data) {
+    benchmark::RegisterBenchmark(
+        name,
+        [&policy, generate_data](auto& st) mutable {
+          constexpr std::size_t BatchSize = 32;
+          std::size_t size                = st.range(0);
+          std::vector<int> data           = generate_data(size);
+          std::array<std::vector<int>, BatchSize> c;
+          std::fill_n(c.begin(), BatchSize, data);
+
+          while (st.KeepRunningBatch(BatchSize)) {
+            for (std::size_t i = 0; i != BatchSize; ++i) {
+              benchmark::DoNotOptimize(c[i]);
+              std::sort(policy, c[i].begin(), c[i].end());
+              benchmark::DoNotOptimize(c[i]);
+            }
+
+            // Reset c to its original unsorted state
+            st.PauseTiming();
+            for (std::size_t i = 0; i != BatchSize; ++i) {
+              std::copy(data.begin(), data.end(), c[i].begin());
+            }
+            st.ResumeTiming();
+          }
+        })
+        ->Arg(1 << 6)  // 64
+        ->Arg(1 << 16) // 65'536
+        ->Arg(1 << 26) // 67'108'864
+        ->UseRealTime();
+  };
+
+  auto register_bm = [&](auto generate, std::string variant) {
+    auto name = [variant](std::string op) { return op + " (" + variant + ")"; };
+#if defined(TEST_PSTL_ENABLE_SEQ_BASELINES)
+    bm.operator()(name("std::sort(std::execution::seq, vector<int>)"), std::execution::seq, generate);
+#endif
+    bm.operator()(name("std::sort(std::execution::par, vector<int>)"), std::execution::par, generate);
+  };
+
+  register_bm(support::quicksort_adversarial_data<int>, "qsort adversarial");
+  register_bm(support::ascending_sorted_data<int>, "ascending");
+  register_bm(support::descending_sorted_data<int>, "descending");
+  register_bm(support::pipe_organ_data<int>, "pipe-organ");
+  register_bm(support::heap_data<int>, "heap");
+  register_bm(support::shuffled_data<int>, "shuffled");
+  register_bm(support::single_element_data<int>, "repeated");
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}

diff  --git a/libcxx/test/benchmarks/numeric/pstl.transform_reduce.bench.cpp b/libcxx/test/benchmarks/numeric/pstl.transform_reduce.bench.cpp
new file mode 100644
index 0000000000000..9ae2ad3cc0860
--- /dev/null
+++ b/libcxx/test/benchmarks/numeric/pstl.transform_reduce.bench.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cmath>
+#include <numeric>
+#include <string>
+#include <type_traits>
+#include <vector>
+#include <execution>
+#include <utility>
+
+#include <benchmark/benchmark.h>
+
+int main(int argc, char** argv) {
+  // A transformation/reduction that does just a bit more than a no-op
+  struct minimal {
+    double operator()(double x) const { return -x; }
+    double operator()(double x, double y) const { return x + y; }
+  };
+
+  // A transformation/reduction that does miniscule work per element
+  struct cheap {
+    double operator()(double x) const { return -x + 0.25; }
+    double operator()(double x, double y) const {
+      // (compilers aren't allowed to optimize away the FP divisions and multiplications without fast-math)
+      return x / 2. * 2. / 2. * 2. + y / 2. * 2. / 2. * 2.;
+    }
+  };
+
+  // A transformation/reduction that does significant work per element
+  struct expensive {
+    double operator()(double x) const { return (-x + 0.25) * (x + 10.); }
+    double operator()(double x, double y) const {
+      // (compilers aren't allowed to optimize away the FP divisions and multiplications without fast-math)
+      return x / 2. * 2. / 3. * 3. / 4. * 4. / 5. * 5. + y / 2. * 2. / 2. * 2. / 4. * 4. / 5. * 5.;
+    }
+  };
+
+  auto bm = [](std::string name, auto&& policy, auto func) {
+    benchmark::RegisterBenchmark(
+        name,
+        [&policy, func](auto& st) {
+          std::size_t size = st.range(0);
+          std::vector<double> c(size);
+          std::iota(c.begin(), c.end(), 1.);
+          for ([[maybe_unused]] auto _ : st) {
+            benchmark::ClobberMemory();
+            auto result = std::transform_reduce(policy, c.begin(), c.end(), 0.0, func, func);
+            benchmark::DoNotOptimize(result);
+          }
+        })
+        ->Arg(1 << 6)  // 64
+        ->Arg(1 << 16) // 65'536
+        ->Arg(1 << 26) // 67'108'864
+        ->UseRealTime();
+  };
+#if defined(TEST_PSTL_ENABLE_SEQ_BASELINES)
+  bm("std::transform_reduce(std::execution::seq, vector<double>) (minimal)", std::execution::seq, minimal{});
+  bm("std::transform_reduce(std::execution::seq, vector<double>) (cheap)", std::execution::seq, cheap{});
+  bm("std::transform_reduce(std::execution::seq, vector<double>) (expensive)", std::execution::seq, expensive{});
+#endif
+  bm("std::transform_reduce(std::execution::par, vector<double>) (minimal)", std::execution::par, minimal{});
+  bm("std::transform_reduce(std::execution::par, vector<double>) (cheap)", std::execution::par, cheap{});
+  bm("std::transform_reduce(std::execution::par, vector<double>) (expensive)", std::execution::par, expensive{});
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}


        


More information about the libcxx-commits mailing list