Files
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

186 lines
8.0 KiB
C++

// Copyright Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_string.hpp>
#include "TestContext.hpp"
#include <common/CommonGraphs.hpp>
#include <rocRoller/DataTypes/DataTypes.hpp>
#include <rocRoller/KernelGraph/KernelGraph.hpp>
#include <rocRoller/KernelGraph/Transforms/All.hpp>
#include <rocRoller/KernelGraph/Utils.hpp>
TEST_CASE("StreamK multiple fix-ups", "[streamk][kernel-graph]")
{
using namespace rocRoller;
using namespace KernelGraph;
using namespace ControlGraph;
using namespace CoordinateGraph;
auto context = TestContext::ForTestDevice();
auto example = rocRollerTest::Graphs::GEMM(DataType::Float);
example.setTileSize(128, 256, 8);
example.setMFMA(32, 32, 2, 1);
example.setUseLDS(false, false, false);
example.setPrefetch(false, 0, 0, false);
auto numWGs = example.getFlattenedWorkgroupSize();
auto numWGsExpr = std::make_shared<Expression::Expression>(numWGs);
// Verify the control graph matches the pseudocode
// if ReceiveTile
// for ReceiveTileLoop
// Assert(WG + forReceiveTileLoopCoord + 1 < numWGs)
// DoWhile
// LoadSGPR(flag[WG + forReceiveTileLoopCoord + 1])
// for XLoop and YLoop
// partialResult = LoadTiled(scratchAccTile[WG + forReceiveTileLoopCoord + 1])
// fullyAccTile = Assign(localPartiallyAccTile)
// fullyAccTile = Assign Add(fullyAccTile, partialResult)
// localAccTile = Assign(fullyAccTile)
// WaitZero()
auto verifyStreamKReceiveTileLoop = [](rocRoller::KernelGraph::KernelGraph const& kgraph) {
auto forLoopTags = kgraph.control.getNodes<ForLoopOp>().to<std::vector>();
auto receiveTileLoopTag = -1;
// verify there is only 1 fixup for-loop
for(const auto tag : forLoopTags)
{
auto forLoopOp = kgraph.control.get<ForLoopOp>(tag);
if(forLoopOp->loopName == rocRoller::RECEIVE)
{
CHECK(receiveTileLoopTag == -1);
receiveTileLoopTag = tag;
}
}
CHECK(receiveTileLoopTag != -1);
// verify the for-loop is under the receive tile condition
auto receiveTileCondTag = -1;
auto parent = only(kgraph.control.getInputNodeIndices<Body>(receiveTileLoopTag));
CHECK(parent.has_value());
receiveTileCondTag = parent.value();
CHECK(kgraph.control.get<ConditionalOp>(receiveTileCondTag).has_value());
// verify there is onlyl 1 for-XLoop and for-YLoop under the fixup for-loop
auto isForXLoopPredicate = [&](int tag) -> bool {
auto maybeForLoop = kgraph.control.get<ForLoopOp>(tag);
if(maybeForLoop.has_value())
return maybeForLoop->loopName == rocRoller::XLOOP;
return false;
};
auto isForYLoopPredicate = [&](int tag) -> bool {
auto maybeForLoop = kgraph.control.get<ForLoopOp>(tag);
if(maybeForLoop.has_value())
return maybeForLoop->loopName == rocRoller::YLOOP;
return false;
};
auto fixupXLoop = only(kgraph.control.findNodes(receiveTileLoopTag, isForXLoopPredicate));
auto fixupYLoop = only(kgraph.control.findNodes(receiveTileLoopTag, isForYLoopPredicate));
CHECK(fixupXLoop.has_value());
CHECK(fixupYLoop.has_value());
// verify this sequence chain: LoadTiled -> Assign -> AssignAdd -> Assign
auto loadPartialResult
= only(kgraph.control.getOutputNodeIndices<Body>(fixupYLoop.value()));
CHECK(loadPartialResult.has_value());
CHECK(kgraph.control.get<LoadTiled>(loadPartialResult.value()).has_value());
auto assignAccTile
= only(kgraph.control.getOutputNodeIndices<Sequence>(loadPartialResult.value()));
CHECK(assignAccTile.has_value());
CHECK(kgraph.control.get<Assign>(assignAccTile.value()).has_value());
auto assignAdd = only(kgraph.control.getOutputNodeIndices<Sequence>(assignAccTile.value()));
CHECK(assignAdd.has_value());
CHECK(kgraph.control.get<Assign>(assignAdd.value()).has_value());
auto assignResultTile
= only(kgraph.control.getOutputNodeIndices<Sequence>(assignAdd.value()));
CHECK(assignResultTile.has_value());
CHECK(kgraph.control.get<Assign>(assignResultTile.value()).has_value());
// verify the mapper connection and expression
auto getTileTag = [&](int assignTag) -> int {
auto op = kgraph.control.getNode<Assign>(assignTag);
return std::get<Expression::DataFlowTag>(*op.expression).tag;
};
auto partialResultTileTag = kgraph.mapper.get<MacroTile>(loadPartialResult.value());
auto accTileTag = getTileTag(assignAccTile.value());
auto assignAccTileDestTag = getDEST(kgraph, assignAccTile.value());
auto [assignAddLHSTag, assignAddLHSExpr]
= getBinaryLHS<Expression::Add>(kgraph, assignAdd.value());
auto [assignAddRHSTag, assignAddRHSExpr]
= getBinaryRHS<Expression::Add>(kgraph, assignAdd.value());
auto assignAddDest = getDEST(kgraph, assignAdd.value());
auto resultTileTag = getTileTag(assignResultTile.value());
auto assignResultTileDest = getDEST(kgraph, assignResultTile.value());
CHECK(assignResultTileDest == accTileTag);
CHECK(assignAccTileDestTag == resultTileTag);
CHECK(assignAddDest == resultTileTag);
auto isLHS = partialResultTileTag == assignAddLHSTag;
auto isRHS = partialResultTileTag == assignAddRHSTag;
CHECK((isLHS || isRHS));
if(isLHS)
{
CHECK(assignAddRHSTag == resultTileTag);
}
if(isRHS)
{
CHECK(assignAddLHSTag == resultTileTag);
}
};
auto applyGraphTransforms
= [&numWGsExpr, &context](CommandParametersPtr params,
rocRoller::KernelGraph::KernelGraph& kgraph) {
std::vector<GraphTransformPtr> transforms;
transforms.push_back(std::make_shared<IdentifyParallelDimensions>());
transforms.push_back(std::make_shared<OrderMemory>(false));
transforms.push_back(std::make_shared<UpdateParameters>(params));
transforms.push_back(std::make_shared<AddLDS>(params, context.get()));
transforms.push_back(std::make_shared<LowerLinear>(context.get()));
transforms.push_back(std::make_shared<LowerTile>(params, context.get()));
transforms.push_back(std::make_shared<LowerTensorContraction>(params, context.get()));
transforms.push_back(std::make_shared<Simplify>());
transforms.push_back(std::make_shared<FuseExpressions>());
transforms.push_back(std::make_shared<AddStreamK>(
context.get(), params, rocRoller::XLOOP, rocRoller::KLOOP, numWGsExpr));
for(auto& t : transforms)
kgraph = kgraph.transform(t);
};
SECTION("Standard StreamK Multiple Fixups")
{
example.setStreamK(StreamKMode::Standard);
auto kgraph = example.getKernelGraph();
auto params = example.getCommandParameters();
applyGraphTransforms(params, kgraph);
verifyStreamKReceiveTileLoop(kgraph);
}
SECTION("TwoTile StreamK Multiple Fixups")
{
example.setStreamK(StreamKMode::TwoTile);
auto kgraph = example.getKernelGraph();
auto params = example.getCommandParameters();
applyGraphTransforms(params, kgraph);
verifyStreamKReceiveTileLoop(kgraph);
}
SECTION("TwoTileDPFirst StreamK Multiple Fixups")
{
example.setStreamK(StreamKMode::TwoTileDPFirst);
auto kgraph = example.getKernelGraph();
auto params = example.getCommandParameters();
applyGraphTransforms(params, kgraph);
verifyStreamKReceiveTileLoop(kgraph);
}
}