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
961 lines
43 KiB
Python
961 lines
43 KiB
Python
################################################################################
|
||
#
|
||
# 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()
|