Files
TheRock/rocm-libraries/shared/rocroller/test/unit/LDSTest.cpp
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

171 lines
6.7 KiB
C++

// Copyright Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
#include "GenericContextFixture.hpp"
#include <rocRoller/DataTypes/DataTypes.hpp>
#include <rocRoller/InstructionValues/Register.hpp>
using namespace rocRoller;
namespace rocRollerTest
{
class LDSTest : public GenericContextFixture
{
};
TEST_F(LDSTest, LDSAllocationTest)
{
auto lds1 = Register::Value::AllocateLDS(m_context, DataType::Int32, 1000);
auto lds2 = Register::Value::AllocateLDS(m_context, DataType::Int32, 300);
EXPECT_EQ(lds1->toString(), "LDS:(Offset: 0, Size: 4000)");
EXPECT_EQ(lds2->toString(), "LDS:(Offset: 4000, Size: 1200)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 5200);
EXPECT_EQ(m_context->ldsAllocator()->maxUsed(), 5200);
lds1.reset();
// Free blocks: [0, 4000]
// Can fit in free block, so offset starts at 0
lds1 = Register::Value::AllocateLDS(m_context, DataType::Int32, 500);
EXPECT_EQ(lds1->toString(), "LDS:(Offset: 0, Size: 2000)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 3200);
EXPECT_EQ(m_context->ldsAllocator()->maxUsed(), 5200);
// Free blocks: [2000, 4000]
// Doesn't fit in free block, so needs to allocate from new memory
auto lds3 = Register::Value::AllocateLDS(m_context, DataType::Half, 1200, 2);
EXPECT_EQ(lds3->toString(), "LDS:(Offset: 5200, Size: 2400)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 5600);
EXPECT_EQ(m_context->ldsAllocator()->maxUsed(), 7600);
// Does fit in free block, so no new memory needed
auto lds4 = Register::Value::AllocateLDS(m_context, DataType::Int32, 500);
EXPECT_EQ(lds4->toString(), "LDS:(Offset: 2000, Size: 2000)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 7600);
EXPECT_EQ(m_context->ldsAllocator()->maxUsed(), 7600);
lds2.reset();
lds4.reset();
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 4400);
// Free blocks [2000, 5200]
lds2 = Register::Value::AllocateLDS(m_context, DataType::Int32, 600);
EXPECT_EQ(lds2->toString(), "LDS:(Offset: 2000, Size: 2400)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 6800);
EXPECT_EQ(m_context->ldsAllocator()->maxUsed(), 7600);
lds3.reset();
lds1.reset();
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 2400);
// Free blocks [0, 2000]
// Doesn't fit in first free block, append to end
lds1 = Register::Value::AllocateLDS(m_context, DataType::Int32, 600);
EXPECT_EQ(lds1->toString(), "LDS:(Offset: 4400, Size: 2400)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 4800);
// Free blocks [0, 2000]
// Fits in the first free block
lds4 = Register::Value::AllocateLDS(m_context, DataType::Int32, 100);
EXPECT_EQ(lds4->toString(), "LDS:(Offset: 0, Size: 400)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 5200);
// Free blocks [400, 2000]
// Exercise merging two free blocks together
lds2.reset();
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 2800);
// Free blocks [400, 4400]
lds1.reset();
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 400);
// Free blocks: None
lds1 = Register::Value::AllocateLDS(m_context, DataType::Int32, 1800);
EXPECT_EQ(lds1->toString(), "LDS:(Offset: 400, Size: 7200)");
lds1.reset();
// Free blocks: None
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 400);
EXPECT_EQ(m_context->ldsAllocator()->maxUsed(), 7600);
// Try different alignment
lds2 = Register::Value::AllocateLDS(m_context, DataType::Half, 1024, 2);
EXPECT_EQ(lds2->toString(), "LDS:(Offset: 400, Size: 2048)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 2448);
EXPECT_EQ(m_context->ldsAllocator()->maxUsed(), 7600);
// Try over allocating
auto maxLDS = m_context->targetArchitecture().GetCapability(GPUCapability::MaxLdsSize);
EXPECT_THROW(Register::Value::AllocateLDS(m_context, DataType::Int32, maxLDS / 4),
FatalError);
}
TEST_F(LDSTest, LDSAlignment)
{
auto lds1 = Register::Value::AllocateLDS(m_context, DataType::Half, 1, 2);
EXPECT_EQ(lds1->toString(), "LDS:(Offset: 0, Size: 2)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 2);
auto lds2 = Register::Value::AllocateLDS(m_context, DataType::Half, 2, 2);
EXPECT_EQ(lds2->toString(), "LDS:(Offset: 2, Size: 4)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 6);
auto lds3 = Register::Value::AllocateLDS(m_context, DataType::Int32, 1, 4);
EXPECT_EQ(lds3->toString(), "LDS:(Offset: 8, Size: 4)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 10);
lds1.reset();
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 8);
lds3.reset();
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 4);
lds2.reset();
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 0);
// All free
}
TEST_F(LDSTest, LDSCurrentUsage)
{
auto lds1 = Register::Value::AllocateLDS(m_context, DataType::Int32, 1000);
EXPECT_EQ(lds1->toString(), "LDS:(Offset: 0, Size: 4000)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 4000);
auto lds2 = Register::Value::AllocateLDS(m_context, DataType::Int32, 1000);
EXPECT_EQ(lds2->toString(), "LDS:(Offset: 4000, Size: 4000)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 8000);
auto lds3 = Register::Value::AllocateLDS(m_context, DataType::Half, 10, 2);
EXPECT_EQ(lds3->toString(), "LDS:(Offset: 8000, Size: 20)");
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 8020);
lds1.reset();
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 4020);
lds3.reset();
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 4000);
lds2.reset();
EXPECT_EQ(m_context->ldsAllocator()->currentUsed(), 0);
// All free
}
TEST_F(LDSTest, LDSOverAllocate)
{
auto maxLDS = m_context->targetArchitecture().GetCapability(GPUCapability::MaxLdsSize);
EXPECT_THROW(Register::Value::AllocateLDS(m_context, DataType::Int32, 1 + (maxLDS / 4), 4),
FatalError);
}
TEST_F(LDSTest, LDSAllocationDoubleFreeTest)
{
auto allocator = m_context->ldsAllocator();
auto alloc1 = allocator->allocate(100, 4);
allocator->deallocate(alloc1);
EXPECT_THROW(allocator->deallocate(alloc1), FatalError);
}
}