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
335 lines
11 KiB
Python
335 lines
11 KiB
Python
################################################################################
|
|
#
|
|
# Copyright (C) 2020-2022 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 Tensile.Utilities.merge import cmpHelper, fixSizeInconsistencies, removeUnusedKernels, mergeLogic
|
|
from Tensile.Utilities.ConditionalImports import yamlLoader
|
|
|
|
import yaml, pytest
|
|
|
|
# the merge scripts does not differentiate solutions based on index or name
|
|
# so "DummyParam" is used to mark if solutions should be equal or not
|
|
|
|
logicPrefix = r"""
|
|
- DummyVersionRequirement
|
|
- DummyLanguage
|
|
- DummyScheduleName
|
|
- DummyDevice
|
|
- DummyProblemType
|
|
"""
|
|
|
|
baseLogic=logicPrefix + r"""
|
|
-
|
|
- SolutionIndex: 2
|
|
SolutionNameMin: InUseForSize256
|
|
DummyParam: InUseForSize256
|
|
- SolutionIndex: 1
|
|
SolutionNameMin: UnusedSolution
|
|
DummyParam: UnusedSolution
|
|
- SolutionIndex: 0
|
|
SolutionNameMin: InUseForSize128or64
|
|
DummyParam: InUseForSize128or64
|
|
- DummyIndexAssignment
|
|
-
|
|
- - [256, 256, 1, 256]
|
|
- [2, 111.1]
|
|
- - [128, 128, 1, 128]
|
|
- [0, 99.9]
|
|
- - [64, 64, 1, 64]
|
|
- [0, 88.8]
|
|
"""
|
|
|
|
incLogic=logicPrefix + r"""
|
|
-
|
|
- SolutionIndex: 39
|
|
SolutionNameMin: InUseForSize256or1024xxx
|
|
DummyParam: InUseForSize256or1024xxx
|
|
- SolutionIndex: 1
|
|
SolutionNameMin: InUseForSize128xxx
|
|
DummyParam: InUseForSize128xxx
|
|
- DummyIndexAssignment
|
|
-
|
|
- - [128, 128, 1, 128]
|
|
- [1, 999.9]
|
|
- - [256, 256, 1, 256]
|
|
- [39, 999.9]
|
|
- - [1024, 1024, 1, 1024]
|
|
- [39, 999.9]
|
|
"""
|
|
|
|
notUniqueSolution=logicPrefix+r"""
|
|
-
|
|
- SolutionIndex: 0
|
|
SolutionNameMin: Kernel0
|
|
DummyParam: Kernel0
|
|
- SolutionIndex: 1
|
|
SolutionNameMin: Kernel0
|
|
DummyParam: Kernel0
|
|
"""
|
|
|
|
uniqueSolution=logicPrefix+r"""
|
|
-
|
|
- SolutionIndex: 0
|
|
SolutionNameMin: Kernel0
|
|
DummyParam: Kernel0
|
|
- SolutionIndex: 1
|
|
SolutionNameMin: Kernel1
|
|
DummyParam: Kernel1
|
|
"""
|
|
|
|
notTrimmedSize=r"""
|
|
-
|
|
- - [128, 128, 1, 128, 128, 128, 128, 128]
|
|
- [1, 999.9]
|
|
- - [1024, 1024, 1, 1024]
|
|
- [42, 0.0]
|
|
- - [128, 128, 1, 128]
|
|
- [39, 0.0]
|
|
- - [1024, 1024, 1, 1024, 1024, 1024, 1024, 1024]
|
|
- [39, 999.9]
|
|
- - [1024, 1024, 1, 1024, 1044, 1044, 1044, 1044]
|
|
- [39, 999.9]
|
|
"""
|
|
|
|
trimmedSize=r"""
|
|
-
|
|
- - [128, 128, 1, 128]
|
|
- [1, 999.9]
|
|
- - [512, 512, 1, 512]
|
|
- [39, 999.9]
|
|
- - [1024, 1024, 1, 1024]
|
|
- [42, 999.9]
|
|
"""
|
|
|
|
mfmaMergeBaseLogic=logicPrefix+r"""
|
|
-
|
|
- SolutionIndex: 0
|
|
SolutionNameMin: MFMA_base
|
|
DummyParam: MFMA_base
|
|
EnableMatrixInstruction: True
|
|
MatrixInstruction: [16, 16, 4, 1]
|
|
- SolutionIndex: 1
|
|
SolutionNameMin: VALU_base
|
|
DummyParam: VALU_base
|
|
EnableMatrixInstruction: False
|
|
MatrixInstruction: []
|
|
- DummyIndexAssignment
|
|
"""
|
|
|
|
mfmaMergeIncLogic=logicPrefix+r"""
|
|
-
|
|
- SolutionIndex: 0
|
|
SolutionNameMin: MFMA_inc
|
|
DummyParam: MFMA_inc
|
|
EnableMatrixInstruction: True
|
|
MatrixInstruction: [16, 16, 4, 1]
|
|
- SolutionIndex: 1
|
|
SolutionNameMin: VALU_inc
|
|
DummyParam: VALU_inc
|
|
EnableMatrixInstruction: False
|
|
MatrixInstruction: []
|
|
- DummyIndexAssignment
|
|
"""
|
|
|
|
mfmaMergeBaseSizes=r"""
|
|
-
|
|
- - [128, 128, 1, 128]
|
|
- [0, 3.0]
|
|
- - [128, 128, 1, 128]
|
|
- [1, 6.0]
|
|
- - [130, 128, 1, 128]
|
|
- [1, 9.0]
|
|
- - [131, 128, 1, 128]
|
|
- [0, 12.0]
|
|
"""
|
|
|
|
mfmaMergeIncFasterSizes=r"""
|
|
-
|
|
- - [128, 128, 1, 128]
|
|
- [0, 4.0]
|
|
- - [128, 128, 1, 128]
|
|
- [1, 7.0]
|
|
- - [131, 128, 1, 128]
|
|
- [0, 13.0]
|
|
- - [130, 128, 1, 128]
|
|
- [1, 10.0]
|
|
"""
|
|
|
|
mfmaMergeIncSlowerSizes=r"""
|
|
-
|
|
- - [128, 128, 1, 128]
|
|
- [0, 2.0]
|
|
- - [128, 128, 1, 128]
|
|
- [1, 5.0]
|
|
- - [131, 128, 1, 128]
|
|
- [0, 11.0]
|
|
- - [130, 128, 1, 128]
|
|
- [1, 8.0]
|
|
"""
|
|
|
|
mfmaMergeIncNotMatchingMFMA=r"""
|
|
-
|
|
- - [130, 128, 1, 128]
|
|
- [0, 7.0]
|
|
- - [131, 128, 1, 128]
|
|
- [1, 12.0]
|
|
"""
|
|
|
|
mfmaMergeResNotMatchingMFMA=r"""
|
|
-
|
|
- - [128, 128, 1, 128]
|
|
- [0, 3.0]
|
|
- - [128, 128, 1, 128]
|
|
- [1, 6.0]
|
|
- - [130, 128, 1, 128]
|
|
- [1, 9.0]
|
|
- - [131, 128, 1, 128]
|
|
- [0, 12.0]
|
|
- - [130, 128, 1, 128]
|
|
- [2, 7.0]
|
|
- - [131, 128, 1, 128]
|
|
- [3, 12.0]
|
|
"""
|
|
|
|
def checkUniqueSolution(solutionPool):
|
|
uniq = set()
|
|
# note: any([False or None, True or None]) -> True
|
|
return not any(frozenset(cmpHelper(i).items()) in uniq or uniq.add(frozenset(cmpHelper(i).items()))
|
|
for i in solutionPool)
|
|
|
|
@pytest.mark.parametrize("sizes, expected", [
|
|
( trimmedSize, [[128,128,1,128],[512,512,1,512],[1024,1024,1,1024]]),
|
|
(notTrimmedSize, [[1024,1024,1,1024],[128,128,1,128]])
|
|
])
|
|
def test_fixSizeInconsistencies(sizes, expected):
|
|
data = yaml.load(sizes, yamlLoader)
|
|
data_ = fixSizeInconsistencies(data[0], "dummy")
|
|
|
|
for [size, [_,_]], expected_ in zip(data_[0], expected):
|
|
assert size == expected_
|
|
|
|
@pytest.mark.parametrize("input,expectedNumKernelRemoved", [(baseLogic, 1),
|
|
(incLogic, 0)])
|
|
def test_removeUnusedKernels(input, expectedNumKernelRemoved):
|
|
data = yaml.load(input, yamlLoader)
|
|
dataFiltered, numKernelRemoved = removeUnusedKernels(data)
|
|
|
|
# test if number of solution removed is correct
|
|
assert numKernelRemoved == expectedNumKernelRemoved
|
|
|
|
# test if solution is re-indexed
|
|
for index, s in enumerate(dataFiltered[5]):
|
|
assert index == s["SolutionIndex"]
|
|
|
|
# check if size-kernel mapping is not compromised
|
|
solutionMapBefore = {}
|
|
solutionMapAfter = {}
|
|
for [size, [index, _]] in data[7]:
|
|
solutionMapBefore[tuple(size)] = [s["SolutionNameMin"] for s in data[5] if s["SolutionIndex"]==index][0]
|
|
for [size, [index, _]] in dataFiltered[7]:
|
|
solutionMapAfter[tuple(size)] = [s["SolutionNameMin"] for s in dataFiltered[5] if s["SolutionIndex"]==index][0]
|
|
|
|
assert solutionMapBefore == solutionMapAfter
|
|
|
|
# print final yaml for visual inspection
|
|
# stream = io.StringIO("")
|
|
# yaml.safe_dump(dataFiltered, stream, default_flow_style=None)
|
|
# print(stream.getvalue())
|
|
|
|
@pytest.mark.parametrize("baseLogic, incLogic, expectedStats, expectedSizes, expectedSolutions", [
|
|
# test case #1: merge incLogic into baseLogic
|
|
(baseLogic, incLogic, [1,2,2], # 1 sizes added, 2 kernels added, 2 kernels removed/replaced
|
|
[(1024,1024,1,1024), (256,256,1,256), (128,128,1,128), (64,64,1,64)],
|
|
["InUseForSize256or1024xxx", "InUseForSize256or1024xxx", "InUseForSize128xxx", "InUseForSize128or64"]),
|
|
# test case #2: merge baseLogic into itself
|
|
(baseLogic, baseLogic, [0,0,1], # 0 sizes added, 0 kernels added, 1 kernel removed because it's unused
|
|
[(256,256,1,256), (128,128,1,128), (64,64,1,64)],
|
|
["InUseForSize256", "InUseForSize128or64", "InUseForSize128or64"]),
|
|
])
|
|
def test_mergeLogic(baseLogic, incLogic, expectedStats, expectedSizes, expectedSolutions):
|
|
baseData = yaml.load(baseLogic, yamlLoader)
|
|
incData = yaml.load(incLogic, yamlLoader)
|
|
|
|
mergedData, *stats = mergeLogic(baseData, incData, False)
|
|
|
|
# check if stats are as expected
|
|
assert stats == expectedStats
|
|
|
|
# check if solution matches expected. assumes SolutionNameMin is uniqueSolution
|
|
# (which is satisfied by the test data given here)
|
|
solutionMap = {} # size -> solutionName
|
|
for size, [index, _] in mergedData[7]:
|
|
solutionMap[tuple(size)] = [s["SolutionNameMin"] for s in mergedData[5] if s["SolutionIndex"]==index][0]
|
|
|
|
for size, expected in zip(expectedSizes, expectedSolutions):
|
|
assert solutionMap[size] == expected
|
|
|
|
# check if each solution in merged data is uniqueSolution
|
|
assert checkUniqueSolution(mergedData[5])
|
|
|
|
@pytest.mark.parametrize("input,expected", [(uniqueSolution, True), (notUniqueSolution, False)])
|
|
def test_checkUniqueSolution(input, expected):
|
|
data = yaml.load(input, yamlLoader)
|
|
assert checkUniqueSolution(data[5]) == expected
|
|
|
|
@pytest.mark.parametrize("baseLogic, incLogic, expectedSizesYaml, expectedSolutions", [
|
|
# test case #1: Slower sizes in incremental logic file
|
|
(mfmaMergeBaseLogic+mfmaMergeBaseSizes, mfmaMergeIncLogic+mfmaMergeIncSlowerSizes,
|
|
mfmaMergeBaseSizes, ["MFMA_base", "VALU_base"]),
|
|
# test case #2: Faster sizes in incremental logic file
|
|
(mfmaMergeBaseLogic+mfmaMergeBaseSizes, mfmaMergeIncLogic+mfmaMergeIncFasterSizes,
|
|
mfmaMergeIncFasterSizes, ["MFMA_inc", "VALU_inc"]),
|
|
# test case #3: Test that VALU size is included alongside MFMA size, and vice versa (regardless of efficiency)
|
|
(mfmaMergeBaseLogic+mfmaMergeBaseSizes, mfmaMergeIncLogic+mfmaMergeIncNotMatchingMFMA,
|
|
mfmaMergeResNotMatchingMFMA, ["MFMA_base", "VALU_base", "MFMA_inc", "VALU_inc"])
|
|
])
|
|
def test_mfmaMergeLogic(baseLogic, incLogic, expectedSizesYaml, expectedSolutions):
|
|
baseData = yaml.load(baseLogic, yamlLoader)
|
|
incData = yaml.load(incLogic, yamlLoader)
|
|
expectedSizes = yaml.load(expectedSizesYaml, yamlLoader)[0]
|
|
|
|
mergedData, _, _, _ = mergeLogic(baseData, incData, False, True, True)
|
|
|
|
solutionIndices = {s['SolutionNameMin']: s['SolutionIndex'] for s in mergedData[5]} # size -> solutionName
|
|
|
|
#Ensure all correct solutions are present in merged data
|
|
for solution in expectedSolutions:
|
|
assert solution in solutionIndices.keys()
|
|
|
|
assert len(expectedSolutions) == len(mergedData[5])
|
|
|
|
#Convert expected sizes to use mergedData's solution indices
|
|
expectedSizes = [ [size, [solutionIndices[expectedSolutions[solIndex]], eff]] for size, [solIndex, eff] in expectedSizes ]
|
|
|
|
#Ensure all expected sizes are present in merged data
|
|
for item in expectedSizes:
|
|
assert item in mergedData[7]
|
|
|
|
assert len(expectedSizes) == len(mergedData[7])
|
|
|
|
if __name__ == "__main__":
|
|
# test_mergeLogic(baseLogic, incLogic, [1,2,2], [(1024, 1024, 1, 1024), (256, 256, 1, 256), (128, 128, 1, 128), (64, 64, 1, 64)], [ "InUseForSize256or1024xxx", "InUseForSize256or1024xxx", "InUseForSize128xxx", "InUseForSize128or64"])
|
|
# test_checkUniqueSolution(uniqueSolution, True)
|
|
# test_fixSizeInconsistencies(trimmedSize, [[128,128,1,128],[512,512,1,512],[1024,1024,1,1024]])
|
|
test_fixSizeInconsistencies(notTrimmedSize, [[1024,1024,1,1024],[128,128,1,128]])
|