From ef502add2b09d7115ce69944f1dcea57f81abaad Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Fri, 4 Sep 2026 08:12:39 +0000 Subject: [PATCH] Add codegen backends to RooFit backend fit benchmarks Benchmark the automatic-differentiation "codegen" evaluation backend and its "codegen_no_grad" variant (numeric gradient) alongside the existing Legacy, CPU, and CUDA configurations. The GausXS model gets no codegen variants because its normalization requires a multi-dimensional numeric integral that the codegen backend does not support. The BDecay benchmarks in RooFitUnBinnedBenchmarks.cxx are also left unchanged, since RooBMixDecay, RooGaussModel, and RooAddModel have no codegen translate functions yet. This supersedes the corresponding part of PR #282. --- root/roofit/roofit/benchRooFitBackends.cxx | 27 +++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/root/roofit/roofit/benchRooFitBackends.cxx b/root/roofit/roofit/benchRooFitBackends.cxx index d205e84b..887d788a 100644 --- a/root/roofit/roofit/benchRooFitBackends.cxx +++ b/root/roofit/roofit/benchRooFitBackends.cxx @@ -25,7 +25,7 @@ int printLevel = 0; size_t nEvents = 10000; const auto minimizerName = "Minuit2"; -enum RunConfig_t { runScalar, runCpu, fitScalar, fitCpu, fitCuda }; +enum RunConfig_t { runScalar, runCpu, fitScalar, fitCpu, fitCuda, fitCodegen, fitCodegenNoGrad }; void runFitBenchmark(benchmark::State &state, RooAbsPdf &pdf, RooAbsData &data) { @@ -44,6 +44,12 @@ void runFitBenchmark(benchmark::State &state, RooAbsPdf &pdf, RooAbsData &data) pdf.fitTo(data, EvalBackend::Cpu(), Minimizer(minimizerName), PrintLevel(printLevel - 1), PrintEvalErrors(-1)); } else if (runConfig == fitCuda) { pdf.fitTo(data, EvalBackend::Cuda(), Minimizer(minimizerName), PrintLevel(printLevel - 1), PrintEvalErrors(-1)); + } else if (runConfig == fitCodegen) { + pdf.fitTo(data, EvalBackend::Codegen(), Minimizer(minimizerName), PrintLevel(printLevel - 1), + PrintEvalErrors(-1)); + } else if (runConfig == fitCodegenNoGrad) { + pdf.fitTo(data, EvalBackend::CodegenNoGrad(), Minimizer(minimizerName), PrintLevel(printLevel - 1), + PrintEvalErrors(-1)); } state.PauseTiming(); params.assign(paramsInitial); @@ -322,18 +328,31 @@ auto const unit = benchmark::kMillisecond; BENCHMARK(benchFitGauss)->Unit(unit)->Name("Gaus_FitLegacy")->Args({fitScalar}); BENCHMARK(benchFitGauss)->Unit(unit)->Name("Gaus_FitCPU")->Args({fitCpu}); +BENCHMARK(benchFitGauss)->Unit(unit)->Name("Gaus_FitCodegen")->Args({fitCodegen}); +BENCHMARK(benchFitGauss)->Unit(unit)->Name("Gaus_FitCodegenNoGrad")->Args({fitCodegenNoGrad}); CUDA_ONLY(BENCHMARK(benchFitGauss)->Unit(unit)->Name("Gaus_FitCUDA")->Args({fitCuda})); +// No codegen variants for this model: normalizing the Gaussian over both x +// and sigma requires a multi-dimensional numeric integral, which the codegen +// backend doesn't support. BENCHMARK(benchFitGaussXSigma)->Unit(unit)->Name("GausXS_FitLegacy")->Args({fitScalar}); BENCHMARK(benchFitGaussXSigma)->Unit(unit)->Name("GausXS_FitCPU")->Args({fitCpu}); CUDA_ONLY(BENCHMARK(benchFitGaussXSigma)->Unit(unit)->Name("GausXS_FitCUDA")->Args({fitCuda})); BENCHMARK(benchFit)->Unit(unit)->Name("AddPdf_FitLegacy")->Args({fitScalar}); BENCHMARK(benchFit)->Unit(unit)->Name("AddPdf_FitCPU")->Args({fitCpu}); +BENCHMARK(benchFit)->Unit(unit)->Name("AddPdf_FitCodegen")->Args({fitCodegen}); +BENCHMARK(benchFit)->Unit(unit)->Name("AddPdf_FitCodegenNoGrad")->Args({fitCodegenNoGrad}); CUDA_ONLY(BENCHMARK(benchFit)->Unit(unit)->Name("AddPdf_FitCUDA")->Args({fitCuda})); BENCHMARK(benchProdPdf)->Unit(unit)->Name("ProdPdf_FitLegacy")->Unit(benchmark::kMillisecond)->Args({fitScalar}); BENCHMARK(benchProdPdf)->Unit(unit)->Name("ProdPdf_FitCPU")->Unit(benchmark::kMillisecond)->Args({fitCpu}); +BENCHMARK(benchProdPdf)->Unit(unit)->Name("ProdPdf_FitCodegen")->Unit(benchmark::kMillisecond)->Args({fitCodegen}); +BENCHMARK(benchProdPdf) + ->Unit(unit) + ->Name("ProdPdf_FitCodegenNoGrad") + ->Unit(benchmark::kMillisecond) + ->Args({fitCodegenNoGrad}); CUDA_ONLY(BENCHMARK(benchProdPdf)->Unit(unit)->Name("ProdPdf_FitCUDA")->Unit(benchmark::kMillisecond)->Args({fitCuda})); // Watch out with the result from these benchmarks: if there are evaluation @@ -341,6 +360,12 @@ CUDA_ONLY(BENCHMARK(benchProdPdf)->Unit(unit)->Name("ProdPdf_FitCUDA")->Unit(ben // how the backends are handling those. This might or might not be wanted. BENCHMARK(benchModel)->Unit(unit)->Name("FitModel_FitLegacy")->Unit(benchmark::kMillisecond)->Args({fitScalar}); BENCHMARK(benchModel)->Unit(unit)->Name("FitModel_FitCPU")->Unit(benchmark::kMillisecond)->Args({fitCpu}); +BENCHMARK(benchModel)->Unit(unit)->Name("FitModel_FitCodegen")->Unit(benchmark::kMillisecond)->Args({fitCodegen}); +BENCHMARK(benchModel) + ->Unit(unit) + ->Name("FitModel_FitCodegenNoGrad") + ->Unit(benchmark::kMillisecond) + ->Args({fitCodegenNoGrad}); CUDA_ONLY(BENCHMARK(benchModel)->Unit(unit)->Name("FitModel_FitCUDA")->Unit(benchmark::kMillisecond)->Args({fitCuda})); int main(int argc, char **argv)