Files
mfem/tests/benchmarks/bench_tmop.cpp
T

198 lines
5.3 KiB
C++

// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#include "bench.hpp"
#ifdef MFEM_USE_BENCHMARK
#include "fem/tmop.hpp"
#include <cassert>
#include <memory>
#include <cmath>
struct TMOP
{
const int N, p, q, dim = 3;
Mesh mesh;
TMOP_Metric_302 metric;
TargetConstructor::TargetType target_t;
TargetConstructor target_c;
H1_FECollection fec;
FiniteElementSpace fes;
const Operator *R;
const IntegrationRule *ir;
TMOP_Integrator nlfi;
const int dofs;
GridFunction x;
Vector de,xe,ye;
double mdof;
TMOP(int p, bool p_eq_q = false):
N(Device::IsEnabled()?16:8),
p(p), q(2*p + (p_eq_q ? 0 : 2)),
mesh(Mesh::MakeCartesian3D(N,N,N,Element::HEXAHEDRON)),
target_t(TargetConstructor::IDEAL_SHAPE_EQUAL_SIZE),
target_c(target_t),
fec(p, dim),
fes(&mesh, &fec, dim),
R(fes.GetElementRestriction(ElementDofOrdering::LEXICOGRAPHIC)),
ir(&IntRules.Get(mesh.GetTypicalElementGeometry(), q)),
nlfi(&metric, &target_c),
dofs(fes.GetVSize()),
x(&fes),
de(R->Height(), Device::GetMemoryType()),
xe(R->Height(), Device::GetMemoryType()),
ye(R->Height(), Device::GetMemoryType()),
mdof(0.0)
{
mesh.SetNodalGridFunction(&x);
target_c.SetNodes(x);
R->Mult(x, xe);
ye = 0.0;
nlfi.SetIntegrationRule(*ir);
nlfi.AssemblePA(fes);
nlfi.AssembleGradPA(xe,fes);
tic_toc.Clear();
}
void AddMultPA()
{
tic_toc.Start();
nlfi.AddMultPA(xe,ye);
MFEM_DEVICE_SYNC;
tic_toc.Stop();
mdof += 1e-6 * dofs;
}
void AddMultGradPA()
{
tic_toc.Start();
nlfi.AddMultGradPA(xe,ye);
MFEM_DEVICE_SYNC;
tic_toc.Stop();
mdof += 1e-6 * dofs;
}
void GetLocalStateEnergyPA()
{
tic_toc.Start();
const double energy = nlfi.GetLocalStateEnergyPA(xe);
MFEM_DEVICE_SYNC;
tic_toc.Stop();
MFEM_CONTRACT_VAR(energy);
mdof += 1e-6 * dofs;
}
void AssembleGradDiagonalPA()
{
tic_toc.Start();
nlfi.AssembleGradDiagonalPA(de);
MFEM_DEVICE_SYNC;
tic_toc.Stop();
mdof += 1e-6 * dofs;
}
double Mdof() const { return mdof; }
double Mdofs() const { return mdof / tic_toc.RealTime(); }
};
// The different orders the tests can run
#define P_ORDERS {1,2,3,4}
// P_EQ_Q selects the D1D & Q1D to use instantiated kernels
// P_EQ_Q: 0x22, 0x33, 0x44, 0x55
// !P_EQ_Q: 0x23, 0x34, 0x45, 0x56
#define P_EQ_Q {false,true}
/**
* @brief The Kernel bm::Fixture struct
*/
struct Kernel: public bm::Fixture
{
std::unique_ptr<TMOP> ker;
~Kernel() { assert(ker == nullptr); }
using bm::Fixture::SetUp;
void SetUp(const bm::State& state) override
{ ker.reset(new TMOP(state.range(1), state.range(0))); }
using bm::Fixture::TearDown;
void TearDown(const bm::State &) override { ker.reset(); }
};
/**
Fixture kernels definitions and registrations
*/
#define BENCHMARK_TMOP_F(Bench)\
BENCHMARK_DEFINE_F(Kernel,Bench)(bm::State &state){\
assert(ker.get());\
while (state.KeepRunning()) { ker->Bench(); }\
state.counters["MDof"] = bm::Counter(ker->Mdof(), bm::Counter::kIsRate);\
state.counters["MDof/s"] = bm::Counter(ker->Mdofs());}\
BENCHMARK_REGISTER_F(Kernel,Bench)->ArgsProduct({P_EQ_Q,P_ORDERS})->Unit(bm::kMicrosecond);
/// creating/registering, not used
//BENCHMARK_TMOP_F(AddMultPA)
//BENCHMARK_TMOP_F(AddMultGradPA)
//BENCHMARK_TMOP_F(GetLocalStateEnergyPA)
//BENCHMARK_TMOP_F(AssembleGradDiagonalPA)
/**
Kernels definitions and registrations
*/
#define BENCHMARK_TMOP(Bench)\
static void Bench(bm::State &state){\
TMOP ker(state.range(1),state.range(0));\
while (state.KeepRunning()) { ker.Bench(); }\
state.counters["MDof"] = bm::Counter(ker.Mdof(), bm::Counter::kIsRate);\
state.counters["MDof/s"] = bm::Counter(ker.Mdofs());}\
BENCHMARK(Bench)->ArgsProduct({P_EQ_Q,P_ORDERS})->Unit(bm::kMicrosecond);
/// creating/registering
BENCHMARK_TMOP(AddMultPA)
BENCHMARK_TMOP(AddMultGradPA)
BENCHMARK_TMOP(GetLocalStateEnergyPA)
BENCHMARK_TMOP(AssembleGradDiagonalPA)
/**
* @brief main entry point
* --benchmark_filter=AddMultPA/4
* --benchmark_context=device=cuda
*/
int main(int argc, char *argv[])
{
bm::ConsoleReporter CR;
bm::Initialize(&argc, argv);
// Device setup, cpu by default
std::string device_config = "cpu";
auto global_context = bmi::GetGlobalContext();
if (bmi::GetGlobalContext() != nullptr)
{
const auto device = global_context->find("device");
if (device != global_context->end())
{
mfem::out << device->first << " : " << device->second << std::endl;
device_config = device->second;
}
}
Device device(device_config.c_str());
device.Print();
if (bm::ReportUnrecognizedArguments(argc, argv)) { return 1; }
bm::RunSpecifiedBenchmarks(&CR);
return 0;
}
#endif // MFEM_USE_BENCHMARK