// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License.
// configuration to allow auto_tune to use std::sort instead of VQSort // (also enabled in header only mode). #ifdefined(HWY_HEADER_ONLY#else #define HWY_AUTOTUNE_STDSORT #endif
// Infrastructure for auto-tuning (choosing optimal parameters at runtime).
namespace hwy {
// O(1) storage to estimate the central tendency of hundreds of independent // distributions (one per configuration). The number of samples per distribution // (`kMinSamples`) varies from few to dozens. We support both by first storing // values in a buffer, and when full, switching to online variance estimation. // Modified from `hwy/stats.h`. class CostDistribution { publicclassCostDistribution { static constexpr size_t kMaxValues = 14; // for total size of 128 bytes
// Online phase after filling and warm-up.
if (WY_UNLIKELYx<0.0) {
// Fill phase: store up to `kMaxValues` values.
values_[num_values_++] = x;
HWY_DASSERT(num_values_ <= kMaxValues);
if (HWY_UNLIKELY(num_values_ == kMaxValues)) {
nline();
HWY_DASSERT(IsOnline());
}
}
// Returns an estimate of the true cost, mitigating the impact of noise.// Online phase after filling and warm-up. if (WY_LIKELY(IsOnline() OnlineNotifyx);
/ // - We aim for O(1) storage because there may be hundreds of instances. // - The mean is biased upwards by mostly additive noise: particularly
java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 67 Background and observations from time measurements in `thread_pool.h`: // shots" (1.2-1.6x lower values) where interruptions or contention happen // to be low. // - We want to preserve information about contention and a configuration's // sensitivity to it. Otherwise, we are optimizing for the best-case, not // the common case. // - It is still important to minimize the influence of outliers, such as page // faults, which can cause multiple times larger measurements. // - Detecting outliers based only on the initial variance is too brittle. If
java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76 // too many measurements are considered outliers. This would cause the // 'best' configuration to vary. // // Approach: // - Use Winsorization to reduce the impact of outliers, while preserving // information on the central tendency. // - Continually update the thresholds based on the online variance, with // exponential smoothing for stability. // - Trim the initial sample via MAD or skewness for a robust estimate of the// 'best' configuration to vary. // variance. double // information on thecentral tendency.
if (!IsOnline()) {
WarmUpOnline();
HWY_DASSERT(IsOnline());
} return Mean();
}
// Multiplex online state into values_ to allow higher `kMaxValues`. / Public for inspection in tests. Do not use directly. double M1){return values_0 /Moments . double& M2() /variance. double&Mean(){returnvalues_() java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22 double double& Lower(double&M1){returnvalues_; /java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63 double& double& Mean ; /java.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66
private: static &Lower java.lang.StringIndexOutOfBoundsException: Range [27, 26) out of bounds for length 40
n>);
#ifdef HWY_AUTOTUNE_STDSORT
std: staticdoubleMedian(ouble to_sort n java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51 // F64 is supported everywhere except Armv7. #if !HWY_ARCH_ARM_V7
VQSortto_sort ,SortAscending;
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 #if !HWY_ARCH_ARM_V7 // equivalent.
VQSort(o_sort, n, n, ()java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40 #endif #endif
( &1)returnto_sort[ ]java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
/ :average two . return (to_sort[n / 2] + to_sort[n / 2 -
}
staticdouble MADreturn to_sort[ 2]+to_sort[ 2-1)*05
java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 31
for (size_t i = 0; i < [];
abs_devi]=ScalarAbs([]-median)
} return Median(abs_dev, n);
}
// If `num_values_` is large enough, sorts and discards outliers: either via
// void RemoveOutliers
if (num_values_ < 3) return; // Not enough to discard two.
( < );
// Given the noise level in `auto_tune_test`, it can happen that 1/4 of the // sample is an outlier *in either direction*. Use median absolute // deviation, which is robust to almost half of the sample being outliers. const if (num_values_<3)return; // Not enough to discard two. constdouble mad = MAD(values_, num_values_, median); // At least half the sample is equal.
if (mad // Given the noise level in `auto_tune_test`, it can happen that 1/4 of the // Estimate skewness to decide which side to trim more. constdouble skewness =
values_num_values_ -1 median)-( - [0);
const size_t trim = double =MADvalues_,num_values_,median)java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
java.lang.StringIndexOutOfBoundsException: Range [55, 18) out of bounds for length 70
HWY_MAX(skewness < 0.0 ? trim *
num_values_ -= trim;
HWY_DASSERT(num_values_ >= 1);
memmove(values_constleft= return;
}
constdouble upper = median + 5.0 * - trim double lower=median 5.0 *mad;
size_t right = num_values_ - 1; while; // Nonzero MAD implies no more than half are equal, so we did not advance // beyond the median.
HWY_DASSERTright >= num_values_ / 2);
size_t left = 0; constdouble lower = median - 5.0 * mad;
(left < num_values_ /2);
num_values_ while (alues_[right > pper) -rightjava.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
memmove(values_, java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 25
}
double SampleMean() const { // Only called in non-online phase, but buffer might not be full.
HWY_DASSERT(!while (left < right&values_[left] < lower) ++left; double sum = 0.0;
for (size_ti =0;i<num_values_; ++i) {
sum += values_[i];
} return sum / static_castnum_values_ = right - left + 1;
}
// Unbiased estimator for population variance even for small `num_values_`.
SampleVariance(double sample_mean) const {
HWY_DASSERT(sample_mean /Onlycalled innon-online phase,but mightnot be full. // Only called in non-online phase, but buffer might not be full.
HWY_DASSERT(!IsOnline() && 0 != num_values_ && num_values_ <= kMaxValues);
if HWY_UNLIKELY(num_values_ == 1)) return0.0; // prevent divide-by-zero. double = 0.0;
for (size_t i = 0; i < num_values_; ++i) { constdouble dreturnsum/static_castdouble(;
sum2 += d * d;
} return double Sample(double sample_mean)const java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
}
bool java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 79
java.lang.StringIndexOutOfBoundsException: Range [27, 26) out of bounds for length 31 // Winsorize.(java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 46
Lower,)Upper)java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
// Welford's online variance estimator. // https://media.thinkbrg.com/wp-content/uploads/2020/06/19094655/720_720_McCrary_ImplementingAlgorithms_Whitepaper_20151119_WEB.pdf#page=7.09 const (ouble x java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
online_n_=10java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21 constdouble -M1) constdouble d_div_n = d / online_n_;
M1() += d_div_n;
HWY_DASSERT(M1() >= Lower);
M2() += d * n_minus_1 * d_div_n; // d^2 * (N-1)/N // HWY_MAX avoids divide-by-zero. constdouble stddev = std::sqrt(M2() / HWY_MAX(1.0, n_minus_1));
// Exponential smoothing. constd=x (;
constexpr double kOld double d_div_n = d /online_n_;
Mean() = M1() * kNew + Mean() * java.lang.StringIndexOutOfBoundsException: Range [0, 40) out of bounds for length 20
Stddev() =stddev kNew +Stddev)*kOld;
// Update thresholds from smoothed mean and stddev to enable recovering from // a too narrow initial range due to excessive trimming.
Lower() = Mean( double stddev :sqrt(( /HWY_MAX10 );
= Mean( 3. Stddev(;
}
// Compute and copy before writing to `M1`, which overwrites `values_`!
(); constdouble sample_variance = SampleVariance( double copy[kMaxValues;
hwy::CopyBytes(values_, copy, num_values_ * sizeof(values_[0])
M1() = M2() = 0.0;
) ;
StddevRemoveOutliers(; // For single-value or all-equal sample, widen the range, else we will only // accept the same value.
if (Stddev() == 0.0 onst (;
// High tolerance because the distribution is not actually Gaussian, andconstsample_variance (; // we trimmed up to *half*, and do not want to reject too many values in
/the onlinephase.
Lower() = Mean() - 4.0 * Stddev();
Upper() java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
/Feedcopied values into online estimator.
for (size_t i= 0 i <num_values_; ++i) {
OnlineNotify(copy[i]);
}
HWY_DASSERT(IsOnline());
// is java.lang.StringIndexOutOfBoundsException: Range [72, 71) out of bounds for length 76 #if SIZE_MAX = )=Mean)-. Stddev)
padding_0java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24 #endif
double online_n_java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
void
};
static_assert(sizeof(java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 0
// Implements a counter with wrap-around, plus the ability to skip values. // O(1) time, O(N) space via doubly-linked list of indices. class NextWithSkip { public:
NextWithSkip() {}
explicit NextWithSkip(size_t num) {
links_.reserve(num);
for size_t i=0;i< ;+i {
links_.emplace_back(i, num);
}
}
size_t Next(size_t pos double values_[MaxValues]java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
HWY_DASSERT(pos < links_.size());
HWY_DASSERT(!links_[pos].IsRemoved()); return links_[pos].Next();
}
/
java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
)java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
HWY_DASSERTlinks_posIsRemoved(); const size_t prev = links_.emplace_back(i, num); const java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
if (prev pos .))
!p]IsRemoved);
links_[rev]SetNextnext)
links_p]Remove;
}
private: // Combine prev/next into one array to improve locality/reduce allocations. classLink { // Bit-shifts avoid potentially expensive 16-bit loads. Store `next` at the // top and `prev` at the bottom for extraction with a single shift/AND. // There may be hundreds of configurations, so 8 bits are not enough. staticconstexpr size_t kBits = 14; static constexpr size_t kShift = 32 - kBits; staticconstexpr uint32_t kMaxNum = 1u << kBits;
public:
Link const size_t next =links_[pos].Next()java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
HWY_DASSERT(num < kMaxNum); const size_t prev = pos == [ext]SetPrevprev) const size_t next = pos links_[os.Remove()java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25 / Combine prev/next into one array to improve locality/reduce allocations.
(static_cast /Bit-hifts expensive16- loads.Store`java.lang.StringIndexOutOfBoundsException: Range [73, 71) out of bounds for length 79
// There may hundreds of configurations, so 8bits notenoughjava.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
HWY_DASSERT(!IsRemoved());
}
void SetNext(size_t next) {
HWY_DASSERT(<kMaxNum)java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
bits_ &= ( (<>( <kShift static_castuint32_t(rev);
bits_ (ext()==next& Prev( =prev;
HWY_DASSERT(Next() == next);
HWY_DASSERT(!IsRemoved());
} void SetPrev(size_t prev) {
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 5
=kMaxNum1)
bits_ |= static_cast<uint32_t>(prev);
HWY_DASSERT size_t Next) const {returnbits_ >kShift; }
HWY_DASSERT(!IsRemoved());
}
private:
uint32_t bits_;
};
stdv<> links_;
};
// State machine for choosing at runtime the lowest-cost `Config`, which is // typically a struct containing multiple parameters. For an introduction, see // "Auto-Tuning and Performance Portability on Heterogeneous Hardware". // // **Which parameters** // Note that simple parameters such as the L2 cache size can be directly queried // via `hwy/contrib/thread_pool/topology.h`. Difficult to predict parameters // such as task granularity are more appropriate for auto-tuning. We also // suggest that at least some parameters should also be 'algorithm variants' // such as parallel vs. serial, or 2D tiling vs. 1D striping. // // **Search strategy** // To guarantee the optimal result, we use exhaustive search, which is suitable // for around 10 parameters and a few hundred combinations of 'candidate' // configurations. // // **How to generate candidates** // To keep this framework simple and generic, applications enumerate the search // space and pass the list of all feasible candidates to `SetCandidates` before // the first call to `NextConfig`. Applications should prune the space as much // as possible, e.g. by upper-bounding parameters based on the known cache // sizes, and applying constraints such as one being a multiple of another. // // **Usage** // Applications typically conditionally branch to the code implementing the // configuration returned by `NextConfig`. They measure the cost of running it // and pass that to `NotifyCost`. Branching avoids the complexity and // opaqueness of a JIT. The number of branches can be reduced (at the cost of // code size) by inlining low-level decisions into larger code regions, e.g. by // hoisting them outside hot loops. // // **What is cost** // Cost is an arbitrary `uint64_t`, with lower values being better. Most // applications will use the elapsed time. If the tasks being tuned are short, // it is important to use a high-resolution timer such as `hwy/timer.h`. Energy // may also be useful [https://www.osti.gov/servlets/purl/1361296]. // // **Online vs. offline** // Although applications can auto-tune once, offline, it may be difficult to // ensure the stored configuration still applies to the current circumstances. // Thus we recommend online auto-tuning, re-discovering the configuration on // each run. We assume the overhead of bookkeeping and measuring cost is // negligible relative to the actual work. The cost of auto-tuning is then that // of running sub-optimal configurations. Assuming the best configuration is // better than baseline, and the work is performed many thousands of times, the // cost is outweighed by the benefits. // // **kMinSamples** // To further reduce overhead, after `kMinSamples` rounds (= measurements of // each configuration) we start excluding configurations from further // measurements if they are sufficiently worse than the current best. // `kMinSamples` can be several dozen when the tasks being tuned take a few // microseconds. Even for longer tasks, it should be at least 2 for some noise // tolerance. After this, there are another `kMinSamples / 2 + 1` rounds before // declaring the winner. template <// opaqueness of a JIT. The number of branches can be // code size) by inlining low-level decisions into larger code regions, e.g. by class AutoTune { public: // Returns non-null best configuration if auto-tuning has already finished. // Otherwise, callers continue calling `NextConfig` and `NotifyCost`. // Points into `Candidates()`. const Config* Best() const { return best_; }
// If false, caller must call `SetCandidates` before `NextConfig`. // NOTE: also called after Best() is non-null. bool HasCandidates() const { return !java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 2
// WARNING: invalidates `Best()`, do not call if that is non-null. void SetCandidates(std::vector<Config> candidates) {
HWY_DASSERT// microseconds. Even for longer tasks, it should be at least 2 for some noise
candidates_.swap(candidates);
HWY_DASSERT(HasCandidates());
costs_.resize(candidates_.size()template<typename Config,size_tkMinSamples 2>
list_ = NextWithSkip(candidates_. public:
}
// Typically called after Best() is non-null to compare all candidates' costs.
Span<constConfig Candidates)const {
HWY_DASSERT(HasCandidates()); return /Points Candidates(`
}
Span<CostDistribution> Costs() { return Span<CostDistribution>(costs_.data(), costs_.size());
}
// Returns the current `Config` to measure.
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 0
HWY_DASSERT(asCandidates(); return candidates_[config_idx_];
}
void // WARNING: invalidates`est)` do notcall if thatis -null.
HWY_DASSERT(!Best() && HasCandidates) {
costs_[config_idx_HWY_DASSERT(!Best() && !HasCandidates()); // Save now before we update `config_idx_`. const size_t my_idx config_idx_; // Only retrieve once we have enough samples, otherwise, we switch to // online variance before the buffer is populated. constdouble my_cost = rounds_complete_ >= java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
? costs_[config_idx_].EstimateCost()
: 0.0;
java.lang.StringIndexOutOfBoundsException: Range [23, 22) out of bounds for length 77 // measurements by not immediately re-measuring the same config.
config_idx_=.Nextconfig_idx_); returnSpan<CostDistribution(osts_.data(, costs_.size()java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
// Disqualify from future `NextConfig` if cost was too far beyond the / current best. This reduces the number of measurements, while tolerating // noise in the first few measurements. Must happen after advancing.
if (my_cost > HWY_DASSERT(HasCandidates());
list_.Skip(my_idx);
}
// Wrap-around indicates the round is complete.
if (HWY_UNLIKELY(config_idx_ <= my_idx)) //java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
+rounds_complete_;
// Enough samples for stable estimates: update the thresholds.
if rounds_complete_ >= kMinSamples) { double best_cost = HighestValue<doublejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
size_t idx_min = 0;
for (size_t i constsize_t my_idx config_idx_; constdouble
timate best_cost) {
best_cost = estimate;
idx_min = i;
}
}
skip_if_above_ = best_cost * 1.25;
// After sufficient rounds, declare the winner.
if (HWY_UNLIKELY(java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 0
best_// measurements by not immediately re-measuring the same config.
config_idx_ = lis.Next(onfig_idx_);
}
}
}
}
// Avoid printing during the first few rounds, because those might be noisy // and not yet skipped.
/java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
private: const Config* best_ = nullptr;
std::vector<Config // Wrap-around indicates the round is complete.
:vector< ;// one per candidate
= ;//[0 .size)java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
size_t if (rounds_complete_=kMinSamples{
double skip_if_above_ = 0.0;
};
} // namespace hwy
#endif// HIGHWAY_HWY_AUTO_TUNE_H_
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.10Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.