Files
TheRock/rocm-libraries/projects/hipblaslt/tensilelite/Tensile/Common/GlobalParameters.py
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

961 lines
43 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
################################################################################
#
# Copyright (C) 2022-2026 Advanced Micro Devices, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
################################################################################
import itertools
import os.path
import subprocess
import time
from collections import OrderedDict
from copy import deepcopy
from typing import Dict
from Tensile import __version__
from .Architectures import isaToGfx
from .Types import IsaVersion, IsaInfo
from .Utilities import locateExe, versionIsCompatible, print1, print2, printExit, printWarning, \
getVerbosity
from .ValidParameters import validParameters
startTime = time.time()
globalParameters = OrderedDict()
globalParameters["MinimumRequiredVersion"] = (
"0.0.0" # which version of tensile is required to handle all the features required by this configuration file
)
globalParameters["PerformanceMetric"] = (
"DeviceEfficiency" # performance metric for benchmarking; one of {DeviceEfficiency, CUEfficiency}
)
globalParameters["ClientLogLevel"] = (
3 # the log level of client. 0=Error, 1=Terse, 2=Verbose, 3=Debug (Aligned with ResultReporter.hpp)
)
# benchmarking
globalParameters["KernelTime"] = False # T=use device timers, F=use host timers
globalParameters["PreciseKernelTime"] = (
True # T=On hip, use the timestamps for kernel start and stop rather than separate events. Can provide more accurate kernel timing. For GlobalSplitU kernels, recommend disabling this to provide consistent
)
# timing between GSU / non-GSU kernels
globalParameters["PinClocks"] = False # T=pin gpu clocks and fan, F=don't
globalParameters["HardwareMonitor"] = (
True # False: disable benchmarking client monitoring clocks using amd-smi.
)
globalParameters["MinFlopsPerSync"] = (
1 # Minimum number of flops per sync to increase stability for small problems
)
globalParameters["NumBenchmarks"] = (
1 # how many benchmark data points to collect per problem/solution
)
globalParameters["SyncsPerBenchmark"] = (
1 # how iterations of the stream synchronization for-loop to do per benchmark data point
)
globalParameters["EnqueuesPerSync"] = 1 # how many solution enqueues to perform per synchronization
globalParameters["MaxEnqueuesPerSync"] = -1 # max solution enqueues to perform per synchronization
globalParameters["SleepPercent"] = (
300 # how long to sleep after every data point: 25 means 25% of solution time. Sleeping lets gpu cool down more.
)
globalParameters["SkipSlowSolutionRatio"] = 0.0 # Skip slow solution during warm-up stage.
# The valid range of this ratio is (0.0 ~ 1.0), and 0.0 means no skipping.
# Skip condition: warm-up time * ratio > current best sol's warm-up time
# Suggestion:
# Small size : 0.5
# Medium size: 0.75
# Large size : 0.9
# validation
globalParameters["NumElementsToValidate"] = (
128 # number of elements to validate, 128 will be evenly spaced out (with prime number stride) across C tensor
)
globalParameters["NumElementsToValidateWinner"] = (
0 # number of elements to validate in LibraryClient stage, the exact number to be validated is max(NumElementsToValidate,NumElementsToValidateWinner)
)
globalParameters["BoundsCheck"] = 0 # Bounds check
# 1: Perform bounds check to find out of bounds reads/writes. NumElementsToValidate must be -1.
# 2: Perform bounds check by front side guard page
# 3: Perform bounds check by back side guard page
# 4: Perform bounds check by both back and front side guard page
globalParameters["ValidationMaxToPrint"] = 4 # maximum number of mismatches to print
globalParameters["ValidationPrintValids"] = False # print matches too
# steps
globalParameters["ForceRedoBenchmarkProblems"] = (
True # if False and benchmarking already complete, then benchmarking will be skipped when tensile is re-run
)
globalParameters["ForceRedoLibraryLogic"] = (
True # if False and library logic already analyzed, then library logic will be skipped when tensile is re-run
)
globalParameters["ForceRedoLibraryClient"] = (
True # if False and library client already built, then building library client will be skipped when tensile is re-run
)
globalParameters["ShowProgressBar"] = (
True # if False and library client already built, then building library client will be skipped when tensile is re-run
)
globalParameters["SolutionSelectionAlg"] = (
1 # algorithm to determine which solutions to keep. 0=removeLeastImportantSolutions, 1=keepWinnerSolutions (faster)
)
globalParameters["GenerateSourcesAndExit"] = False # Exit after kernel source generation.
globalParameters["ExitOnFails"] = (
1 # 1: Exit after benchmark run if failures detected. 2: Exit during benchmark run.
)
globalParameters["CpuThreads"] = (
-1
) # How many CPU threads to use for kernel generation. 0=no threading, -1 == nproc, N=min(nproc,N). TODO - 0 sometimes fails with a kernel name error? 0 does not check error codes correctly
# If True: after each kernel is assembled, verify that StinkyTofu's total instruction encoding
# size (sum of each instruction's encoded byte length from the Stinky pass pipeline) matches the
# compiled total instruction size (ELF ``.text`` size of the ``.o``, via llvm-readelf/readelf). In
# other words: computed encoding total == compiled total instruction size.
#
# Why: command-processor (CP) prefetch uses that computed total so the right amount of
# kernel code is prefetched. When you add instructions, literals, or passes, this catches mistakes
# where the pipeline’s instruction-size analysis no longer matches real assembly output.
#
# Scope: only kernels emitted through the StinkyTofu assembly path carry the embedded total in the
# generated ``.s`` and participate in this check; that same encoding total feeds
# ``.amdhsa_inst_pref_size`` in ``.amdhsa_kernel`` metadata for CP instruction prefetch.
# Currently this applies to gfx1250 only (StinkyTofu gfx1250 emitter and CP prefetch on that arch).
# Testing: ``tox`` turns on ``CheckASMCodeSize=True`` for the default Tensile pytest runs (see
# ``tox.ini``), so gfx1250 kernels built during those tests are verified automatically.
globalParameters["CheckASMCodeSize"] = False
globalParameters["NumWarmups"] = 0
globalParameters["TimingInstrumentation"] = False # Enable detailed timing instrumentation output
globalParameters["ParallelGpuExecution"] = 1 # Number of GPUs for parallel client execution (0=auto-detect, 1=serial, N=use N GPUs)
globalParameters["PythonProfile"] = False # Enable python profiling
globalParameters["ISA"] = []
########################################
# less common
########################################
globalParameters["CMakeBuildType"] = (
"Release" # whether benchmark clients and library client should be release or debug
)
globalParameters["LogicFormat"] = "yaml" # set library backend (yaml, or json)
globalParameters["LibraryFormat"] = "yaml" # set library backend (yaml, or msgpack)
globalParameters["MXScaleFormat"] = 0 # MX scale data format (0=none, 1=pre-swizzle for GPU kernel layout). Only the gfx950 subtile MX kernels need the pre-swizzle; gfx1250 reads canonical scales. The two gfx950 yamls that need it set MXScaleFormat: 1 explicitly.
# True/False: CSV will/won't export WinnerGFlops, WinnerTimeUS, WinnerIdx, WinnerName.
# TODO - if no side-effect, we can set default to True. This can make analyzing "LibraryLogic" (AddFromCSV) faster
globalParameters["CSVExportWinner"] = False
# (When NumBenchmarks > 1). True: CSV will merge the rows of same Problem-ID. False: Each problem will write out "NumBenchmarks" rows
# In old client - No effect, since in old client, CSV file only exports the last benchmark, somehow is not correct because the previous benchmarks are discarded
# In new client - csv file exports "NumBenchmarks" rows for every problem. This also make the later analyzing slower
# Set this to "True" can merge the rows for same problem, hence can reduce the csv file size and speed up the later analyzing
# TODO - if side-effect, we can set default to True. This can make "getResults()" / "AddFromCSV()" faster
globalParameters["CSVMergeSameProblemID"] = False
# how to initialize tensor data
# serial-in-u will use a sequence that increments in the K dimension
# This is a predictable patterns that can be checked as the kernel runs to detect
# when the wrong data is being used.
# trig_float initializes with the sin function to have non-zero values in the mantissa
# and exponent. It cannot be used for int8 or int32. Need to use tensileAlmostEqual
# not tensileEqual for checking the result.
# See ClientWriter.py, the DataInitName(Enum) for a list of initialization patterns
# - Problem-Independent: 0=0, 1=1, 2=2, 3=rand, 4=Nan, 5=Infinity, 6=BadInput(Nan), 7=BadOutput(Inf), 16=RandomNarrow,
# 21=RandomNegPosLimited(-128~128 or -1~1), 23~26=Ind Cos/Sin Abs or Not
# - Problem-dependent: 8=SerialID, 9=SerialDim0, 10=SerialDim1, 11=Identity, 12~15= Cos/Sin, Abs or Not
# For A, B, C, D: All the InitMode (0~16) can be used
# For Alpha/Beta: Only problem-independent init (0~7, 16, 23~26) can be used,
# problem-dependent init (8~15) would cause a exception (Invalid InitMode) in New Client
globalParameters["DataInitTypeAB"] = 3
globalParameters["DataInitTypeA"] = -1
globalParameters["DataInitTypeB"] = -1
globalParameters["DataInitTypeC"] = 3
globalParameters["DataInitTypeD"] = 0
globalParameters["DataInitTypeE"] = 0
globalParameters["DataInitTypeAlpha"] = 2
globalParameters["DataInitTypeBeta"] = 2
globalParameters["DataInitTypeBias"] = 3
globalParameters["DataInitTypeGate"] = 3
globalParameters["DataInitTypeScaleA"] = 2
globalParameters["DataInitTypeScaleB"] = 2
globalParameters["DataInitTypeScaleC"] = 2
globalParameters["DataInitTypeScaleD"] = 2
globalParameters["DataInitTypeScaleAlphaVec"] = 3
globalParameters["DataInitTypeMXSA"] = 1
globalParameters["DataInitTypeMXSB"] = 1
globalParameters["DataInitValueActivationArgs"] = [2.0, 2.0]
# StreamK=5 hybrid-mode toggle values driven by the benchmark client.
# Each list entry causes ClientProblemFactory to replay every base
# problem with setParams().setStreamKTileSchedulingMode(value). Accepts
# the full tri-state {0=OFF (static), 1=ON (dynamic per-XCD work-queue),
# 2=AUTO (heuristic)}. Set to [0, 1] in YAML GlobalParameters to
# deterministically exercise both SK5 sub-paths in a single sweep run;
# AUTO is supported as well, but in a sweep it leaves the per-launch
# sub-path up to the runtime heuristic, so [0, 1] is preferred when
# the YAML's job is sub-path coverage. AUTO is most useful when
# overriding from the command line (e.g. `--streamk-hybrid-mode 2`)
# to run the heuristic end-to-end on a real problem. Ignored at the
# host for non-SK5 solutions. Default keeps behavior unchanged for
# existing tests.
globalParameters["StreamKHybridMode"] = [0]
globalParameters["CEqualD"] = (
False # Set to true if testing for the case where the pointer to C is the same as D.
)
# When this parameter is set to 0, the Tensile client will use srand(time(NULL)).
# If not 0 the Tensile client will use srand(seed).
globalParameters["DataInitSeed"] = 0
globalParameters["PruneSparseMode"] = (
0 # Prune mode for Sparse Matrix: 0=random, 1=XX00, 2=X0X0, 3=0XX0, 4=X00X, 5=0X0X, 6=00XX
)
# build parameters
globalParameters["CMakeCXXFlags"] = "" # pass flags to cmake
globalParameters["CMakeCFlags"] = "" # pass flags to cmake
globalParameters["AsanBuild"] = False # build with asan
#globalParameters["SaveTemps"] = False # Generate intermediate results of hip kernels
globalParameters["KeepBuildTmp"] = False # If true, do not remove artifacts in build_tmp
# debug for assembly
#globalParameters["SplitGSU"] = False # Split GSU kernel into GSU1 and GSUM
# Tensor printing controls:
globalParameters["PrintTensorA"] = 0 # Print TensorA after initialization
globalParameters["PrintTensorB"] = 0 # Print TensorB after initialization
globalParameters["PrintTensorC"] = (
0 # Print TensorC. 0x1=after init; 0x2=after copy-back; 0x3=both
)
globalParameters["PrintTensorD"] = (
0 # Print TensorD. 0x1=after init; 0x2=after copy-back; 0x3=both
)
globalParameters["PrintTensorRef"] = (
0 # Print reference tensor. 0x1=after init; 0x2=after copy-back; 0x3=both
)
globalParameters["PrintTensorBias"] = 0 # Print TensorBias after initialization
globalParameters["PrintTensorGate"] = 0
globalParameters["PrintTensorScaleAlphaVec"] = 0 # Print TensorScaleAlphaVec after initialization
globalParameters["PrintTensorAmaxD"] = 0 # Print AmaxD after validation
globalParameters["PrintWinnersOnly"] = False # Only print the solutions which become the fastest
globalParameters["PrintCodeCommands"] = (
False # print the commands used to generate the code objects (asm,link,hip-clang, etc)
)
globalParameters["DumpTensors"] = (
False # If True, dump tensors to binary files instead of printing them.
)
# If PrintMax* is greater than the dimension, the middle elements will be replaced with "..."
# device selection
globalParameters["Platform"] = 0 # select opencl platform
# shouldn't need to change
globalParameters["ClientExecutionLockPath"] = (
None # Path for a file lock to ensure only one client is executed at once. filelock module is required if this is enabled.
)
globalParameters["LibraryUpdateFile"] = (
"" # File name for writing indices and speeds suitable for updating an existing library logic file
)
globalParameters["LibraryUpdateComment"] = (
False # Include solution name as a comment in the library update file
)
# internal, i.e., gets set during startup
globalParameters["AMDSMIPath"] = None # /usr/bin/amd-smi
globalParameters["HipClangVersion"] = "0.0.0"
# default runtime is selected based on operating system, user can override
if os.name == "nt":
globalParameters["RuntimeLanguage"] = "HIP"
else:
globalParameters["RuntimeLanguage"] = "HIP"
globalParameters["CodeObjectVersion"] = "4"
# perf model
globalParameters["PerfModelL2ReadHits"] = 0.0
globalParameters["PerfModelL2WriteHits"] = 0.15
globalParameters["PerfModelL2ReadBwMul"] = 2
globalParameters["PerfModelReadEfficiency"] = 0.85
# limitation for training
globalParameters["MaxWorkspaceSize"] = 128 * 1024 * 1024 # max workspace for training (128MB)
#globalParameters["MinKForGSU"] = 32 # min K size to use GlobalSplitU algorithm (only for HPA now)
# control if a solution is run for a given problem
globalParameters["GranularityThreshold"] = 0.0
# control if a solution is run for a given performance prediction
# if enabled, the solutions will be run in the order of the performance prediction, from fatest to slowest.
# PredictionThreshold > 1 : Regular tuning, no sorting with performance prediction.
# PredictionThreshold == 1: Regular tuning, but sorted with performance prediction.
# PredictionThreshold < 1 : Sort and use the `PredictionThreshold * NumSolutions`-th performance prediction value as the threshold,
# and run the solutions with better prediction value than the threshold. Usually only run the
# `PredictionThreshold`-percent of solutions.
# PredictionTHreshold == 0: Run the single solution with best prediction value.
globalParameters["PredictionThreshold"] = 2.0
globalParameters["PristineOnGPU"] = (
True # use Pristine memory on Tensile trainning verification or not
)
globalParameters["SeparateArchitectures"] = (
False # write Tensile library metadata to separate files for each architecture
)
globalParameters["LazyLibraryLoading"] = (
False # Load library and code object files when needed instead of at startup
)
globalParameters["EnableMarker"] = False # Enable Tensile markers
globalParameters["UseUserArgs"] = False
globalParameters["RotatingBufferSize"] = 0 # Size in MB
globalParameters["RotatingMode"] = (
0 # Default is 0, allocated in order A0B0C0D0..ANBNCNDN. 1 is in order A0 pad B0 pad .... AN pad BN pad.
)
# Mode 0 requires memcpy everytime when the problem changes to reset the data, but mode 1 doesn't.
# I-cache rotation (used by client --icache-rotate-copies / --icache-rotate-size).
# IcacheRotateCopies: number of EXTRA hipModule_t copies of each --code-object to load
# for I-cache cold-miss tests. 0 = disabled (default). N (>0) = load N extras
# (total = N+1 modules). -1 = auto: extras = max(rotating buffer num,
# cache-overflow term). The cache-overflow term is
# IcacheRotateSize * 2 * 1024 / min(kernel_start->label_GW_End) on Linux, and
# IcacheRotateSize directly on non-Linux (no <elf.h> available).
globalParameters["IcacheRotateCopies"] = 0
# IcacheRotateSize: cache budget (in KB) used by the auto path's cache-overflow term.
# Linux: effective bytes = IcacheRotateSize * 2 * 1024. Default 64 -> 128 KB,
# loosely targeting ~2x a typical L1 I-cache.
# Non-Linux: used directly as the raw extras count (no ELF parsing).
globalParameters["IcacheRotateSize"] = 64
globalParameters["BuildIdKind"] = "sha1"
globalParameters["AsmDebug"] = (
False # Set to True to keep debug information for compiled code objects
)
globalParameters["UseEffLike"] = True # Set to False to use winnerGFlops as the performance metric
globalParameters["DisableAsmComments"] = False # Set to True to disable assembly comments in generated assembly code
# Enable SQTT markers around mainloop iteration (subtile kernels only).
globalParameters["EmitMainloopTraceMarker"] = False
globalParameters["RocProfCounter"] = None # No rocprof counter
# StinkyTofu debug level (applies per-PM: outer PM + each ScopeAdaptor inner PM)
# 0: Silent (default)
# 1: Pass names + AnalysisManager cache activity to stdout
# 2: Initial IR + IR after each pass to per-PM files:
# kernel-OuterPM-{before,after}_passes.txt (outer PM)
# <groupName>-{before,after}_passes.txt (single-region adapter)
# <group1>+<group2>-{before,after}_passes.txt (multi-region adapter)
# wholeKernel-{before,after}_passes.txt (whole-kernel adapter)
globalParameters["StinkyTofuDebugLevel"] = 0
# StinkyTofu selective pass IR dump (applies per-PM, same file naming as DebugLevel 2)
# Comma-separated pass names to print IR before/after (case-sensitive)
# e.g. "CFG Builder" or "RedundantMovEliminationPass, StinkyDAGSchedulerPass"
# Unmatched pass names are silently ignored
globalParameters["StinkyTofuPrintBeforePass"] = ""
globalParameters["StinkyTofuPrintAfterPass"] = ""
# StinkyTofu internal pass debug logging & instruction-order snapshot (global — applies to all PMs)
# Comma-separated pass names (case-sensitive) to:
# 1. Enable PASS_DEBUG output for the listed passes
# 2. Record before/after instruction order JSON when StinkyTofuPassOrderSnapshotJson is set
# e.g. "StinkyDAGSchedulerPass"
# Unmatched pass names are silently ignored
globalParameters["StinkyTofuDebugPass"] = ""
# Before/after instruction-order JSON for tools/stinkytofu-analysis (empty = disabled).
# When set, PassManager records snapshots for passes listed in StinkyTofuDebugPass
# (defaults to StinkyDAGSchedulerPass only when StinkyTofuDebugPass is empty).
# Note: multiple kernels may overwrite the same file unless you use a unique path per build.
globalParameters["StinkyTofuPassOrderSnapshotJson"] = ""
# StinkyTofu optimization remarks (stderr). Unlike PASS_DEBUG (for compiler
# developers), remarks are for kernel developers who want to understand generated
# code quality — e.g. how many regions a loop was split into, what caused the
# splits, and how many s_nop cycles were wasted.
globalParameters["StinkyTofuEnableRemarks"] = False
globalParameters["DisableSTWaitCnt"] = True
# Internal plumbing for the --cpu-only CLI switch (see Tensile.py addCommonArguments).
# When True, the benchmark flow runs GPU-less: ISA is spoofed, the GPU clock-frequency
# probe is skipped, and the client device-launch is stubbed with a synthetic results CSV.
# This is undocumented plumbing only: it is NOT exposed via --global-parameters help and
# must be set solely from the args.cpuOnly flag. Listed here so restoreDefaultGlobalParameters
# resets it to False between runs/tests.
globalParameters["CpuOnly"] = False
# Companion plumbing for --cpu-only: the target gfx arch the belt spoof in
# _detectGlobalCurrentISA returns when the direct ISA-detection path is reached
# without an arch (e.g. a test calling detectGlobalCurrentISA directly). The primary
# path supplies the arch via --gpu-targets and never reaches detection. Undocumented;
# not exposed via --global-parameters. Reset here so restoreDefaultGlobalParameters
# clears it between runs/tests.
globalParameters["CpuOnlyArch"] = "gfx942"
# Save a copy - since pytest doesn't re-run this initialization code and YAML files can override global settings - odd things can happen
# we should do this here...
defaultGlobalParameters = deepcopy(globalParameters)
################################################################################
# Tensile internal parameters
################################################################################
# These parameters are not adjustable by the config yamls. They change with the
# generator versions
internalParameters = {
# Each universal kernel will generate one PostGSU(GlobalSplitUPGR) kernel
"GlobalSplitUPGR": 16
}
# These parameters are used in ContractionSolutions for user arguments support.
defaultInternalSupportParams = {
"KernArgsVersion": 2,
# Information about user input internal kernel argument support
# Change this to False if the CustomKernel does not support.
"SupportUserGSU": True,
# This is a little different from GSU because GSU is already a parameter,
# but WGM is not.
"SupportCustomWGM": True,
"SupportCustomStaggerU": True,
# Use GG as G's backend
"UseUniversalArgs": True,
"UseSFC": False,
}
# same parameter for all solution b/c depends only on compiler
defaultBenchmarkCommonParameters = [
{"InnerUnroll": [1]},
{"KernelLanguage": ["Assembly"]},
{"LdsPadA": [-1]},
{"LdsPadMXSA": [ -1 ] },
{"LdsPadB": [-1]},
{"LdsPadMXSB": [ -1 ] },
{"LdsPadMetadata": [0]},
{"LdsBlockSizePerPadA": [-1]},
{"LdsBlockSizePerPadMXSA": [ -1 ] },
{"LdsBlockSizePerPadB": [-1]},
{"LdsBlockSizePerPadMXSB": [ -1 ] },
{"LdsBlockSizePerPadMetadata": [0]},
{"TransposeLDS": [-1]},
{"TransposeLDSMetadata": [-1]},
{"MaxOccupancy": [40]},
{"MaxLDS": [-1]},
{"VectorWidthA": [-1]},
{"VectorWidthB": [-1]},
{"VectorStore": [-1]},
{"StoreVectorWidth": [-1]},
{"GlobalReadVectorWidthA": [-1]},
{"GlobalReadVectorWidthB": [-1]},
{"LocalReadVectorWidth": [-1]},
{"LocalReadVectorWidthA": [-1]},
{"LocalReadVectorWidthB": [-1]},
{"WaveSeparateGlobalReadA": [0]},
{"WaveSeparateGlobalReadB": [0]},
{"WaveSeparateGlobalReadMetadata": [0]},
{"UnrollLoopSwapGlobalReadOrder": [0]},
{"PrefetchGlobalRead": [1]},
{"PrefetchLocalRead": [1]},
{"PrefetchGL2": [0]},
{"ClusterLocalRead": [1]},
{"SuppressNoLoadLoop": [False]},
{"ExpandPointerSwap": [True]},
{"ScheduleGlobalRead": [1]},
{"ScheduleLocalWrite": [1]},
{"ScheduleIterAlg": [3]},
{"GlobalReadPerMfma": [1.0]},
{"LocalWritePerMfma": [-1]},
{"InterleaveAlpha": [0]},
{"OptNoLoadLoop": [1]},
{"BufferLoad": [True]},
{"BufferStore": [True]},
{"CompactLoopStore": [False]},
{"DirectToVgprA": [False]},
{"DirectToVgprB": [False]},
{"DirectToVgprMXSA": [False]},
{"DirectToVgprMXSB": [False]},
{"DirectToVgprSparseMetadata": [False]},
{"DirectToLds": [0]},
{"DirectToLdsMetadata": [1]},
{"UseSubtileImpl": [False]},
{"UseSgprForGRO": [-1]},
{"UseInstOffsetForGRO": [0]},
{"AssertSummationElementMultiple": [1]},
{"AssertFree0ElementMultiple": [1]},
{"AssertFree1ElementMultiple": [1]},
{"AssertAIGreaterThanEqual": [-1]},
{"AssertAILessThanEqual": [-1]},
{"StaggerU": [32]}, # recommend [0,32]
{"StaggerUStride": [256]}, # recommend 256 for V10,V20
{"StaggerUMapping": [0]}, # recommend [0,1]
{"MagicDivAlg": [2]},
{"GlobalSplitU": [1]},
{"GlobalSplitUAlgorithm": ["MultipleBuffer"]},
{"GlobalSplitUCoalesced": [False]},
{"GlobalSplitUWorkGroupMappingRoundRobin": [False]},
{"Use64bShadowLimit": [True]},
{"Use64bShadowLimitMX": [False]}, # Disable Use64bShadowLimit for MXSA/B by default
{"NumLoadsCoalescedA": [1]},
{"NumLoadsCoalescedB": [1]},
{"WorkGroup": [[16, 16, 1]]},
{"WorkGroupMapping": [8]},
{"WorkGroupMappingXCC": [1]},
{"WorkGroupMappingXCCGroup": [-1]},
{"ThreadTile": [[4, 4]]},
{"WavefrontSize": [-1]},
{"MatrixInstruction": [[]]},
{"1LDSBuffer": [0]},
{"LDSSegmentInterleave": [0]},
{"DepthU": [-1]},
{"NonTemporalE": [0]},
{"NonTemporalGate": [0]},
{"NonTemporalD": [0]},
{"NonTemporalC": [0]},
{"NonTemporalA": [0]},
{"NonTemporalMXSA": [ 0 ] },
{"NonTemporalB": [0]},
{"NonTemporalMXSB": [ 0 ] },
{"NonTemporalWS": [0]},
{"NonTemporalMetadata": [0]},
{"NonTemporal": [-1]},
{"TemporalHint": [-1]},
{"TemporalHintE": [0]},
{"TemporalHintD": [0]},
{"TemporalHintC": [0]},
{"TemporalHintA": [0]},
{"TemporalHintMXSA": [0]},
{"TemporalHintB": [0]},
{"TemporalHintMXSB": [0]},
{"TemporalHintWS": [0]},
{"TemporalHintMetadata": [0]},
{"NonVolatile": [-1]},
{"NonVolatileE": [0]},
{"NonVolatileD": [0]},
{"NonVolatileC": [0]},
{"NonVolatileA": [0]},
{"NonVolatileMXSA": [0]},
{"NonVolatileB": [0]},
{"NonVolatileMXSB": [0]},
{"NonVolatileWS": [0]},
{"NonVolatileMetadata": [0]},
{"PreloadKernArgs": [True]},
{"CustomKernelName": [""]},
{"NoReject": [False]},
{"StoreRemapVectorWidth": [0]},
{"SourceSwap": [False]},
{"UseDualFMAC": [False]},
{"StorePriorityOpt": [False]},
{"NumElementsPerBatchStore": [0]},
{"StoreSyncOpt": [0]},
{"GroupLoadStore": [False]},
{"MIArchVgpr": [False]},
{"StreamK": [0]},
{"StreamKForceDPOnly": [0]},
{"StreamKAtomic": [0]},
{"StreamKWorkStealing": [0]},
{"StreamKXCCMapping": [0]},
{"StreamKFixupTreeReduction": [0]},
{"DebugStreamK": [0]},
{"DebugPersistentKernelLoopForever": [False]},
{"ActivationFused": [True]},
{"ActivationFuncCall": [True]},
{"ActivationAlt": [False]},
{"WorkGroupReduction": [False]},
{"ConvertAfterDS": [False]},
{"ForceDisableShadowInit": [False]},
{"InitCIterWmma": [-1]},
{"LDSTrInst": [False]},
{"WaveSplitK": [ False ]},
{"MbskPrefetchMethod": [-1]},
{"PrefetchAcrossPersistent": [0]},
{"UseCustomMainLoopSchedule": [-1]},
{"SpaceFillingAlgo": [[]]},
{"SFCWGM": [[[1,1],[1,1]]]},
{"AdaptiveGemm": [0]},
{"AdaptiveGemmGSUA": [0]},
{"AdaptiveGemmNTAB": [0]},
{"ExtraMiLatencyLeft": [-1]},
{"ExtraLatencyForLR": [0]},
{"TailloopInNll": [False]},
{"SwapGlobalReadOrder": [0]},
{"ScheduleGROverBarrier": [-1]},
{"DtlPlusLdsBuf": [-1]},
{"MinGRIncPerMfma": [-1]},
{"UsePLRPack": [0]},
{"TDMInst": [0]},
{"TDMSplit": [False]},
{"MXScaleFormat": ["Auto"]},
{"MXLoadInst": ["Auto"]},
# SwInstructionPrefetch — True: reserve one scratch SGPR so StinkyTofu can insert software
# instruction prefetch when the ISA supports it (SwPrefetchInsertionPass).
# Purpose: CP prefetch covers only a bounded window; very large kernels can see early kernel
# code evicted from the I-cache before it runs. Software prefetch helps keep instruction fetch
# ahead of execution. False: no SGPR reserved; Stinky prefetch pass disabled for that kernel.
{"SwInstructionPrefetch": [True]},
# ClusterDim — workgroup cluster dimensions [x, y] for clustered kernel launch.
# [1, 1] disables clustering. Non-[1, 1] enables Multicast so workgroups within
# a cluster can share data loaded via TDM-multicast, reducing redundant global reads.
{"ClusterDim": [[1, 1]]},
{"HalfPLR": [0]},
{"TDMIterateMode": [0]}
]
# dictionary of defaults comprised of default option for each parameter
defaultSolution = {}
for paramDict in defaultBenchmarkCommonParameters:
for key, value in paramDict.items():
defaultSolution[key] = value[0]
# other non-benchmark options for solutions
defaultProblemSizes = [{"Range": [[2880], 0, 0]}]
defaultBenchmarkFinalProblemSizes = [{"Range": [[64, 64, 64, 512], 0, 0]}]
defaultBatchedProblemSizes = [{"Range": [[2880], 0, [1], 0]}]
defaultBatchedBenchmarkFinalProblemSizes = [{"Range": [[64, 64, 64, 512], 0, [1], 0]}]
defaultSolutionSummationSizes = [32, 64, 96, 128, 256, 512, 1024, 2048, 4096, 8192, 16192]
################################################################################
# Default Analysis Parameters
################################################################################
defaultAnalysisParameters = {
"ScheduleName": "Tensile",
"DeviceNames": "fallback",
"ArchitectureName": "gfx000",
"LibraryType": "GridBased",
"SolutionImportanceMin": 0.01, # = 0.01=1% total time saved by keeping this solution
}
# Per-key expected-type overrides for the LibraryLogic block. The
# defaults map gives a single example value per key; for keys that
# legitimately accept multiple Python types (e.g. DeviceNames can be a
# single str like the default "fallback" OR a list of strings naming
# multiple ASIC device IDs that share the same library logic), the
# override widens the accepted type set. Without this widening the
# strict gate in generateLogic() rejects the common list form.
libraryLogicTypeOverrides = {
"DeviceNames": {str, list},
}
################################################################################
# Is query version compatible with current version
# a yaml file is compatible with tensile if
# tensile.major == yaml.major and tensile.minor.step > yaml.minor.step
################################################################################
def restoreDefaultGlobalParameters():
"""
Restores `globalParameters` back to defaults.
"""
global globalParameters
global defaultGlobalParameters
# Can't just assign globalParameters = deepcopy(defaultGlobalParameters) because that would
# result in dangling references, specifically in Tensile.Tensile().
globalParameters.clear()
for key, value in deepcopy(defaultGlobalParameters).items():
globalParameters[key] = value
# hopefully the isaInfoMap keys only contain isas we plan to build and not all
def printCapabilitiesTable(isaInfoMap: Dict[str, IsaInfo]):
"""
Prints a capability table for the given parameters and ISA information map.
Args:
supportedIsas: The ISAs to show in the table.
isaInfoMap: The ISA information map containing assembler and architecture capabilities.
"""
def printTable(rows):
rows = [[str(cell) for cell in row] for row in rows]
colWidths = [max(len(cell) for cell in col) for col in zip(*rows)]
for row in rows:
print(" ".join(cell.ljust(width) for cell, width in zip(row, colWidths)))
def capRow(isaInfoMap, cap, capType):
return [cap] + [
"1" if cap in getattr(info, capType) and getattr(info, capType)[cap] else "-"
for info in isaInfoMap.values()
]
gfxs = list(map(isaToGfx, isaInfoMap.keys()))
headerRow = ["Capability"] + gfxs
allAsmCaps = sorted(
set(itertools.chain(*[info.asmCaps for info in isaInfoMap.values()])),
key=lambda k: (k.split("_")[-1], k),
)
asmCapRows = [capRow(isaInfoMap, cap, "asmCaps") for cap in allAsmCaps]
allArchCaps = sorted(set(itertools.chain(*[info.archCaps for info in isaInfoMap.values()])))
archCapRows = [capRow(isaInfoMap, cap, "archCaps") for cap in allArchCaps]
printTable([headerRow] + asmCapRows + archCapRows)
# Override table for globalParameters keys whose default value is None
# (and therefore have no usable type to derive from type(default)). Each
# entry is the set of permitted types for the user-supplied value.
# Skipping None-defaulted keys wholesale was a coverage gap that allowed
# e.g. RocProfCounter: 42 to pass silently.
globalParameterTypeOverrides = {
"ClientExecutionLockPath": {type(None), str}, # path or unset
"AMDSMIPath": {type(None), str}, # path, populated at startup
"CmakeCxxCompiler": {type(None), str}, # path, populated at startup
"RocProfCounter": {type(None), str}, # counter spec or None
}
def _assertOverrideTableCovers(defaults_dict, override_dict):
"""Coverage guard: every None-defaulted key has an override entry.
Asserts the invariant that any None-defaulted key in globalParameters
carries a corresponding type-override annotation. Exercised in CI by
test_assignGlobalParameters_types.py /
test_registry_disjoint_property.py rather than at module-import time,
so the coverage gap is caught by a failing test (with the same precise
message) instead of coupling the invariant to every import of this
module.
"""
missing = [k for k, v in defaults_dict.items()
if v is None and k not in override_dict]
if missing:
raise RuntimeError(
"globalParameterTypeOverrides is missing entries for the "
f"following None-defaulted globalParameters: {missing!r}. "
"Add type annotations for each to "
"Tensile/Common/GlobalParameters.py."
)
def _assertGlobalParametersAreValid(config, ignoreKeys):
"""Raise ConfigTypeError for the first unknown or mistyped key in *config*.
No side effects: no subprocess, no ``locateExe``, no ISA mutation,
no writes into the module-level ``globalParameters`` registry.
Shared by production (``assignGlobalParameters``) and the corpus test
so the two never diverge on what counts as a clean GlobalParameters block.
Args:
config: the raw ``GlobalParameters:`` dict from the YAML.
ignoreKeys: keys with a sanctioned opt-out from the strict gate.
"""
from .TypeValidationErrors import ConfigTypeError, formatMismatch
# MinimumRequiredVersion is validated separately at the top of
# assignGlobalParameters; skip it in the type loop here.
typeCheckSkip = {"MinimumRequiredVersion"}
for key in config:
if key in ignoreKeys:
continue
value = config[key]
if key not in globalParameters:
raise ConfigTypeError(
f"Unknown global parameter '{key}' = {value!r}. "
f"Add it to globalParameters in GlobalParameters.py if it is real, "
f"or remove it from the config."
)
if key in typeCheckSkip:
continue
if key in globalParameterTypeOverrides:
expectedTypes = globalParameterTypeOverrides[key]
else:
default = globalParameters[key]
if default is None:
continue
expectedTypes = {type(default)}
if type(value) not in expectedTypes:
raise ConfigTypeError(formatMismatch("", f"GlobalParameters.{key}", value, expectedTypes))
# Keys that may appear in a GlobalParameters: block but are not (or no longer)
# entries in the globalParameters registry. _assertGlobalParametersAreValid
# skips these silently. Shared with the corpus test so the two never diverge.
_GLOBAL_PARAMETER_IGNORE_KEYS = [
# --- CLI / TensileCreateLibrary-level config consumed outside the
# globalParameters registry (each has its own argparse dest or
# direct arguments[...] reader) ---
"Architecture", # build-arch list, read directly in Tensile.py
"PrintLevel", # verbosity, read by setVerbosity in TensileCreateLibrary/Run.py
"Device", # device id, read from config in Tensile.py
"UseCompression", # code-object compression toggle, set in ParseArguments / read in Run.py
"CxxCompiler", # --cxx-compiler arg, resolved in Toolchain layer, not a registry value
"CCompiler", # --c-compiler arg, resolved in Toolchain layer, not a registry value
"OffloadBundler", # --offload-bundler arg, resolved in Toolchain layer
"Assembler", # --assembler arg, resolved in Toolchain layer
"LogicPath", # library-logic dir, read by TensileCreateLibrary/Run.py
"LogicFilter", # logic-file glob, read by TensileCreateLibrary/Run.py
"OutputPath", # positional output dir arg in Tensile.py / RetuneLibrary
"Experimental", # --experimental logic-dir toggle in ParseArguments
"GenSolTable", # --gen-sol-table toggle in ParseArguments
# Keys with a sanctioned opt-out from the strict gate:
# - Live but read via DebugConfig (makeDebugConfig in
# Tensile/Common/Types.py) directly from the raw config dict
# after assignGlobalParameters, bypassing the globalParameters
# registry:
"ForceGenerateKernel", # DebugConfig.forceGenerateKernel, read by makeDebugConfig
"PrintIndexAssignmentInfo", # DebugConfig.printIndexAssignmentInfo, read by makeDebugConfig
"PrintSolutionRejectionReason", # DebugConfig.printSolutionRejectionReason, read by makeDebugConfig
]
def assignGlobalParameters(config, isaInfoMap: Dict[IsaVersion, IsaInfo]):
"""
Assign Global Parameters
Each global parameter has a default parameter, and the user
can override them, those overridings happen here
"""
global globalParameters
# Minimum Required Version
if "MinimumRequiredVersion" in config:
if not versionIsCompatible(config["MinimumRequiredVersion"]):
printExit(
"Config file requires version=%s is not compatible with current Tensile version=%s"
% (config["MinimumRequiredVersion"], __version__)
)
# User-specified global parameters
print2("GlobalParameters:")
for key in globalParameters:
defaultValue = globalParameters[key]
if key in config:
configValue = config[key]
if configValue == defaultValue:
print2(" %24s: %8s (same)" % (key, configValue))
else:
print2(" %24s: %8s (overriden)" % (key, configValue))
else:
print2(" %24s: %8s (unspecified)" % (key, defaultValue))
globalParameters["ROCmPath"] = "/opt/rocm"
if "ROCM_PATH" in os.environ:
globalParameters["ROCmPath"] = os.environ.get("ROCM_PATH")
if "TENSILE_ROCM_PATH" in os.environ:
globalParameters["ROCmPath"] = os.environ.get("TENSILE_ROCM_PATH")
if os.name == "nt" and "HIP_DIR" in os.environ:
globalParameters["ROCmPath"] = os.environ.get("HIP_DIR") # windows has no ROCM
globalParameters["CmakeCxxCompiler"] = None
if "CMAKE_CXX_COMPILER" in os.environ:
globalParameters["CmakeCxxCompiler"] = os.environ.get("CMAKE_CXX_COMPILER")
if "CMAKE_C_COMPILER" in os.environ:
globalParameters["CmakeCCompiler"] = os.environ.get("CMAKE_C_COMPILER")
globalParameters["ROCmBinPath"] = os.path.join(globalParameters["ROCmPath"], "bin")
try:
globalParameters["AMDSMIPath"] = locateExe(globalParameters["ROCmBinPath"], "amd-smi")
except OSError:
# amd-smi is only needed at runtime to pin clocks/fans during benchmarking
# and tuning; it is not required to build libraries or validate logic.
# It is also not presently supported on Windows. Treat a missing amd-smi as
# non-fatal: leave AMDSMIPath unset (None) so that clock pinning is skipped,
# rather than aborting the build in environments that do not ship amd-smi.
globalParameters["AMDSMIPath"] = None
if os.name != "nt":
printWarning(
"Could not locate amd-smi; GPU clock/fan pinning will be disabled. "
"Install the amdsmi package to enable it."
)
if "AsanBuild" in config:
globalParameters["AsanBuild"] = config["AsanBuild"]
if "KeepBuildTmp" in config:
globalParameters["KeepBuildTmp"] = config["KeepBuildTmp"]
if "CodeObjectVersion" in config:
globalParameters["CodeObjectVersion"] = config["CodeObjectVersion"]
if getVerbosity() >= 1:
printCapabilitiesTable(isaInfoMap)
isaList = list(isaInfoMap.keys())
validParameters["ISA"] = [IsaVersion(0, 0, 0), *isaList]
# For ubuntu platforms, call dpkg to grep the version of hip-clang. This check is platform specific, and in the future
# additional support for yum, dnf zypper may need to be added. On these other platforms, the default version of
# '0.0.0' will persist
# Due to platform.linux_distribution() being deprecated, just try to run dpkg regardless.
# The alternative would be to install the `distro` package.
# See https://docs.python.org/3.7/library/platform.html#platform.linux_distribution
# The following try except block computes the hipcc version
# TODO: hipcc is deprecated, this block should be removed.
try:
compiler = "hipcc"
output = subprocess.run(
[compiler, "--version"], check=True,
stdout=subprocess.PIPE,
# Avoids some warning spam on Windows.
stderr=subprocess.DEVNULL,
).stdout.decode()
for line in output.split("\n"):
if "HIP version" in line:
globalParameters["HipClangVersion"] = line.split()[2]
print1("# Found hipcc version " + globalParameters["HipClangVersion"])
except (subprocess.CalledProcessError, OSError) as e:
printWarning("Error: {} running {} {} ".format("hipcc", "--version", e))
ignoreKeys = _GLOBAL_PARAMETER_IGNORE_KEYS
_assertGlobalParametersAreValid(config, ignoreKeys)
for key in config:
if key in ignoreKeys:
continue
globalParameters[key] = config[key]
def setupRestoreClocks():
import atexit
def restoreClocks():
# Clocks will only be pinned if amd-smi is available, therefore
# we only need to restore if found.
if globalParameters["PinClocks"]:
asmi = globalParameters["AMDSMIPath"]
if asmi is not None:
# amd-smi set/reset require elevated privileges.
# Reset clocks/overdrive to default and return fans to
# automatic (driver) control.
cmd = [asmi, "reset", "-g", "0", "--clocks", "--fans"]
if hasattr(os, "geteuid") and os.geteuid() != 0:
cmd = ["sudo", "-n"] + cmd
subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
atexit.register(restoreClocks)
setupRestoreClocks()