Skip to content

Commit 6175079

Browse files
committed
[hipblaslt] update tensilelite code-gen part for 64bit offset support to add arguments appropriately and to use only two extra SGPRs
1 parent 34b5c81 commit 6175079

5 files changed

Lines changed: 101 additions & 64 deletions

File tree

projects/hipblaslt/library/src/amd_detail/rocblaslt/src/rocblaslt_mat.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ rocblaslt_status rocblaslt_matmul_impl(const rocblaslt_handle handle,
131131
hipDataType scale_type = matmul_descr->scale_type;
132132

133133
// Others
134+
// Use strided_batch=true for kernel selection (StridedBatched=true kernels with SupportUserArgs)
135+
// The actual batch mode is tracked via problem.batchMode() for argument passing
134136
bool strided_batch = true;
135137
bool grouped_gemm = false;
136138

@@ -343,6 +345,8 @@ rocblaslt_status rocblaslt_gemm_create_cpp_impl(const rocblaslt_handle
343345
void* amaxD = matmul_descr->amaxD;
344346

345347
// Others
348+
// Use strided_batch=true for kernel selection (StridedBatched=true kernels with SupportUserArgs)
349+
// The actual batch mode is tracked via problem.batchMode() for argument passing
346350
bool strided_batch = true;
347351
bool grouped_gemm = false;
348352

projects/hipblaslt/tensilelite/Tensile/Components/Signature.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,6 @@ def __call__(self, writer) -> SignatureBase:
163163
if kernel["ProblemType"]["Sparse"]:
164164
signature.addArg("MetaData", SVK.SIG_GLOBALBUFFER, "void" , "generic")
165165

166-
# Batch offset support for general batched mode (pointer array)
167-
# Only for non-strided, non-grouped GEMM
168-
if not kernel["ProblemType"]["StridedBatched"] and not kernel["ProblemType"]["GroupedGemm"]:
169-
signature.addArg("batchOffsetD", SVK.SIG_VALUE, "u64")
170-
signature.addArg("batchOffsetC", SVK.SIG_VALUE, "u64")
171-
signature.addArg("batchOffsetA", SVK.SIG_VALUE, "u64")
172-
signature.addArg("batchOffsetB", SVK.SIG_VALUE, "u64")
173-
userArgumentsInfo.gemmArgumentSize += 32 # 4 offsets * 8 bytes each
174-
175166
if kernel["StreamK"] > 0 and kernel["StreamKAtomic"] == 0:
176167
signature.addArg("AddressWS", SVK.SIG_GLOBALBUFFER, cptValueType, "generic")
177168
signature.addArg("AddressFlags", SVK.SIG_GLOBALBUFFER, dstValueType, "generic")
@@ -235,6 +226,16 @@ def __call__(self, writer) -> SignatureBase:
235226
signature.addArg("skTiles", SVK.SIG_VALUE, "u32")
236227
userArgumentsInfo.gemmArgumentSize += 8
237228

229+
# Batch offset support for general batched mode (pointer array)
230+
# Placed after core GEMM args (strides, alpha/beta, StreamK)
231+
# Enabled for all SupportUserArgs kernels (offsets are 0 when not in General Batched mode)
232+
if kernel["ProblemType"]["SupportUserArgs"] and not kernel["ProblemType"]["GroupedGemm"]:
233+
signature.addArg("batchOffsetD", SVK.SIG_VALUE, "u64")
234+
signature.addArg("batchOffsetC", SVK.SIG_VALUE, "u64")
235+
signature.addArg("batchOffsetA", SVK.SIG_VALUE, "u64")
236+
signature.addArg("batchOffsetB", SVK.SIG_VALUE, "u64")
237+
userArgumentsInfo.gemmArgumentSize += 32 # 4 offsets * 8 bytes each
238+
238239
if kernel["ProblemType"]["UseScaleAB"]:
239240
signature.addArg("AddressScaleA", SVK.SIG_GLOBALBUFFER, cptValueType, "generic")
240241
signature.addArg("AddressScaleB", SVK.SIG_GLOBALBUFFER, cptValueType, "generic")

projects/hipblaslt/tensilelite/Tensile/KernelWriter.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8460,11 +8460,8 @@ def vgprAllocationImplSubtile():
84608460
self.defineSgpr("StridesMetadata", self.states.m.numSgprStrides)
84618461

84628462
# Batch offset support for general batched GEMM (pointer array mode)
8463-
if not kernel["ProblemType"]["StridedBatched"] and not kernel["ProblemType"]["GroupedGemm"]:
8464-
self.defineSgpr("BatchOffsetD", 2) # 64-bit offset requires 2 SGPRs
8465-
self.defineSgpr("BatchOffsetC", 2) # 64-bit offset requires 2 SGPRs
8466-
self.defineSgpr("BatchOffsetA", 2) # 64-bit offset requires 2 SGPRs
8467-
self.defineSgpr("BatchOffsetB", 2) # 64-bit offset requires 2 SGPRs
8463+
# Offsets are loaded on-demand from kernel arguments to avoid using persistent SGPRs
8464+
# No SGPR allocation here - offsets loaded directly when applying to addresses
84688465

84698466
# for packed batches without stride restrictions need to do something different here
84708467
assert sorted(kernel["PackedC0IdxChars"]+kernel["PackedC1IdxChars"]) == \

projects/hipblaslt/tensilelite/Tensile/KernelWriterAssembly.py

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1898,9 +1898,13 @@ def loadBatchedAddress(self, kernel, Batch, tmpSgprResource: ContinuousRegister)
18981898
module.add(SMulI32(dst=sgpr(tmpSgpr), src0=sgpr(Batch), src1=0x8, comment="offset of global buffer address"))
18991899
module.add(SLoadB64(dst=sgpr("AddressD", 2), base=sgpr("AddressD",2), soffset=sgpr(tmpSgpr), comment="load global buffer D address"))
19001900
# Apply batch offset to AddressD for general batched mode
1901-
if not kernel["ProblemType"]["StridedBatched"] and not kernel["ProblemType"]["GroupedGemm"]:
1902-
module.add(SWaitCnt(kmcnt=0, comment="Wait for the Matrix Address Load from the Pointer Array before updating offset"))
1903-
module.add(SAddU64(dst=sgpr("AddressD", 2), src0=sgpr("AddressD", 2), src1=sgpr("BatchOffsetD", 2), comment="add batch offset to D address"))
1901+
# Load offset on-demand from kernel args (no persistent SGPRs needed)
1902+
if kernel["ProblemType"]["SupportUserArgs"] and not kernel["ProblemType"]["GroupedGemm"]:
1903+
with self.allocTmpSgpr(2) as tmpSgprOffset:
1904+
module.add(self.argLoader.loadKernArg(tmpSgprOffset.idx, "KernArgAddress", sgprOffset=hex(self.states.batchOffsetDKernArgOffset), dword=2))
1905+
module.add(SWaitCnt(kmcnt=0, comment="Wait for the Matrix Address and Batch Offset Loads"))
1906+
module.add(SAddU32(dst=sgpr("AddressD+0"), src0=sgpr("AddressD+0"), src1=sgpr(tmpSgprOffset.idx), comment="add batch offset to D address (low)"))
1907+
module.add(SAddCU32(dst=sgpr("AddressD+1"), src0=sgpr("AddressD+1"), src1=sgpr(tmpSgprOffset.idx+1), comment="add batch offset to D address (high)"))
19041908

19051909
# Only load C buffer address if Beta is used and potentially non-zero
19061910
if kernel["ProblemType"]["UseBeta"]:
@@ -1913,9 +1917,13 @@ def loadBatchedAddress(self, kernel, Batch, tmpSgprResource: ContinuousRegister)
19131917
module.add(SMulI32(dst=sgpr(tmpSgpr), src0=sgpr(Batch), src1=0x8, comment="offset of global buffer address"))
19141918
module.add(SLoadB64(dst=sgpr("AddressC", 2), base=sgpr("AddressC",2), soffset=sgpr(tmpSgpr), comment="load global buffer C address"))
19151919
# Apply batch offset to AddressC for general batched mode
1916-
if not kernel["ProblemType"]["StridedBatched"] and not kernel["ProblemType"]["GroupedGemm"]:
1917-
module.add(SWaitCnt(kmcnt=0, comment="Wait for the Matrix Address Load from the Pointer Array before updating offset"))
1918-
module.add(SAddU64(dst=sgpr("AddressC", 2), src0=sgpr("AddressC", 2), src1=sgpr("BatchOffsetC", 2), comment="add batch offset to C address"))
1920+
# Load offset on-demand from kernel args (no persistent SGPRs needed)
1921+
if kernel["ProblemType"]["SupportUserArgs"] and not kernel["ProblemType"]["GroupedGemm"]:
1922+
with self.allocTmpSgpr(2) as tmpSgprOffset:
1923+
module.add(self.argLoader.loadKernArg(tmpSgprOffset.idx, "KernArgAddress", sgprOffset=hex(self.states.batchOffsetCKernArgOffset), dword=2))
1924+
module.add(SWaitCnt(kmcnt=0, comment="Wait for the Matrix Address and Batch Offset Loads"))
1925+
module.add(SAddU32(dst=sgpr("AddressC+0"), src0=sgpr("AddressC+0"), src1=sgpr(tmpSgprOffset.idx), comment="add batch offset to C address (low)"))
1926+
module.add(SAddCU32(dst=sgpr("AddressC+1"), src0=sgpr("AddressC+1"), src1=sgpr(tmpSgprOffset.idx+1), comment="add batch offset to C address (high)"))
19191927

19201928
module.add(endCheckLabel)
19211929

@@ -1935,11 +1943,19 @@ def loadBatchedAddress(self, kernel, Batch, tmpSgprResource: ContinuousRegister)
19351943
module.add(SLoadB64(dst=sgpr("AddressA", 2), base=sgpr("AddressA",2), soffset=sgpr(tmpSgpr), comment="load global buffer A address"))
19361944
module.add(SLoadB64(dst=sgpr("AddressB", 2), base=sgpr("AddressB",2), soffset=sgpr(tmpSgpr), comment="load global buffer B address"))
19371945
# Apply batch offset to AddressA and AddressB for general batched mode
1938-
if not kernel["ProblemType"]["StridedBatched"] and not kernel["ProblemType"]["GroupedGemm"]:
1939-
module.add(SWaitCnt(kmcnt=1, comment="Wait for the AddressA Load from the Pointer Array before updating offset"))
1940-
module.add(SAddU64(dst=sgpr("AddressA", 2), src0=sgpr("AddressA", 2), src1=sgpr("BatchOffsetA", 2), comment="add batch offset to A address"))
1941-
module.add(SWaitCnt(kmcnt=0, comment="Wait for the AddressB Load from the Pointer Array before updating offset"))
1942-
module.add(SAddU64(dst=sgpr("AddressB", 2), src0=sgpr("AddressB", 2), src1=sgpr("BatchOffsetB", 2), comment="add batch offset to B address"))
1946+
# Load offsets on-demand from kernel args (no persistent SGPRs needed)
1947+
if kernel["ProblemType"]["SupportUserArgs"] and not kernel["ProblemType"]["GroupedGemm"]:
1948+
with self.allocTmpSgpr(2) as tmpSgprOffset:
1949+
# Load and apply offset A
1950+
module.add(self.argLoader.loadKernArg(tmpSgprOffset.idx, "KernArgAddress", sgprOffset=hex(self.states.batchOffsetAKernArgOffset), dword=2))
1951+
module.add(SWaitCnt(kmcnt=1, comment="Wait for the AddressA Load from the Pointer Array"))
1952+
module.add(SAddU32(dst=sgpr("AddressA+0"), src0=sgpr("AddressA+0"), src1=sgpr(tmpSgprOffset.idx), comment="add batch offset to A address (low)"))
1953+
module.add(SAddCU32(dst=sgpr("AddressA+1"), src0=sgpr("AddressA+1"), src1=sgpr(tmpSgprOffset.idx+1), comment="add batch offset to A address (high)"))
1954+
# Load and apply offset B (reuse same tmpSgprOffset)
1955+
module.add(self.argLoader.loadKernArg(tmpSgprOffset.idx, "KernArgAddress", sgprOffset=hex(self.states.batchOffsetBKernArgOffset), dword=2))
1956+
module.add(SWaitCnt(kmcnt=0, comment="Wait for the AddressB and Batch Offset Loads"))
1957+
module.add(SAddU32(dst=sgpr("AddressB+0"), src0=sgpr("AddressB+0"), src1=sgpr(tmpSgprOffset.idx), comment="add batch offset to B address (low)"))
1958+
module.add(SAddCU32(dst=sgpr("AddressB+1"), src0=sgpr("AddressB+1"), src1=sgpr(tmpSgprOffset.idx+1), comment="add batch offset to B address (high)"))
19431959

19441960
module.add(endCheckLabel)
19451961

@@ -1966,17 +1982,22 @@ def getKernelArgLoadModule(self, kernel, sgprStartIdx, numsOfLoad, preloadNum):
19661982
sgprOffset += 4
19671983
self.argLoader.setOffset(sgprOffset)
19681984

1969-
# Load batch offset arguments for general batched mode
1970-
if not kernel["ProblemType"]["StridedBatched"] and not kernel["ProblemType"]["GroupedGemm"]:
1985+
# Batch offset arguments for general batched mode
1986+
# Store kernarg offsets for on-demand loading (no persistent SGPRs needed)
1987+
if kernel["ProblemType"]["SupportUserArgs"] and not kernel["ProblemType"]["GroupedGemm"]:
19711988
sgprOffset = self.argLoader.getOffset()
1972-
kernelArgs.add(self.argLoader.loadKernArg("BatchOffsetD", "KernArgAddress", sgprOffset=hex(sgprOffset), dword=2))
1989+
self.states.batchOffsetDKernArgOffset = sgprOffset
19731990
sgprOffset += 8 # 64-bit = 8 bytes
1974-
kernelArgs.add(self.argLoader.loadKernArg("BatchOffsetC", "KernArgAddress", sgprOffset=hex(sgprOffset), dword=2))
1991+
self.states.batchOffsetCKernArgOffset = sgprOffset
19751992
sgprOffset += 8
1976-
kernelArgs.add(self.argLoader.loadKernArg("BatchOffsetA", "KernArgAddress", sgprOffset=hex(sgprOffset), dword=2))
1993+
self.states.batchOffsetAKernArgOffset = sgprOffset
19771994
sgprOffset += 8
1978-
kernelArgs.add(self.argLoader.loadKernArg("BatchOffsetB", "KernArgAddress", sgprOffset=hex(sgprOffset), dword=2))
1995+
self.states.batchOffsetBKernArgOffset = sgprOffset
19791996
sgprOffset += 8
1997+
self.argLoader.setOffset(sgprOffset)
1998+
# Debug: write kernel arg offsets to file for verification
1999+
with open("/tmp/kernel_batch_offset_debug.txt", "a") as f:
2000+
f.write(f"{self.states.kernelName}: D@{self.states.batchOffsetDKernArgOffset}, C@{self.states.batchOffsetCKernArgOffset}, A@{self.states.batchOffsetAKernArgOffset}, B@{self.states.batchOffsetBKernArgOffset}\n")
19802001

19812002
return kernelArgs
19822003

@@ -4424,7 +4445,15 @@ def computeLoadSrd(self, kernel, tP, tc, indices, bpe):
44244445
moduleLoadGeneralBatch.add(SAddU32(dst=sgpr(stmp+0), src0=sgpr(stmp+0), src1=sgpr("Address%s+0"%tc), comment="Offsetting to the location [Lower half of address]"))
44254446
moduleLoadGeneralBatch.add(SAddCU32(dst=sgpr(stmp+1), src0=sgpr("Address%s+1"%tc), src1=0, comment="Offsetting to the location [Higher half of address]"))
44264447
moduleLoadGeneralBatch.add(SLoadB64(dst=sgpr("Srd%s"%tc, 2), base=sgpr(stmp, 2), soffset=0, comment="Load the Matrix Address in the Pointer Array"))
4427-
moduleLoadGeneralBatch.add(SWaitCnt(kmcnt=0, comment="Wait for the Matrix Address Load from the Pointer Array"))
4448+
# Load and apply batch offset for General Batched GEMM
4449+
if kernel["ProblemType"]["SupportUserArgs"] and not kernel["ProblemType"]["GroupedGemm"]:
4450+
batchOffsetKernArgOffset = self.states.batchOffsetAKernArgOffset if tc == "A" else self.states.batchOffsetBKernArgOffset
4451+
moduleLoadGeneralBatch.add(SLoadB64(dst=sgpr(stmp, 2), base=sgpr("KernArgAddress", 2), soffset=hex(batchOffsetKernArgOffset), comment="Load batchOffset%s from kernel args"%tc))
4452+
moduleLoadGeneralBatch.add(SWaitCnt(kmcnt=0, comment="Wait for Matrix Address and Batch Offset Loads"))
4453+
moduleLoadGeneralBatch.add(SAddU32(dst=sgpr("Srd%s+0"%tc), src0=sgpr("Srd%s+0"%tc), src1=sgpr(stmp+0), comment="Add batch offset to %s address (low)"%tc))
4454+
moduleLoadGeneralBatch.add(SAddCU32(dst=sgpr("Srd%s+1"%tc), src0=sgpr("Srd%s+1"%tc), src1=sgpr(stmp+1), comment="Add batch offset to %s address (high)"%tc))
4455+
else:
4456+
moduleLoadGeneralBatch.add(SWaitCnt(kmcnt=0, comment="Wait for the Matrix Address Load from the Pointer Array"))
44284457
if self.states.groOffsetInMacroTile and ((tc == "A" and not kernel["enableTDMA"]) or (tc == "B" and not kernel["enableTDMB"])):
44294458
prePad1 = int(self.states.srdShiftLeft[tc] * tP["bpeGR"]) # leave room in case we have to pointer shift
44304459
moduleLoadGeneralBatch.add(SSubU32(dst=sgpr("Srd%s+0"%tc), src0=sgpr("Srd%s+0"%tc), src1=prePad1, comment="pre-pad to make room for possible pointer shift"))
@@ -12422,9 +12451,18 @@ def computeStoreSrdStart(self, kernel, srdTcList: list, sgprBpeList = [], useSiz
1242212451
module.add(SAddU32(dst=sgpr(tmpS0), src0=sgpr(tmpS0), src1=sgpr("Address%s+0"%mat), comment="Offsetting to the location [Lower half of address]"))
1242312452
module.add(SAddCU32(dst=sgpr(tmpS1), src0=sgpr("Address%s+1"%mat), src1=0, comment="Offsetting to the location [Higher half of address]"))
1242412453
module.add(SLoadB64(dst=sgpr(tmpS0, 2), base=sgpr(tmpS0, 2), soffset=0, comment="Load the Matrix Address in the Pointer Array"))
12425-
module.add(SWaitCnt(kmcnt=0, comment="Wait for the Matrix Address Load from the Pointer Array"))
12426-
module.add(SAddU32(dst=sgpr("Srd%s+0"%mat), src0=sgpr("Srd%s+0"%mat), src1=sgpr(tmpS0), comment="Offsetting within the Batch Matrix [Lower half of address]"))
12427-
module.add(SAddCU32(dst=sgpr("Srd%s+1"%mat), src0=sgpr("Srd%s+1"%mat), src1=sgpr(tmpS1), comment="Offsetting within the Batch Matrix [Higher half of address]"))
12454+
# Load and apply batch offset for General Batched GEMM (C or D matrix)
12455+
if kernel["ProblemType"]["SupportUserArgs"] and not kernel["ProblemType"]["GroupedGemm"]:
12456+
batchOffsetKernArgOffset = self.states.batchOffsetCKernArgOffset if mat == "C" else self.states.batchOffsetDKernArgOffset
12457+
module.add(SLoadB64(dst=sgpr("Srd%s"%mat, 2), base=sgpr("KernArgAddress", 2), soffset=hex(batchOffsetKernArgOffset), comment="Load batchOffset%s from kernel args"%mat))
12458+
module.add(SWaitCnt(kmcnt=0, comment="Wait for Matrix Address and Batch Offset Loads"))
12459+
# Add loaded matrix address to SRD
12460+
module.add(SAddU32(dst=sgpr("Srd%s+0"%mat), src0=sgpr("Srd%s+0"%mat), src1=sgpr(tmpS0), comment="Add matrix address to SRD (low)"))
12461+
module.add(SAddCU32(dst=sgpr("Srd%s+1"%mat), src0=sgpr("Srd%s+1"%mat), src1=sgpr(tmpS1), comment="Add matrix address to SRD (high)"))
12462+
else:
12463+
module.add(SWaitCnt(kmcnt=0, comment="Wait for the Matrix Address Load from the Pointer Array"))
12464+
module.add(SAddU32(dst=sgpr("Srd%s+0"%mat), src0=sgpr("Srd%s+0"%mat), src1=sgpr(tmpS0), comment="Offsetting within the Batch Matrix [Lower half of address]"))
12465+
module.add(SAddCU32(dst=sgpr("Srd%s+1"%mat), src0=sgpr("Srd%s+1"%mat), src1=sgpr(tmpS1), comment="Offsetting within the Batch Matrix [Higher half of address]"))
1242812466
module.add(generalBatchedGemmLoad_End)
1242912467
module.addSpaceLine()
1243012468

0 commit comments

Comments
 (0)