Skip to content

[libc++] Add benchmarks for partitioning algorithms #127324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 24, 2025

Conversation

ldionne
Copy link
Member

@ldionne ldionne commented Feb 15, 2025

This patch adds benchmarks for std::partition, is_partitioned, etc and their ranges:: variants.

@ldionne ldionne requested a review from a team as a code owner February 15, 2025 13:55
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Feb 15, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 15, 2025

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

Changes

This patch adds benchmarks for std::partition, is_partitioned, etc and their ranges:: variants.


Patch is 20.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/127324.diff

6 Files Affected:

  • (removed) libcxx/test/benchmarks/algorithms/algorithms.partition_point.bench.cpp (-131)
  • (added) libcxx/test/benchmarks/algorithms/partitions/is_partitioned.bench.cpp (+94)
  • (added) libcxx/test/benchmarks/algorithms/partitions/partition.bench.cpp (+77)
  • (added) libcxx/test/benchmarks/algorithms/partitions/partition_copy.bench.cpp (+74)
  • (added) libcxx/test/benchmarks/algorithms/partitions/partition_point.bench.cpp (+73)
  • (added) libcxx/test/benchmarks/algorithms/partitions/stable_partition.bench.cpp (+79)
diff --git a/libcxx/test/benchmarks/algorithms/algorithms.partition_point.bench.cpp b/libcxx/test/benchmarks/algorithms/algorithms.partition_point.bench.cpp
deleted file mode 100644
index e0bd7e36f78ad..0000000000000
--- a/libcxx/test/benchmarks/algorithms/algorithms.partition_point.bench.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-#include <algorithm>
-#include <array>
-#include <cassert>
-#include <cstdint>
-#include <tuple>
-#include <vector>
-
-#include "benchmark/benchmark.h"
-
-#include "../CartesianBenchmarks.h"
-#include "../GenerateInput.h"
-
-namespace {
-
-template <typename I, typename N>
-std::array<I, 10> every_10th_percentile_N(I first, N n) {
-  N step = n / 10;
-  std::array<I, 10> res;
-
-  for (size_t i = 0; i < 10; ++i) {
-    res[i] = first;
-    std::advance(first, step);
-  }
-
-  return res;
-}
-
-template <class IntT>
-struct TestIntBase {
-  static std::vector<IntT> generateInput(size_t size) {
-    std::vector<IntT> Res(size);
-    std::generate(Res.begin(), Res.end(), [] { return getRandomInteger<IntT>(0, std::numeric_limits<IntT>::max()); });
-    return Res;
-  }
-};
-
-struct TestInt32 : TestIntBase<std::int32_t> {
-  static constexpr const char* Name = "TestInt32";
-};
-
-struct TestInt64 : TestIntBase<std::int64_t> {
-  static constexpr const char* Name = "TestInt64";
-};
-
-struct TestUint32 : TestIntBase<std::uint32_t> {
-  static constexpr const char* Name = "TestUint32";
-};
-
-struct TestMediumString {
-  static constexpr const char* Name  = "TestMediumString";
-  static constexpr size_t StringSize = 32;
-
-  static std::vector<std::string> generateInput(size_t size) {
-    std::vector<std::string> Res(size);
-    std::generate(Res.begin(), Res.end(), [] { return getRandomString(StringSize); });
-    return Res;
-  }
-};
-
-using AllTestTypes = std::tuple<TestInt32, TestInt64, TestUint32, TestMediumString>;
-
-struct LowerBoundAlg {
-  template <class I, class V>
-  I operator()(I first, I last, const V& value) const {
-    return std::lower_bound(first, last, value);
-  }
-
-  static constexpr const char* Name = "LowerBoundAlg";
-};
-
-struct UpperBoundAlg {
-  template <class I, class V>
-  I operator()(I first, I last, const V& value) const {
-    return std::upper_bound(first, last, value);
-  }
-
-  static constexpr const char* Name = "UpperBoundAlg";
-};
-
-struct EqualRangeAlg {
-  template <class I, class V>
-  std::pair<I, I> operator()(I first, I last, const V& value) const {
-    return std::equal_range(first, last, value);
-  }
-
-  static constexpr const char* Name = "EqualRangeAlg";
-};
-
-using AllAlgs = std::tuple<LowerBoundAlg, UpperBoundAlg, EqualRangeAlg>;
-
-template <class Alg, class TestType>
-struct PartitionPointBench {
-  size_t Quantity;
-
-  std::string name() const {
-    return std::string("PartitionPointBench_") + Alg::Name + "_" + TestType::Name + '/' + std::to_string(Quantity);
-  }
-
-  void run(benchmark::State& state) const {
-    auto Data = TestType::generateInput(Quantity);
-    std::sort(Data.begin(), Data.end());
-    auto Every10Percentile = every_10th_percentile_N(Data.begin(), Data.size());
-
-    for (auto _ : state) {
-      for (auto Test : Every10Percentile)
-        benchmark::DoNotOptimize(Alg{}(Data.begin(), Data.end(), *Test));
-    }
-  }
-};
-
-} // namespace
-
-int main(int argc, char** argv) {
-  benchmark::Initialize(&argc, argv);
-  if (benchmark::ReportUnrecognizedArguments(argc, argv))
-    return 1;
-
-  const std::vector<size_t> Quantities = {1 << 8, 1 << 10, 1 << 20};
-  makeCartesianProductBenchmark<PartitionPointBench, AllAlgs, AllTestTypes>(Quantities);
-  benchmark::RunSpecifiedBenchmarks();
-}
diff --git a/libcxx/test/benchmarks/algorithms/partitions/is_partitioned.bench.cpp b/libcxx/test/benchmarks/algorithms/partitions/is_partitioned.bench.cpp
new file mode 100644
index 0000000000000..55f8f7dcb990a
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/partitions/is_partitioned.bench.cpp
@@ -0,0 +1,94 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cassert>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+auto compute_median(auto first, auto last) {
+  std::vector v(first, last);
+  auto middle = v.begin() + v.size() / 2;
+  std::nth_element(v.begin(), middle, v.end());
+  return *middle;
+}
+
+template <class Container, bool Partitioned, class Operation>
+void bm(std::string operation_name, Operation is_partitioned) {
+  auto bench = [is_partitioned](auto& st) {
+    auto const size = st.range(0);
+    using ValueType = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    // Partition the container in two equally-sized halves, ensuring the median
+    // value appears in the left half. Note that the median value isn't located
+    // in the middle -- this isn't std::nth_element.
+    ValueType median = compute_median(c.begin(), c.end());
+    auto pred        = [median](auto const& element) { return element <= median; };
+    std::partition(c.begin(), c.end(), pred);
+    assert(std::is_partitioned(c.begin(), c.end(), pred));
+
+    if constexpr (!Partitioned) {
+      // De-partition the container by swapping the element containing the median
+      // value with the last one.
+      auto median_it = std::find(c.begin(), c.end(), median);
+      auto last_it   = std::next(c.begin(), c.size() - 1);
+      std::iter_swap(median_it, last_it);
+      assert(!std::is_partitioned(c.begin(), c.end(), pred));
+    }
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = is_partitioned(c.begin(), c.end(), pred);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_is_partitioned    = [](auto first, auto last, auto pred) { return std::is_partitioned(first, last, pred); };
+  auto ranges_is_partitioned = [](auto first, auto last, auto pred) {
+    return std::ranges::is_partitioned(first, last, pred);
+  };
+
+  // std::is_partitioned
+  bm<std::vector<int>, true>("std::is_partitioned(vector<int>) (partitioned)", std_is_partitioned);
+  bm<std::vector<int>, false>("std::is_partitioned(vector<int>) (not partitioned)", std_is_partitioned);
+
+  bm<std::deque<int>, true>("std::is_partitioned(deque<int>) (partitioned)", std_is_partitioned);
+  bm<std::deque<int>, false>("std::is_partitioned(deque<int>) (not partitioned)", std_is_partitioned);
+
+  bm<std::list<int>, true>("std::is_partitioned(list<int>) (partitioned)", std_is_partitioned);
+  bm<std::list<int>, false>("std::is_partitioned(list<int>) (not partitioned)", std_is_partitioned);
+
+  // ranges::is_partitioned
+  bm<std::vector<int>, true>("ranges::is_partitioned(vector<int>) (partitioned)", ranges_is_partitioned);
+  bm<std::vector<int>, false>("ranges::is_partitioned(vector<int>) (not partitioned)", ranges_is_partitioned);
+
+  bm<std::deque<int>, true>("ranges::is_partitioned(deque<int>) (partitioned)", ranges_is_partitioned);
+  bm<std::deque<int>, false>("ranges::is_partitioned(deque<int>) (not partitioned)", ranges_is_partitioned);
+
+  bm<std::list<int>, true>("ranges::is_partitioned(list<int>) (partitioned)", ranges_is_partitioned);
+  bm<std::list<int>, false>("ranges::is_partitioned(list<int>) (not partitioned)", ranges_is_partitioned);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/partitions/partition.bench.cpp b/libcxx/test/benchmarks/algorithms/partitions/partition.bench.cpp
new file mode 100644
index 0000000000000..4e2cd3170fc6b
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/partitions/partition.bench.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+auto compute_median(auto first, auto last) {
+  std::vector v(first, last);
+  auto middle = v.begin() + v.size() / 2;
+  std::nth_element(v.begin(), middle, v.end());
+  return *middle;
+}
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation partition) {
+  auto bench = [partition](auto& st) {
+    auto const size = st.range(0);
+    using ValueType = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    std::vector<ValueType> yes(size), no(size);
+    ValueType median = compute_median(c.begin(), c.end());
+    auto pred1       = [median](auto const& element) { return element < median; };
+    auto pred2       = [median](auto const& element) { return element > median; };
+    bool toggle      = false;
+
+    for ([[maybe_unused]] auto _ : st) {
+      if (toggle) {
+        auto result = partition(c.begin(), c.end(), pred1);
+        benchmark::DoNotOptimize(result);
+      } else {
+        auto result = partition(c.begin(), c.end(), pred2);
+        benchmark::DoNotOptimize(result);
+      }
+      toggle = !toggle;
+
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_partition    = [](auto first, auto last, auto pred) { return std::partition(first, last, pred); };
+  auto ranges_partition = [](auto first, auto last, auto pred) { return std::ranges::partition(first, last, pred); };
+
+  // std::partition
+  bm<std::vector<int>>("std::partition(vector<int>)", std_partition);
+  bm<std::deque<int>>("std::partition(deque<int>)", std_partition);
+  bm<std::list<int>>("std::partition(list<int>)", std_partition);
+
+  // ranges::partition
+  bm<std::vector<int>>("ranges::partition(vector<int>)", ranges_partition);
+  bm<std::deque<int>>("ranges::partition(deque<int>)", ranges_partition);
+  bm<std::list<int>>("ranges::partition(list<int>)", ranges_partition);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/partitions/partition_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/partitions/partition_copy.bench.cpp
new file mode 100644
index 0000000000000..68f3fa027169e
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/partitions/partition_copy.bench.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+auto compute_median(auto first, auto last) {
+  std::vector v(first, last);
+  auto middle = v.begin() + v.size() / 2;
+  std::nth_element(v.begin(), middle, v.end());
+  return *middle;
+}
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation partition_copy) {
+  auto bench = [partition_copy](auto& st) {
+    auto const size = st.range(0);
+    using ValueType = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    std::vector<ValueType> yes(size), no(size);
+    ValueType median = compute_median(c.begin(), c.end());
+    auto pred        = [median](auto const& element) { return element < median; };
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = partition_copy(c.begin(), c.end(), yes.begin(), no.begin(), pred);
+      benchmark::DoNotOptimize(yes);
+      benchmark::DoNotOptimize(no);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_partition_copy = [](auto first, auto last, auto out_yes, auto out_no, auto pred) {
+    return std::partition_copy(first, last, out_yes, out_no, pred);
+  };
+  auto ranges_partition_copy = [](auto first, auto last, auto out_yes, auto out_no, auto pred) {
+    return std::ranges::partition_copy(first, last, out_yes, out_no, pred);
+  };
+
+  // std::partition_copy
+  bm<std::vector<int>>("std::partition_copy(vector<int>)", std_partition_copy);
+  bm<std::deque<int>>("std::partition_copy(deque<int>)", std_partition_copy);
+  bm<std::list<int>>("std::partition_copy(list<int>)", std_partition_copy);
+
+  // ranges::partition_copy
+  bm<std::vector<int>>("ranges::partition_copy(vector<int>)", ranges_partition_copy);
+  bm<std::deque<int>>("ranges::partition_copy(deque<int>)", ranges_partition_copy);
+  bm<std::list<int>>("ranges::partition_copy(list<int>)", ranges_partition_copy);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/partitions/partition_point.bench.cpp b/libcxx/test/benchmarks/algorithms/partitions/partition_point.bench.cpp
new file mode 100644
index 0000000000000..da810a59bff5b
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/partitions/partition_point.bench.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+auto compute_median(auto first, auto last) {
+  std::vector v(first, last);
+  auto middle = v.begin() + v.size() / 2;
+  std::nth_element(v.begin(), middle, v.end());
+  return *middle;
+}
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation partition_point) {
+  auto bench = [partition_point](auto& st) {
+    auto const size = st.range(0);
+    using ValueType = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    // Partition the container in two equally-sized halves. Based on experimentation, the running
+    // time of the algorithm doesn't change much depending on the size of the halves.
+    ValueType median = compute_median(c.begin(), c.end());
+    auto pred        = [median](auto const& element) { return element < median; };
+    std::partition(c.begin(), c.end(), pred);
+    assert(std::is_partitioned(c.begin(), c.end(), pred));
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = partition_point(c.begin(), c.end(), pred);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_partition_point = [](auto first, auto last, auto pred) { return std::partition_point(first, last, pred); };
+  auto ranges_partition_point = [](auto first, auto last, auto pred) {
+    return std::ranges::partition_point(first, last, pred);
+  };
+
+  // std::partition_point
+  bm<std::vector<int>>("std::partition_point(vector<int>)", std_partition_point);
+  bm<std::deque<int>>("std::partition_point(deque<int>)", std_partition_point);
+  bm<std::list<int>>("std::partition_point(list<int>)", std_partition_point);
+
+  // ranges::partition_point
+  bm<std::vector<int>>("ranges::partition_point(vector<int>)", ranges_partition_point);
+  bm<std::deque<int>>("ranges::partition_point(deque<int>)", ranges_partition_point);
+  bm<std::list<int>>("ranges::partition_point(list<int>)", ranges_partition_point);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/partitions/stable_partition.bench.cpp b/libcxx/test/benchmarks/algorithms/partitions/stable_partition.bench.cpp
new file mode 100644
index 0000000000000..60e723a3a29d8
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/partitions/stable_partition.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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+auto compute_median(auto first, auto last) {
+  std::vector v(first, last);
+  auto middle = v.begin() + v.size() / 2;
+  std::nth_element(v.begin(), middle, v.end());
+  return *middle;
+}
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation stable_partition) {
+  auto bench = [stable_partition](auto& st) {
+    auto const size = st.range(0);
+    using ValueType = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    std::vector<ValueType> yes(size), no(size);
+    ValueType median = compute_median(c.begin(), c.end());
+    auto pred1       = [median](auto const& element) { return element < median; };
+    auto pred2       = [median](auto const& element) { return element > median; };
+    bool toggle      = false;
+
+    for ([[maybe_unused]] auto _ : st) {
+      if (toggle) {
+        auto result = stable_partition(c.begin(), c.end(), pred1);
+        benchmark::DoNotOptimize(result);
+      } else {
+        auto result = stable_partition(c.begin(), c.end(), pred2);
+        benchmark::DoNotOptimize(result);
+      }
+      toggle = !toggle;
+
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_stable_partition = [](auto first, auto last, auto pr...
[truncated]

ldionne added 4 commits March 20, 2025 14:27
This patch adds benchmarks for std::partition, is_partitioned, etc
and their ranges:: variants.
@ldionne ldionne force-pushed the review/benchmark-add-partitioning branch from 1770cf0 to 32baaa9 Compare March 20, 2025 18:29
@ldionne
Copy link
Member Author

ldionne commented Mar 20, 2025

I'll merge this once CI is finished since @philnik777 and I have went over it pretty extensively, but I will make another pass with him when he's back from vacation for due diligence.

@ldionne ldionne added the pending-ci Merging the PR is only pending completion of CI label Mar 20, 2025
@ldionne ldionne merged commit 4107544 into llvm:main Mar 24, 2025
83 of 86 checks passed
@ldionne ldionne deleted the review/benchmark-add-partitioning branch March 24, 2025 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. pending-ci Merging the PR is only pending completion of CI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants