Files
TheRock/rocm-libraries/shared/tensile/Tensile/Components/ComputeStoreVgprs.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

341 lines
15 KiB
Python

################################################################################
#
# Copyright (C) 2021-2024 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.
#
################################################################################
from ..Component import ComputeStoreVgprs
from ..AsmUtils import log2, vectorStaticDivideAndRemainder, staticMultiply, vgpr, sgpr, inst, vectorStaticDivide, vectorStaticRemainder
class ComputeStoreVgprsVALU(ComputeStoreVgprs):
kernel = {"EnableMatrixInstructionStore": False}
"""
computeStoreVgprs
Compute workitem/TT offsets in VGPRS
and coord0/coord1
tid0Scale specifies the number of output elements in 0/coalesced dim
that should be written by each work-item in each batch element.
"""
def __call__(self, writer, kernel, divisor, tid0Scale, tid1Scale):
kStr = ""
tmpS0 = writer.getTmpSgpr(3).idx()
tmpS1 = tmpS0+1
wgMT1 = tmpS0+2
if writer.prefetchAcrossPersistent:
wg0="PrevWorkGroup0"
wg1="PrevWorkGroup1"
else:
wg0="WorkGroup0"
wg1="WorkGroup1"
# tid0, tid1: element offsets from the start of macroTile in 0 and 1 direction
# These will live for entire GlobalWrite loop - allocate before tmps
# to avoid fragmentation
tid0 = writer.vgprPool.checkOut(1, "tid0")
tid1 = writer.vgprPool.checkOut(1, "tid1")
packedC1 = kernel["PackedC1IndicesX"]
if kernel["BufferStore"]:
writer.cinRowPtr = writer.vgprPool.checkOut(1, "cinRowPtr")
writer.coutRowPtr = writer.vgprPool.checkOut(1, "coutRowPtr")
kStr += vectorStaticDivideAndRemainder(tid1, tid0, "Serial", divisor, tmpS0)
kStr += staticMultiply(vgpr(tid0), vgpr(tid0), tid0Scale, sgpr(tmpS1))
if tid1Scale != 1:
kStr += staticMultiply(vgpr(tid1), vgpr(tid1), tid1Scale, sgpr(tmpS1))
if kernel["BufferStore"]:
# compute rowStart- this is just tid1 scaled by appropriate stride.
# rowPtr is offset from the beginning of the tile/SRD not the tensor base
# when incremented, it moves in units of (col) Stride to get to a new row
# it is used for address computation, not element range detection.
# rowPtr is in the element space and must be scaled by bpe if bytes are required.
# Do this before code below which overwries the tid1:
# TODO-packed
# Eventually need to modify if supporting packed coord1, to start just assert if that case is detected
#--
strideC1 = "StrideC%s" % (writer.indexChars[packedC1[0]])
kStr += inst("v_mul_lo_u32", vgpr(writer.cinRowPtr),
vgpr(tid1), sgpr(strideC1), \
"rowStart vgpr")
strideD1 = "StrideD%s" % (writer.indexChars[packedC1[0]])
kStr += inst("v_mul_lo_u32", vgpr(writer.coutRowPtr),
vgpr(tid1), sgpr(strideD1), \
"rowStart vgpr")
kStr += "\n"
#kStr += writer.assert_ne(sgpr("WorkGroup1"),1)
# Compute coord0 and coord1
# These are element offsets from the beginning of the tensor.
# These are 'flattened' meaning they span packed tensor dims.
# They need to be preserved so can use in comparisons against
# product-of-packed sizes to determine OOB cases. (for Edge tiles only)
kStr += inst("s_mul_i32", \
sgpr(tmpS0), \
hex(kernel["MacroTile0"]), \
sgpr(wg0), \
"%s = wg0*MT0"%sgpr(tmpS0))
# coord = tid*VW + workgroup offset
kStr += inst("_v_add_co_u32", \
vgpr(tid0), \
writer.vcc, \
sgpr(tmpS0), \
vgpr(tid0), \
"coord0 = tid0*VW + wg0*MT0")
kStr += inst("s_mul_i32", \
sgpr(wgMT1), \
hex(kernel["MacroTile1"]), \
sgpr(wg1), \
"<- wg1*MT1")
kStr += inst("_v_add_co_u32", \
vgpr(tid1), \
writer.vcc, \
sgpr(wgMT1), \
vgpr(tid1), \
"coord1 = tid1*VW + wg1*MT1")
if len(packedC1) > 1:
kStr += writer.extractPackedCoord1ToRowStart(kernel, packedC1, tid1, 'D')
writer.coord0 = tid0
writer.coord1 = tid1
return kStr
class ComputeStoreVgprsMFMA(ComputeStoreVgprs):
kernel = {"EnableMatrixInstructionStore": True,
"SourceSwap": False}
"""
computeStoreVgprs
Compute workitem/TT offsets in VGPRS
and coord0/coord1
tid0Scale specifies the number of output elements in 0/coalesced dim
that should be written by each work-item in each batch element.
"""
def __call__(self, writer, kernel, divisor, tid0Scale, tid1Scale):
# writer.coord0
# writer.coord1
# writer.cinRowPtr : C buffer column offset
# writer.coutRowPtr : D buffer column offset
# alloc resources
tid0 = writer.vgprPool.checkOut(1)
tid1 = writer.vgprPool.checkOut(1)
if kernel["BufferStore"]:
writer.cinRowPtr = writer.vgprPool.checkOut(1, "cinRowPtr")
writer.coutRowPtr = writer.vgprPool.checkOut(1, "coutRowPtr")
wave_id = writer.vgprPool.checkOut(1)
tmpVgpr0 = writer.vgprPool.checkOut(1,"tmpVgpr0")
tmpSgpr = writer.getTmpSgpr(1).idx()
# constant
MIBShape0 = kernel["MatrixInstM"] * kernel["MatrixInstBM"]
MIBShape1 = kernel["MatrixInstN"] * kernel["MatrixInstBN"]
# matrixInstM = kernel["MatrixInstM"] * kernel["MatrixInstBM"] if (kernel["MatrixInstM"] == 4) else kernel["MatrixInstM"]
matrixInstN = kernel["MatrixInstN"] * kernel["MatrixInstBN"] if (kernel["MatrixInstN"] == 4) else kernel["MatrixInstN"]
kStr = ""
# coord 1 : wave part
kStr += vectorStaticDivide(wave_id, "Serial", writer.kernel["WavefrontSize"], tmpSgpr)
kStr += vectorStaticDivide(tid1, wave_id, kernel["MIWaveGroup"][0], tmpSgpr)
kStr += inst("v_mul_lo_u32", vgpr(tid1), hex(MIBShape1), vgpr(tid1), "wave coordination offset 1")
# coord 1 : thread part
kStr += vectorStaticRemainder(tmpVgpr0, "Serial", matrixInstN, tmpSgpr)
kStr += inst("_v_add_lshl_u32", vgpr(tid1), vgpr(tmpVgpr0), vgpr(tid1), log2(kernel["VectorWidthB"]), "coordination 1 = vwb *(wave_id1 + tid1)")
if kernel["BufferStore"]:
# coord 1 : offset part
packedC1 = kernel["PackedC1IndicesX"]
strideC1 = "StrideC%s" % (writer.indexChars[packedC1[0]])
strideD1 = "StrideD%s" % (writer.indexChars[packedC1[0]])
kStr += inst("v_mul_lo_u32", vgpr(writer.cinRowPtr), vgpr(tid1), sgpr(strideC1), " offset 1")
kStr += inst("v_mul_lo_u32", vgpr(writer.coutRowPtr), vgpr(tid1), sgpr(strideD1), " offset 1")
# coord 0 : thread part
kStr += vectorStaticRemainder(tid0, "Serial", writer.kernel["WavefrontSize"], tmpSgpr)
kStr += vectorStaticDivide(tid0, tid0, matrixInstN, tmpSgpr)
kStr += staticMultiply(vgpr(tid0), vgpr(tid0), kernel["MIOutputVectorWidth"], sgpr(tmpSgpr), "thread0 * continuous_output")
if kernel["MatrixInstBM"] > 1 and kernel["MatrixInstN"] == 4 and (kernel["MatrixInstM"] > kernel["MIOutputVectorWidth"]):
# conversion for MI4x4 + MIBM>1
# tid0 = (tid0/MIBM) + (tid0%MIBM)*(MIM//MIOVW)
kStr += vectorStaticDivideAndRemainder(tmpVgpr0, tid0, tid0, kernel["MatrixInstBM"], tmpSgpr) # using rReg=dReg (assuming MIBM is power of 2)
kStr += staticMultiply(vgpr(tid0), vgpr(tid0), kernel["MatrixInstM"]//kernel["MIOutputVectorWidth"], sgpr(tmpSgpr), "(tid1%MIBM)*(MIM//MIOVW)")
kStr += inst("_v_add_u32", vgpr(tid0), vgpr(tmpVgpr0), vgpr(tid0), "tid0 = (tid0/MIBM) + (tid0%MIBM)*MIM")
# coord 0 : wave part
kStr += vectorStaticRemainder(tmpVgpr0, wave_id, kernel["MIWaveGroup"][0], tmpSgpr)
kStr += inst("v_mul_lo_u32", vgpr(tmpVgpr0), hex(MIBShape0), vgpr(tmpVgpr0), "wave coordination offset 0")
kStr += inst("_v_add_lshl_u32", vgpr(tid0), vgpr(tmpVgpr0), vgpr(tid0), log2(kernel["VectorWidthA"]), "coordination 0 = vwa *(wave_id0 + tid0)")
if writer.prefetchAcrossPersistent:
wg0="PrevWorkGroup0"
wg1="PrevWorkGroup1"
else:
wg0="WorkGroup0"
wg1="WorkGroup1"
# macro tile 0 part
kStr += inst("s_mul_i32", sgpr(tmpSgpr), kernel["MacroTile0"], sgpr(wg0), "wgp0 * MT0")
kStr += inst("_v_add_u32", vgpr(tid0), sgpr(tmpSgpr), vgpr(tid0), "coord 0 = (tid0/MI_m)*4 + waveG0*MIB_m + MT0*SG0")
# macro tile 1 part
kStr += inst("s_mul_i32", sgpr(tmpSgpr), kernel["MacroTile1"], sgpr(wg1), "wgp1 * MT1")
kStr += inst("_v_add_u32", vgpr(tid1), sgpr(tmpSgpr), vgpr(tid1), "coord 1 = (tid0%MI_m) + waveG1*MIB_n + MT1*SG1")
# extract packed rowStart vgpr
if kernel["BufferStore"] and len(packedC1) > 1:
kStr += writer.extractPackedCoord1ToRowStart(kernel, packedC1, tid1, 'D')
# release resource
writer.vgprPool.checkIn(tmpVgpr0)
writer.vgprPool.checkIn(wave_id)
# StoreRemap: calculate
# 1. local read address
# 2. local write address
# 3. global write coord0 and coord1
if kernel["StoreRemapVectorWidth"]:
kStr += writer.storeRemapComputeStoreVgprs(kernel)
writer.coord0 = tid0
writer.coord1 = tid1
return kStr
class ComputeStoreVgprsMFMASwap(ComputeStoreVgprs):
kernel = {"EnableMatrixInstructionStore": True,
"SourceSwap": True}
"""
computeStoreVgprs
Compute workitem/TT offsets in VGPRS
and coord0/coord1
tid0Scale specifies the number of output elements in 0/coalesced dim
that should be written by each work-item in each batch element.
"""
def __call__(self, writer, kernel, divisor, tid0Scale, tid1Scale):
# writer.coord0
# writer.coord1
# writer.cinRowPtr : C buffer column offset
# writer.coutRowPtr : D buffer column offset
# alloc resources
tid0 = writer.vgprPool.checkOut(1)
tid1 = writer.vgprPool.checkOut(1)
if kernel["BufferStore"]:
writer.cinRowPtr = writer.vgprPool.checkOut(1, "cinRowPtr")
writer.coutRowPtr = writer.vgprPool.checkOut(1, "coutRowPtr")
wave_id = writer.vgprPool.checkOut(1)
tmpVgpr0 = writer.vgprPool.checkOut(1,"tmpVgpr0")
tmpSgpr = writer.getTmpSgpr(1).idx()
# constant
MIBShape0 = kernel["MatrixInstM"] * kernel["MatrixInstBM"]
MIBShape1 = kernel["MatrixInstN"] * kernel["MatrixInstBN"]
matrixInstM = kernel["MatrixInstM"] * kernel["MatrixInstBM"] if (kernel["MatrixInstM"] == 4) else kernel["MatrixInstM"]
# matrixInstN = kernel["MatrixInstN"] * kernel["MatrixInstBN"] if (kernel["MatrixInstN"] == 4) else kernel["MatrixInstN"]
kStr = ""
kStr += vectorStaticDivide(wave_id, "Serial", writer.kernel["WavefrontSize"], tmpSgpr)
# coord 1 : thread part
kStr += vectorStaticRemainder(tid1, "Serial", writer.kernel["WavefrontSize"], tmpSgpr)
kStr += vectorStaticDivide(tid1, tid1, matrixInstM, tmpSgpr)
kStr += staticMultiply(vgpr(tid1), vgpr(tid1), kernel["MIOutputVectorWidth"], sgpr(tmpSgpr), "thread0 * continuous_output")
if kernel["MatrixInstBN"] > 1 and kernel["MatrixInstM"] == 4 and (kernel["MatrixInstN"] > kernel["MIOutputVectorWidth"]):
# conversion for MI4x4 + MIBN>1
# tid1 = (tid1/MIBN) + (tid1%MIBN)*(MIN//MIOVW)
kStr += vectorStaticDivideAndRemainder(tmpVgpr0, tid1, tid1, kernel["MatrixInstBN"], tmpSgpr) # using rReg=dReg (assuming MIBN is power of 2)
kStr += staticMultiply(vgpr(tid1), vgpr(tid1), kernel["MatrixInstN"]//kernel["MIOutputVectorWidth"], sgpr(tmpSgpr), "(tid1%MIBN)*(MIN//MIOVW)")
kStr += inst("_v_add_u32", vgpr(tid1), vgpr(tmpVgpr0), vgpr(tid1), "tid1 = (tid1/MIBN) + (tid1%MIBN)*MIN")
# coord 1 : wave part
kStr += vectorStaticDivide(tmpVgpr0, wave_id, kernel["MIWaveGroup"][0], tmpSgpr)
kStr += inst("v_mul_lo_u32", vgpr(tmpVgpr0), hex(MIBShape1), vgpr(tmpVgpr0), "wave coordination offset 1")
kStr += inst("_v_add_lshl_u32", vgpr(tid1), vgpr(tmpVgpr0), vgpr(tid1), log2(kernel["VectorWidthB"]), "coordination 1 = vwb *(wave_id1 + tid1)")
if kernel["BufferStore"]:
# coord 1 : offset part
packedC1 = kernel["PackedC1IndicesX"]
strideC1 = "StrideC%s" % (writer.indexChars[packedC1[0]])
strideD1 = "StrideD%s" % (writer.indexChars[packedC1[0]])
kStr += inst("v_mul_lo_u32", vgpr(writer.cinRowPtr), vgpr(tid1), sgpr(strideC1), " offset 1")
kStr += inst("v_mul_lo_u32", vgpr(writer.coutRowPtr), vgpr(tid1), sgpr(strideD1), " offset 1")
# coord 0 : wave part
kStr += vectorStaticRemainder(tmpVgpr0, wave_id, kernel["MIWaveGroup"][0], tmpSgpr)
if kernel["MIWaveGroup"][0] > 1:
kStr += inst("v_mul_lo_u32", vgpr(tmpVgpr0), hex(MIBShape0), vgpr(tmpVgpr0), "wave coordination offset 0")
# coord 0 : thread part
kStr += vectorStaticRemainder(tid0, "Serial", matrixInstM, tmpSgpr)
kStr += inst("_v_add_lshl_u32", vgpr(tid0), vgpr(tmpVgpr0), vgpr(tid0), log2(kernel["VectorWidthA"]), "coordination 0 = vwa *(wave_id0 + tid0)")
if writer.prefetchAcrossPersistent:
wg0="PrevWorkGroup0"
wg1="PrevWorkGroup1"
else:
wg0="WorkGroup0"
wg1="WorkGroup1"
# macro tile 0 part
kStr += inst("s_mul_i32", sgpr(tmpSgpr), kernel["MacroTile0"], sgpr(wg0), "wgp0 * MT0")
kStr += inst("_v_add_u32", vgpr(tid0), sgpr(tmpSgpr), vgpr(tid0), "coord 0 = (tid0/MI_m)*4 + waveG0*MIB_m + MT0*SG0")
# macro tile 1 part
kStr += inst("s_mul_i32", sgpr(tmpSgpr), kernel["MacroTile1"], sgpr(wg1), "wgp1 * MT1")
kStr += inst("_v_add_u32", vgpr(tid1), sgpr(tmpSgpr), vgpr(tid1), "coord 1 = (tid0%MI_m) + waveG1*MIB_n + MT1*SG1")
# release resource
writer.vgprPool.checkIn(tmpVgpr0)
writer.vgprPool.checkIn(wave_id)
# StoreRemap: calculate
# 1. local read address
# 2. local write address
# 3. global write coord0 and coord1
if kernel["StoreRemapVectorWidth"]:
kStr += writer.storeRemapComputeStoreVgprs(kernel)
writer.coord0 = tid0
writer.coord1 = tid1
return kStr