Files
TheRock/rocm-libraries/projects/hipdnn/frontend/include/hipdnn_frontend/autotune/BenchmarkStatistics.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

101 lines
3.6 KiB
C++

// Copyright © Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
/**
* @file BenchmarkStatistics.hpp
* @brief Statistics utilities for autotune benchmarking
*
* Provides functions for computing mean, standard deviation, and coefficient
* of variation from timing samples. Used by the RUN_UNTIL_STABLE strategy
* to determine convergence.
*/
#pragma once
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <numeric>
#include <stdexcept>
#include <type_traits>
#include <vector>
namespace hipdnn_frontend::autotune::detail
{
// Compute the arithmetic mean of a range of floating-point timing samples.
// Throws std::invalid_argument if values is empty.
//
// The result is clamped to the observed [min, max] range. Floating-point
// summation and division can round the mean a few ULP outside that range when
// the samples are near-identical, which would otherwise violate the
// min <= mean <= max invariant that callers rely on (e.g. the autotune
// min/avg timing stats, where avg dipping below min by a ULP is a real,
// observed flake). The mean of a set is mathematically within its range, so
// clamping only corrects rounding noise and is a no-op for well-separated data.
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
T computeMean(const std::vector<T>& values)
{
if(values.empty())
{
throw std::invalid_argument("computeMean: input vector must not be empty");
}
const auto [minIt, maxIt] = std::minmax_element(values.begin(), values.end());
const auto sum = std::accumulate(values.begin(), values.end(), T{0});
const auto mean = sum / static_cast<T>(values.size());
return std::clamp(mean, *minIt, *maxIt);
}
// Compute the population standard deviation of a range of floating-point
// timing samples. Throws std::invalid_argument if values is empty.
//
// Uses population stddev (divides by N, not N-1) because the benchmarking
// samples represent the complete set of measurements, not a sample drawn
// from a larger population.
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
T computeStddev(const std::vector<T>& values)
{
if(values.empty())
{
throw std::invalid_argument("computeStddev: input vector must not be empty");
}
auto mean = computeMean(values);
auto variance = T{0};
for(const auto& v : values)
{
auto diff = v - mean;
variance += diff * diff;
}
variance /= static_cast<T>(values.size());
return std::sqrt(variance);
}
// Compute the coefficient of variation (CoV) of a range of floating-point
// timing samples: stddev / mean, or 0 if mean is 0. Throws
// std::invalid_argument if values is empty.
//
// The coefficient of variation expresses timing variability as a fraction
// of the mean. A CoV below the stabilityThreshold indicates convergence
// in the RUN_UNTIL_STABLE strategy.
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
T computeCoefficientOfVariation(const std::vector<T>& values)
{
if(values.empty())
{
throw std::invalid_argument(
"computeCoefficientOfVariation: input vector must not be empty");
}
auto mean = computeMean(values);
// Exact zero check is intentional: if all samples are exactly 0.0
// (e.g., sub-microsecond kernel on a coarse timer), CoV is undefined.
// A near-zero check (epsilon) would mask legitimate near-zero means
// where CoV is meaningful (e.g., mean=1e-7, stddev=1e-8 -> CoV=0.1).
if(mean == T{0})
{
return T{0};
}
return computeStddev(values) / mean;
}
} // namespace hipdnn_frontend::autotune::detail