blob: a9625496d7b7c5fcb172ef7f000dc354ed9af27d [file]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
// GEMM on the thread pool over the pool size. On a machine whose GEMM kernel
// runs on shared units (the ARM SME backend: one unit per cluster), the rate
// levels off at the unit count and falls beyond it unless the thread count is
// capped; the "uncapped" variant removes the cap (setNbSmeUnits(0)) for the
// comparison and is a no-op on other backends.
#define EIGEN_GEMM_THREADPOOL
#include <benchmark/benchmark.h>
#include <Eigen/Core>
#include <Eigen/ThreadPool>
#include <initializer_list>
#include <thread>
using namespace Eigen;
#ifndef SCALAR
#define SCALAR float
#endif
using Scalar = SCALAR;
using Mat = Matrix<Scalar, Dynamic, Dynamic>;
template <typename A, typename B, typename C>
EIGEN_DONT_INLINE void gemm(const A& a, const B& b, C& c) {
c.noalias() += a * b;
}
template <bool Uncapped>
static void BM_GemmThreads(benchmark::State& state) {
const int n = static_cast<int>(state.range(0));
const int threads = static_cast<int>(state.range(1));
ThreadPool pool(threads);
setGemmThreadPool(&pool);
const int units = nbSmeUnits();
if (Uncapped) setNbSmeUnits(0);
Mat a = Mat::Random(n, n), b = Mat::Random(n, n), c = Mat::Zero(n, n);
for (auto _ : state) {
gemm(a, b, c);
benchmark::DoNotOptimize(c.data());
benchmark::ClobberMemory();
}
state.counters["GFLOPS"] =
benchmark::Counter(2.0 * n * n * n, benchmark::Counter::kIsIterationInvariantRate, benchmark::Counter::kIs1000);
setNbSmeUnits(units);
}
// Pool sizes up to the core count (a larger pool only oversubscribes), keeping the smallest of each list.
static void ThreadArgs(::benchmark::Benchmark* b, std::initializer_list<int> threads) {
const int cores = static_cast<int>(std::thread::hardware_concurrency());
for (int n : {1024, 2048})
for (int t : threads)
if (t <= cores || t == *threads.begin()) b->Args({n, t});
}
BENCHMARK(BM_GemmThreads<false>)
->Name("BM_GemmThreads")
->Apply([](::benchmark::Benchmark* b) {
ThreadArgs(b, {1, 2, 4, 8, 12});
})
->UseRealTime();
BENCHMARK(BM_GemmThreads<true>)
->Name("BM_GemmThreads_uncapped")
->Apply([](::benchmark::Benchmark* b) {
ThreadArgs(b, {4, 8, 12});
})
->UseRealTime();