Files
TheRock/rocm-libraries/projects/hipdnn/frontend/include/hipdnn_frontend/autotune/TimedRunLoop.hpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

145 lines
4.9 KiB
C++

// Copyright © Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
/**
* @file TimedRunLoop.hpp
* @brief Host-testable timed-run loop helpers for autotune benchmarking
*
* Implements the FIXED_AVERAGE and RUN_UNTIL_STABLE timed-iteration loops as
* pure helpers parameterized on a timing callable. The only GPU dependency of
* these loops in production is a single per-iteration timing call, so injecting
* that call as a callable makes the convergence/counting logic testable on the
* host with a scripted timing sequence (real hipEvent timings cannot be steered
* deterministically). Per-iteration logging stays at the production call site,
* supplied via the onIteration callback, so the helpers stay free of GPU and
* member state.
*/
#pragma once
#include <string>
#include <vector>
#include "hipdnn_frontend/autotune/BenchmarkStatistics.hpp"
namespace hipdnn_frontend::autotune
{
/**
* @brief Result of a timed-run loop.
*
* @c timings holds every successfully measured iteration (in iteration order).
* @c converged is set by RUN_UNTIL_STABLE when the trailing-window CoV drops
* below the threshold, and by FIXED_AVERAGE when all iterations succeed.
* @c benchmarkFailed / @c errorMessage carry the failure path back to the
* caller so it can mark the engine failed without aborting the autotune run.
*/
struct TimedRunOutcome
{
std::vector<float> timings;
bool converged = false;
bool benchmarkFailed = false;
std::string errorMessage;
};
namespace detail
{
// RUN_UNTIL_STABLE timed loop: run until the trailing-window CoV converges or
// maxIterations is reached.
//
// TimeOnceFn is a callable (float& elapsed) -> Error with no GPU and no member
// state; it returns a bad Error to signal a benchmark failure. OnIterationFn is
// a callable (int iter, float elapsed, float cov, bool covValid) -> void,
// invoked once per successful iteration for logging. windowSize is the number
// of trailing samples used for the CoV check; stabilityThreshold is the CoV
// value below which the loop is considered converged. cov/covValid passed to
// onIteration are only meaningful once timings.size() >= windowSize.
template <typename TimeOnceFn, typename OnIterationFn>
TimedRunOutcome runUntilStable(int maxIterations,
int windowSize,
float stabilityThreshold,
TimeOnceFn&& timeOnce,
OnIterationFn&& onIteration)
{
TimedRunOutcome outcome;
outcome.timings.reserve(static_cast<size_t>(maxIterations));
bool converged = false;
for(int t = 0; t < maxIterations; ++t)
{
float elapsed = 0.0f;
auto benchErr = timeOnce(elapsed);
if(benchErr.is_bad())
{
outcome.errorMessage = "Benchmark failed on iteration " + std::to_string(t) + ": "
+ benchErr.get_message();
outcome.benchmarkFailed = true;
break;
}
outcome.timings.push_back(elapsed);
// Compute CoV for convergence check and logging.
float cov = 0.0f;
bool covValid = false;
bool convergedThisIter = false;
if(static_cast<int>(outcome.timings.size()) >= windowSize)
{
const std::vector<float> window(outcome.timings.end() - windowSize,
outcome.timings.end());
cov = computeCoefficientOfVariation(window);
covValid = true;
if(cov < stabilityThreshold)
{
convergedThisIter = true;
}
}
onIteration(t, elapsed, cov, covValid);
if(convergedThisIter)
{
converged = true;
break;
}
}
outcome.converged = converged;
return outcome;
}
// FIXED_AVERAGE timed loop: run exactly timedIterations and average.
//
// TimeOnceFn is a callable (float& elapsed) -> Error; OnIterationFn is a
// callable (int iter, float elapsed) -> void invoked once per iteration for
// logging.
template <typename TimeOnceFn, typename OnIterationFn>
TimedRunOutcome
runFixedAverage(int timedIterations, TimeOnceFn&& timeOnce, OnIterationFn&& onIteration)
{
TimedRunOutcome outcome;
outcome.timings.reserve(static_cast<size_t>(timedIterations));
for(int t = 0; t < timedIterations; ++t)
{
float elapsed = 0.0f;
auto benchErr = timeOnce(elapsed);
if(benchErr.is_bad())
{
outcome.errorMessage = "Benchmark failed on iteration " + std::to_string(t) + ": "
+ benchErr.get_message();
outcome.benchmarkFailed = true;
break;
}
outcome.timings.push_back(elapsed);
onIteration(t, elapsed);
}
// FIXED_AVERAGE converges iff every iteration succeeded.
outcome.converged = !outcome.benchmarkFailed;
return outcome;
}
} // namespace detail
} // namespace hipdnn_frontend::autotune