// Benchmarks for symmetric rank-1 update (SYR). // // Tests C.selfadjointView().rankUpdate(v, alpha) which computes // C += alpha * v * v^T, updating only the lower (or upper) triangle. // Exercises SelfadjointProduct.h / selfadjoint_rank1_update. #include #include using namespace Eigen; template double syrFlops(Index n) { // SYR: n*(n+1)/2 multiply-adds ~ n^2 return (NumTraits::IsComplex ? 8.0 : 2.0) * n * (n + 1) / 2; } template static void BM_SYR_Lower(benchmark::State& state) { const Index n = state.range(0); using Mat = Matrix; using Vec = Matrix; Vec v = Vec::Random(n); Mat C = Mat::Zero(n, n); Scalar alpha(1); for (auto _ : state) { C.template selfadjointView().rankUpdate(v, alpha); benchmark::DoNotOptimize(C.data()); benchmark::ClobberMemory(); } state.counters["GFLOPS"] = benchmark::Counter(syrFlops(n), benchmark::Counter::kIsIterationInvariantRate, benchmark::Counter::kIs1000); } template static void BM_SYR_Upper(benchmark::State& state) { const Index n = state.range(0); using Mat = Matrix; using Vec = Matrix; Vec v = Vec::Random(n); Mat C = Mat::Zero(n, n); Scalar alpha(1); for (auto _ : state) { C.template selfadjointView().rankUpdate(v, alpha); benchmark::DoNotOptimize(C.data()); benchmark::ClobberMemory(); } state.counters["GFLOPS"] = benchmark::Counter(syrFlops(n), benchmark::Counter::kIsIterationInvariantRate, benchmark::Counter::kIs1000); } // clang-format off BENCHMARK(BM_SYR_Lower)->Arg(8)->Arg(16)->Arg(32)->Arg(64)->Arg(128)->Arg(256)->Arg(512)->Arg(1024)->Arg(2048)->Name("SYR_Lower_float"); BENCHMARK(BM_SYR_Lower)->Arg(8)->Arg(16)->Arg(32)->Arg(64)->Arg(128)->Arg(256)->Arg(512)->Arg(1024)->Arg(2048)->Name("SYR_Lower_double"); BENCHMARK(BM_SYR_Upper)->Arg(8)->Arg(16)->Arg(32)->Arg(64)->Arg(128)->Arg(256)->Arg(512)->Arg(1024)->Arg(2048)->Name("SYR_Upper_float"); BENCHMARK(BM_SYR_Upper)->Arg(8)->Arg(16)->Arg(32)->Arg(64)->Arg(128)->Arg(256)->Arg(512)->Arg(1024)->Arg(2048)->Name("SYR_Upper_double"); // clang-format on