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
275 lines
12 KiB
C++
275 lines
12 KiB
C++
// Copyright Advanced Micro Devices, Inc., or its affiliates.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#include <rocRoller/Expression.hpp>
|
|
#include <rocRoller/KernelGraph/KernelGraph.hpp>
|
|
#include <rocRoller/KernelGraph/Transforms/RemoveSetCoordinate.hpp>
|
|
#include <rocRoller/Scheduling/Scheduler.hpp>
|
|
#include <rocRoller/Utilities/Utils.hpp>
|
|
|
|
#include "GenericContextFixture.hpp"
|
|
#include "SourceMatcher.hpp"
|
|
|
|
using namespace rocRoller;
|
|
using namespace rocRoller::KernelGraph;
|
|
using namespace rocRoller::KernelGraph::ControlGraph;
|
|
using namespace rocRoller::KernelGraph::CoordinateGraph;
|
|
|
|
namespace ScopeTest
|
|
{
|
|
class ScopeTest : public GenericContextFixture,
|
|
public ::testing::WithParamInterface<Scheduling::SchedulerProcedure>
|
|
{
|
|
void SetUp() override
|
|
{
|
|
Settings::getInstance()->set(Settings::AllowUnknownInstructions, true);
|
|
GenericContextFixture::SetUp();
|
|
}
|
|
};
|
|
|
|
TEST_P(ScopeTest, ScopeOperation)
|
|
{
|
|
auto kgraph = rocRoller::KernelGraph::KernelGraph();
|
|
|
|
int dst1 = kgraph.coordinates.addElement(VGPR());
|
|
int dst2 = kgraph.coordinates.addElement(VGPR());
|
|
int dst3 = kgraph.coordinates.addElement(VGPR());
|
|
|
|
int kernel = kgraph.control.addElement(Kernel());
|
|
|
|
int scope1 = kgraph.control.addElement(Scope());
|
|
int scope2 = kgraph.control.addElement(Scope());
|
|
|
|
int assign1
|
|
= kgraph.control.addElement(Assign{Register::Type::Vector, Expression::literal(11u)});
|
|
int assign2
|
|
= kgraph.control.addElement(Assign{Register::Type::Vector, Expression::literal(22u)});
|
|
int assign3
|
|
= kgraph.control.addElement(Assign{Register::Type::Vector, Expression::literal(33u)});
|
|
int assign4
|
|
= kgraph.control.addElement(Assign{Register::Type::Vector, Expression::literal(44u)});
|
|
|
|
kgraph.mapper.connect(assign1, dst1, NaryArgument::DEST);
|
|
kgraph.mapper.connect(assign2, dst2, NaryArgument::DEST);
|
|
kgraph.mapper.connect(assign3, dst3, NaryArgument::DEST);
|
|
kgraph.mapper.connect(assign4, dst1, NaryArgument::DEST);
|
|
|
|
// kernel(base scope):
|
|
// - assign vector: 11u
|
|
// - scope1:
|
|
// - scope2:
|
|
// - assign vector: 33u
|
|
// - assign vector: 44u, using pre-existing vector
|
|
// - assign vector: 22u
|
|
kgraph.control.addElement(Body(), {kernel}, {assign1});
|
|
kgraph.control.addElement(Sequence(), {assign1}, {scope1});
|
|
kgraph.control.addElement(Body(), {scope1}, {scope2});
|
|
kgraph.control.addElement(Body(), {scope2}, {assign3});
|
|
kgraph.control.addElement(Sequence(), {assign3}, {assign4});
|
|
kgraph.control.addElement(Sequence(), {scope2}, {assign2});
|
|
|
|
kgraph = kgraph.transform(std::make_shared<RemoveSetCoordinate>());
|
|
|
|
auto sched = GetParam();
|
|
Settings::getInstance()->set(Settings::Scheduler, sched);
|
|
|
|
m_context->schedule(generate(kgraph, m_context->kernel()));
|
|
|
|
// assign1 should be to v0, which is deallocated before the end of the kernel
|
|
// assign2 should be to v1, which is deallocated
|
|
// assign3 should be to v1, which is deallocated
|
|
|
|
// TODO: Rewrite ScopeTest test using the register allocation state
|
|
// instead of comments so it's less fragile.
|
|
|
|
if(sched == Scheduling::SchedulerProcedure::Sequential)
|
|
{
|
|
auto kexpected = R"(
|
|
// CodeGeneratorVisitor::generate() begin
|
|
// RemoveSetCoordinate
|
|
// generate({1})
|
|
// Kernel(1) BEGIN
|
|
// (op 1) generate({})
|
|
// (op 1) end: generate({})
|
|
// (op 1) generate({4})
|
|
// (op 1) Assign VGPR 11:U32(4) BEGIN
|
|
// (op 4) Assign dim(1) = 11:U32
|
|
// tag 1: v**UNALLOCATED**
|
|
// (op 4) Generate 11:U32 into DataFlowTag1: VGPR Value: UInt32 x 1: (unallocated)
|
|
// Allocated DataFlowTag1: 1 VGPR (Value: UInt32) (op 4): v0
|
|
v_mov_b32 v0, 11 // (op 4) call()
|
|
// (op 1) Assign VGPR 11:U32(4) END
|
|
// (op 1) Scope(2) BEGIN
|
|
// (op 2) Lock Scope 2
|
|
// Lock Branch
|
|
// (op 2) generate({3})
|
|
// (op 2) Scope(3) BEGIN
|
|
// (op 3) Lock Scope 3
|
|
// Lock Branch
|
|
// (op 3) generate({6})
|
|
// (op 3) Assign VGPR 33:U32(6) BEGIN
|
|
// (op 6) Assign dim(3) = 33:U32
|
|
// tag 3: v**UNALLOCATED**
|
|
// (op 6) Generate 33:U32 into DataFlowTag3: VGPR Value: UInt32 x 1: (unallocated)
|
|
// Allocated DataFlowTag3: 1 VGPR (Value: UInt32) (op 6): v1
|
|
v_mov_b32 v1, 33 // (op 6) call()
|
|
// (op 3) Assign VGPR 33:U32(6) END
|
|
// (op 3) Assign VGPR 44:U32(7) BEGIN
|
|
// (op 7) Assign dim(1) = 44:U32
|
|
// (op 7) Generate 44:U32 into DataFlowTag1: VGPR Value: UInt32 x 1: v0
|
|
v_mov_b32 v0, 44 // (op 7) call()
|
|
// (op 3) Assign VGPR 44:U32(7) END
|
|
// (op 3) end: generate({6})
|
|
// Freeing DataFlowTag3: 1 VGPR (Value: UInt32) (op 6): v1
|
|
// Deleting tag 3
|
|
// (op 3) Unlock Scope 3
|
|
// Unlock None
|
|
// (op 2) Scope(3) END
|
|
// (op 2) Assign VGPR 22:U32(5) BEGIN
|
|
// (op 5) Assign dim(2) = 22:U32
|
|
// tag 2: v**UNALLOCATED**
|
|
// (op 5) Generate 22:U32 into DataFlowTag2: VGPR Value: UInt32 x 1: (unallocated)
|
|
// Allocated DataFlowTag2: 1 VGPR (Value: UInt32) (op 5): v1
|
|
v_mov_b32 v1, 22 // (op 5) call()
|
|
// (op 2) Assign VGPR 22:U32(5) END
|
|
// (op 2) end: generate({3})
|
|
// Freeing DataFlowTag2: 1 VGPR (Value: UInt32) (op 5): v1
|
|
// Deleting tag 2
|
|
// (op 2) Unlock Scope 2
|
|
// Unlock None
|
|
// (op 1) Scope(2) END
|
|
// (op 1) end: generate({4})
|
|
// Freeing DataFlowTag1: 1 VGPR (Value: UInt32) (op 4): v0
|
|
// Deleting tag 1
|
|
// Kernel(1) END
|
|
// end: generate({1})
|
|
// CodeGeneratorVisitor::generate() end
|
|
)";
|
|
|
|
EXPECT_EQ(NormalizedSource(kexpected, true), NormalizedSource(output(), true));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This is a regression test that will fail if codegen for the Scope operation doesn't
|
|
* lock the scheduler.
|
|
*
|
|
* For the bug to appear, we need the following to happen:
|
|
* Scope A and B are under separate locations of the graph.
|
|
*
|
|
* - Begin Scope A
|
|
* - Begin Scope B
|
|
* - Allocate a DataFlow register (df1)
|
|
* (this goes into scope B)
|
|
* - End Scope B (will deallocate df1)
|
|
* - Try to use df1 (throws an exception)
|
|
*/
|
|
TEST_P(ScopeTest, ScopeOperationFalseNesting)
|
|
{
|
|
auto kgraph = rocRoller::KernelGraph::KernelGraph();
|
|
|
|
int kernel = kgraph.control.addElement(Kernel());
|
|
|
|
int dst1 = kgraph.coordinates.addElement(VGPR());
|
|
int dst2 = kgraph.coordinates.addElement(VGPR());
|
|
int dst3 = kgraph.coordinates.addElement(VGPR());
|
|
int dst4 = kgraph.coordinates.addElement(VGPR());
|
|
|
|
Expression::DataFlowTag dst3Tag{dst3, Register::Type::Vector, DataType::UInt32};
|
|
auto dst3Expr = std::make_shared<Expression::Expression>(dst3Tag);
|
|
|
|
Expression::DataFlowTag dst2Tag{dst2, Register::Type::Vector, DataType::UInt32};
|
|
auto dst2Expr = std::make_shared<Expression::Expression>(dst2Tag);
|
|
|
|
int scope1 = kgraph.control.addElement(Scope());
|
|
int scope2 = kgraph.control.addElement(Scope());
|
|
int scope3 = kgraph.control.addElement(Scope());
|
|
|
|
int assign1
|
|
= kgraph.control.addElement(Assign{Register::Type::Vector, Expression::literal(11u)});
|
|
int assign2
|
|
= kgraph.control.addElement(Assign{Register::Type::Vector, Expression::literal(22u)});
|
|
int assign3
|
|
= kgraph.control.addElement(Assign{Register::Type::Vector, Expression::literal(33u)});
|
|
int assign4 = kgraph.control.addElement(
|
|
Assign{Register::Type::Vector, (Expression::literal(44u) + dst3Expr) * dst3Expr});
|
|
|
|
int assign5 = kgraph.control.addElement(
|
|
Assign{Register::Type::Vector, Expression::literal(4u) + dst2Expr});
|
|
|
|
kgraph.mapper.connect(assign1, dst1, NaryArgument::DEST);
|
|
kgraph.mapper.connect(assign2, dst2, NaryArgument::DEST);
|
|
kgraph.mapper.connect(assign3, dst3, NaryArgument::DEST);
|
|
kgraph.mapper.connect(assign4, dst1, NaryArgument::DEST);
|
|
kgraph.mapper.connect(assign5, dst4, NaryArgument::DEST);
|
|
|
|
int barrier = kgraph.control.addElement(Barrier{});
|
|
|
|
// kernel(base scope):
|
|
// - assign dst1 = 11u
|
|
// - scope1:
|
|
// - scope2:
|
|
// - barrier
|
|
// - assign dst3 = 33u
|
|
// - assign dst1 = (44u + dst3) * dst3
|
|
// - scope3:
|
|
// - assign dst2 = 22u
|
|
// - assign dst4 = dst2 + 4u
|
|
|
|
kgraph.control.addElement(Body(), {kernel}, {assign1});
|
|
kgraph.control.addElement(Sequence(), {assign1}, {scope1});
|
|
kgraph.control.addElement(Body(), {scope1}, {scope2});
|
|
kgraph.control.addElement(Body(), {scope2}, {barrier});
|
|
kgraph.control.addElement(Body(), {barrier}, {assign3});
|
|
kgraph.control.addElement(Sequence(), {assign3}, {assign4});
|
|
kgraph.control.addElement(Body(), {scope1}, {scope3});
|
|
kgraph.control.addElement(Body(), {scope3}, {assign2});
|
|
kgraph.control.addElement(Sequence(), {assign2}, {assign5});
|
|
|
|
kgraph = kgraph.transform(std::make_shared<RemoveSetCoordinate>());
|
|
|
|
auto sched = GetParam();
|
|
Settings::getInstance()->set(Settings::Scheduler, sched);
|
|
EXPECT_NO_THROW(m_context->schedule(generate(kgraph, m_context->kernel())));
|
|
|
|
auto expected = R"(
|
|
"coord1" -> "to_cntrl_1_5"
|
|
"to_cntrl_1_5"[label="5->1: DEST", shape=cds]
|
|
"cntrl5" -> "to_coord_5_1"
|
|
"to_coord_5_1"[label="5->1: DEST", shape=cds]
|
|
"coord2" -> "to_cntrl_2_6"
|
|
"to_cntrl_2_6"[label="6->2: DEST", shape=cds]
|
|
"cntrl6" -> "to_coord_6_2"
|
|
"to_coord_6_2"[label="6->2: DEST", shape=cds]
|
|
"coord3" -> "to_cntrl_3_7"
|
|
"to_cntrl_3_7"[label="7->3: DEST", shape=cds]
|
|
"cntrl7" -> "to_coord_7_3"
|
|
"to_coord_7_3"[label="7->3: DEST", shape=cds]
|
|
"coord1" -> "to_cntrl_1_8"
|
|
"to_cntrl_1_8"[label="8->1: DEST", shape=cds]
|
|
"cntrl8" -> "to_coord_8_1"
|
|
"to_coord_8_1"[label="8->1: DEST", shape=cds]
|
|
"coord4" -> "to_cntrl_4_9"
|
|
"to_cntrl_4_9"[label="9->4: DEST", shape=cds]
|
|
"cntrl9" -> "to_coord_9_4"
|
|
"to_coord_9_4"[label="9->4: DEST", shape=cds]
|
|
)";
|
|
|
|
EXPECT_EQ(NormalizedSource(expected),
|
|
NormalizedSource(kgraph.mapper.toDOT("coord", "cntrl", true)));
|
|
}
|
|
|
|
auto schedulers()
|
|
{
|
|
std::vector<Scheduling::SchedulerProcedure> rv;
|
|
for(int i = 0; i < static_cast<int>(Scheduling::SchedulerProcedure::Count); i++)
|
|
{
|
|
rv.push_back(static_cast<Scheduling::SchedulerProcedure>(i));
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(ScopeTest, ScopeTest, ::testing::ValuesIn(schedulers()));
|
|
}
|