Skip to content

Record

The mneme record command executes an application while transparently capturing GPU kernel executions and the associated device memory state. For full CLI details, see CLI → mneme record.

Recording does not require modifying application source code. However, if you want tolerance-aware verification during replay, you can optionally annotate device pointers with comparison metadata before the kernel launches that will be recorded.

Selecting which launches are recorded

Mneme supports several ways to filter which kernel launches get recorded and which do not.

Scoped filtering uses a Mneme runtime API to enable/disable recording. It is best used when application state determines which invocation should be recorded.

#include "mneme/MnemeRecordScope.hpp"

for (int iter = 0; iter < iterations; ++iter) {
    mneme::record_scope scope(iter == 5);
    advance_solution();  // All kernels submitted here are eligible at iteration 5.
}

Run the instrumented application with:

mneme record --filter-mode scoped -- ./app

The default mode, default, records normally and ignores scopes. Invalid modes are rejected. Scoped mode records nothing without an enabled scope.

To select a particular kernel, pass its function instead:

{
  mneme::record_scope scope(foo, iter == 5);
  foo<<<grid, block>>>(data);
  bar<<<grid, block>>>(data);  // This scope does not select bar.
}
foo<<<grid, block>>>(data); // This does not record, since `scope` is out-of-scope.

Kernel selectors use function addresses, not names. Template specializations such as foo<double> are supported; overloaded functions require an explicit function-pointer cast. Null pointers throw std::invalid_argument. The innermost matching scope decides whether a launch is eligible for recording. A scope without a kernel matches every kernel; a kernel-specific scope matches only its selected kernel. Without a matching scope, the launch is not recorded.

mneme::record_scope outer_scope(foo, false);
{
  mneme::record_scope inner_scope(foo, true);
  foo<<<grid, block>>>(data);  // recorded
}
foo<<<grid, block>>>(data);  // not recorded

Scopes cover host launch submission on the calling thread, including ordinary helper calls. Worker threads need their own scopes. Scope entry and exit do not synchronize the GPU. Memory allocated before a scope remains available for recording. All kernels still execute whether or not they are recorded.

Selecting launches with a configuration file

mneme record --filter-mode config --filter-config filter.yaml -- ./app
# Equivalent shorthand:
mneme record --filter-config filter.yaml -- ./app

Config mode ignores application scopes. It is an error to pass --filter-config if the mode is set to scope. With neither --filter-mode nor --filter-config, the CLI selects default.

recording:
  defaults:
    skip: 0
    every: 1
    max_records: 1
    ranks: [0, 2]              # or: all; [] disables all ranks
  kernel_overrides:
    - match:
        demangled_regex: "^foo\\("
      skip: 5
    - match:
        demangled_regex: "^bar\\("
      skip: 1
      every: 10
      max_records: 3

recording is required, but all fields inside it are optional. The built-in defaults are skip: 0, every: 1, and max_records: 4. Mneme uses these by default, unless defaults overrides them or the fields supplied by the first matching override change them.

Default-mode CLI and environment controls

Default mode accepts some overrides from CLI and/or environment variables:

CLI option Environment variable Default
-sr / --per-kernel-skip-recordings MNEME_SKIP_RECORDINGS 0
-mr / --per-kernel-max-recordings MNEME_MAX_RECORDINGS 4
— MNEME_RR_KERNELS All kernels

They apply only in --filter-mode default. An explicit CLI count overrides its environment variable, including explicit zero or four. The below example would record the foo kernel, skip its first five invocations, and record a maximum of two unique configurations of foo.

MNEME_RR_KERNELS='foo' mneme record -sr 5 -mr 2 -- ./app

In scoped and config modes, these count options and environment variables are ignored with a warning.

Annotating buffers for verification

By default, replay verification uses exact byte-wise comparison between the replayed and recorded epilogue snapshots. For kernels that produce floating-point results, this is often too strict.

Mneme provides a lightweight C++ API — mneme::annotate() — that lets you attach a data type, error threshold, aggregation norm, and an optional tag to any device pointer. The metadata is captured inside the recorded snapshot and used automatically during every subsequent replay.

#include "mneme/MnemeAnnotation.hpp"

mneme::annotate(d_output, mneme::Metadata{
    .builtin        = mneme::BuiltinDType::F64,
    .threshold      = 1e-6,
    .threshold_kind = mneme::ThresholdKind::Relative,
    .norm           = mneme::Norm::Linf,
    .tag            = std::string("output_vector"),
});

Annotations must be applied before the kernel launch they should affect. You can update the annotation on the same pointer between launches to record different tolerance policies for different dynamic instances of the same kernel.

For the full API reference, supported data types, threshold semantics, and a complete example, see Usage → Verification.