From 0dff46f6b9a788ad1c3973e53d90fe49018fcee9 Mon Sep 17 00:00:00 2001 From: "Bernhart, Bryan" Date: Thu, 10 Aug 2023 14:59:45 -0700 Subject: [PATCH] Convert sizes to printable units. --- src/gpgmm/common/BUILD.gn | 2 ++ src/gpgmm/common/CMakeLists.txt | 2 ++ src/gpgmm/common/SizeClass.cpp | 42 ++++++++++++++++++++++ src/gpgmm/common/SizeClass.h | 5 +++ src/gpgmm/d3d12/ResidencyManagerD3D12.cpp | 12 +++---- src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp | 14 ++++---- src/tests/BUILD.gn | 1 + src/tests/CMakeLists.txt | 1 + src/tests/unittests/SizeClassTests.cpp | 38 ++++++++++++++++++++ 9 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 src/gpgmm/common/SizeClass.cpp create mode 100644 src/tests/unittests/SizeClassTests.cpp diff --git a/src/gpgmm/common/BUILD.gn b/src/gpgmm/common/BUILD.gn index 4f893c379..cf9f7f410 100644 --- a/src/gpgmm/common/BUILD.gn +++ b/src/gpgmm/common/BUILD.gn @@ -214,6 +214,8 @@ source_set("gpgmm_common_sources") { "SegmentedMemoryAllocator.h", "SentinelMemoryAllocator.cpp", "SentinelMemoryAllocator.h", + "SizeClass.cpp", + "SizeClass.h", "SlabBlockAllocator.cpp", "SlabBlockAllocator.h", "SlabMemoryAllocator.cpp", diff --git a/src/gpgmm/common/CMakeLists.txt b/src/gpgmm/common/CMakeLists.txt index 80186ed7c..32c0036b1 100644 --- a/src/gpgmm/common/CMakeLists.txt +++ b/src/gpgmm/common/CMakeLists.txt @@ -53,6 +53,8 @@ target_sources(gpgmm_common PRIVATE "SegmentedMemoryAllocator.h" "SentinelMemoryAllocator.cpp" "SentinelMemoryAllocator.h" + "SizeClass.cpp" + "SizeClass.h" "SlabBlockAllocator.cpp" "SlabBlockAllocator.h" "SlabMemoryAllocator.cpp" diff --git a/src/gpgmm/common/SizeClass.cpp b/src/gpgmm/common/SizeClass.cpp new file mode 100644 index 000000000..ac13dfdeb --- /dev/null +++ b/src/gpgmm/common/SizeClass.cpp @@ -0,0 +1,42 @@ +// Copyright 2022 The GPGMM Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "gpgmm/common/SizeClass.h" + +#include "gpgmm/utils/Assert.h" +#include "gpgmm/utils/Limits.h" + +#include +#include + +namespace gpgmm { + + std::string GetBytesToSizeInUnits(uint64_t bytes) { + // UINT_MAX is given special "invalid" size. + if (bytes == kInvalidSize) { + return "INVALID_SIZE"; + } + + const char* unitsArray[] = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; + size_t unitIndex = 0; + while (bytes >= 1024 && unitIndex < sizeof(unitsArray) / sizeof(unitsArray[0]) - 1) { + bytes /= 1024; + unitIndex++; + } + std::ostringstream oss; + oss << std::fixed << std::setprecision(2) << bytes << " " << unitsArray[unitIndex]; + return oss.str(); + } + +} // namespace gpgmm diff --git a/src/gpgmm/common/SizeClass.h b/src/gpgmm/common/SizeClass.h index ed956bc49..ff49c9d0b 100644 --- a/src/gpgmm/common/SizeClass.h +++ b/src/gpgmm/common/SizeClass.h @@ -16,6 +16,7 @@ #define SRC_GPGMM_COMMON_SIZECLASS_H_ #include +#include // Convert sizes, in bytes, to/from SI prefix. #define GPGMM_KB_TO_BYTES(bytes) ((bytes)*1024ull) @@ -33,6 +34,10 @@ namespace gpgmm { uint64_t Alignment; }; + // Returns the printable string of |bytes| in storage units (eg. 2*1024 => + // 2 MB). + std::string GetBytesToSizeInUnits(uint64_t bytes); + // Generates array containing values in range [2^N1...2^N2], where N2 > N1. template static constexpr std::array GeneratePowerOfTwoSizes() { diff --git a/src/gpgmm/d3d12/ResidencyManagerD3D12.cpp b/src/gpgmm/d3d12/ResidencyManagerD3D12.cpp index 88d0aae89..9a6161d99 100644 --- a/src/gpgmm/d3d12/ResidencyManagerD3D12.cpp +++ b/src/gpgmm/d3d12/ResidencyManagerD3D12.cpp @@ -582,7 +582,7 @@ namespace gpgmm::d3d12 { DebugEvent(this, MessageId::kBudgetExceeded) << "GPU page-out. Number of allocations: " << objectsToEvict.size() << " (" - << bytesEvicted << " bytes)."; + << GetBytesToSizeInUnits(bytesEvicted) << ")."; } if (bytesEvictedOut != nullptr) { @@ -746,7 +746,7 @@ namespace gpgmm::d3d12 { DebugEvent(this, MessageId::kBudgetExceeded) << "GPU page-in. Number of allocations: " << numberOfObjectsToMakeResident << " (" - << sizeToMakeResident << " bytes)."; + << GetBytesToSizeInUnits(sizeToMakeResident) << ")."; // Decrease the overhead from using MakeResident, a synchronous call, by calling the // asynchronous MakeResident, called EnqueueMakeResident, instead first. Should @@ -869,13 +869,13 @@ namespace gpgmm::d3d12 { DebugLog(MessageId::kBudgetUpdated, this) << GetMemorySegmentName(segmentGroup, IsUMA()) << " GPU memory segment:"; DebugLog(MessageId::kBudgetUpdated, this) - << "\tBudget: " << GPGMM_BYTES_TO_MB(info->Budget) << " MBs (" - << GPGMM_BYTES_TO_MB(info->CurrentUsage) << " used)."; + << "\tBudget: " << GetBytesToSizeInUnits(info->Budget) << " (" + << GetBytesToSizeInUnits(info->CurrentUsage) << " used)."; if (info->CurrentReservation == 0) { DebugLog(MessageId::kBudgetUpdated, this) - << "\tReserved: " << GPGMM_BYTES_TO_MB(info->CurrentReservation) << " MBs (" - << GPGMM_BYTES_TO_MB(info->AvailableForReservation) << " available)."; + << "\tReserved: " << GetBytesToSizeInUnits(info->CurrentReservation) << " (" + << GetBytesToSizeInUnits(info->AvailableForReservation) << " available)."; } } diff --git a/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp b/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp index c638a6020..d75f3b7b2 100644 --- a/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp +++ b/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp @@ -1018,8 +1018,8 @@ namespace gpgmm::d3d12 { ErrorLog(MessageId::kSizeExceeded, this) << "Unable to create resource allocation because the resource size exceeded " "the capabilities of the device: " - << GPGMM_BYTES_TO_GB(resourceInfo.SizeInBytes) << " vs " - << GPGMM_BYTES_TO_GB(mMaxResourceHeapSize) << " GBs."; + << GetBytesToSizeInUnits(resourceInfo.SizeInBytes) << " vs " + << GetBytesToSizeInUnits(mMaxResourceHeapSize); return E_OUTOFMEMORY; } @@ -1141,8 +1141,8 @@ namespace gpgmm::d3d12 { ErrorLog(MessageId::kSizeExceeded, this) << "Unable to create resource allocation because the resource size exceeded " "the capabilities of the adapter: " - << GPGMM_BYTES_TO_GB(request.SizeInBytes) << " vs " - << GPGMM_BYTES_TO_GB(maxSegmentSize) << " GBs."; + << GetBytesToSizeInUnits(request.SizeInBytes) << " vs " + << GetBytesToSizeInUnits(maxSegmentSize); return E_OUTOFMEMORY; } @@ -1164,9 +1164,9 @@ namespace gpgmm::d3d12 { DebugLog(MessageId::kBudgetExceeded, this) << "Current usage exceeded budget: " - << GPGMM_BYTES_TO_MB(currentVideoInfo->CurrentUsage) << " vs " - << GPGMM_BYTES_TO_MB(currentVideoInfo->Budget) << " MBs (" - << GPGMM_BYTES_TO_MB(request.AvailableForAllocation) << " MBs free)."; + << GetBytesToSizeInUnits(currentVideoInfo->CurrentUsage) << " vs " + << GetBytesToSizeInUnits(currentVideoInfo->Budget) << " (" + << GetBytesToSizeInUnits(request.AvailableForAllocation) << " free)."; } else { // Otherwise, only memory in budget is considered available. diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn index 81c49a20b..ae2e511ae 100644 --- a/src/tests/BUILD.gn +++ b/src/tests/BUILD.gn @@ -117,6 +117,7 @@ test("gpgmm_unittests") { "unittests/PooledMemoryAllocatorTests.cpp", "unittests/RefCountTests.cpp", "unittests/SegmentedMemoryAllocatorTests.cpp", + "unittests/SizeClassTests.cpp", "unittests/SlabBlockAllocatorTests.cpp", "unittests/SlabMemoryAllocatorTests.cpp", "unittests/StableListTests.cpp", diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 52579730f..e5a8b4573 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -36,6 +36,7 @@ target_sources(gpgmm_unittests PRIVATE "unittests/PooledMemoryAllocatorTests.cpp" "unittests/RefCountTests.cpp" "unittests/SegmentedMemoryAllocatorTests.cpp" + "unittests/SizeClassTests.cpp" "unittests/SlabBlockAllocatorTests.cpp" "unittests/SlabMemoryAllocatorTests.cpp" "unittests/StableListTests.cpp" diff --git a/src/tests/unittests/SizeClassTests.cpp b/src/tests/unittests/SizeClassTests.cpp new file mode 100644 index 000000000..afee382f6 --- /dev/null +++ b/src/tests/unittests/SizeClassTests.cpp @@ -0,0 +1,38 @@ +// Copyright 2022 The GPGMM Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "gpgmm/common/SizeClass.h" +#include "gpgmm/utils/Limits.h" + +using namespace gpgmm; + +TEST(SizeClassTests, SizeToUnits) { + EXPECT_EQ(GetBytesToSizeInUnits(1), "1 B"); + EXPECT_EQ(GetBytesToSizeInUnits(GPGMM_KB_TO_BYTES(1)), "1 KB"); + EXPECT_EQ(GetBytesToSizeInUnits(GPGMM_MB_TO_BYTES(1)), "1 MB"); + EXPECT_EQ(GetBytesToSizeInUnits(GPGMM_GB_TO_BYTES(1)), "1 GB"); + EXPECT_EQ(GetBytesToSizeInUnits(kInvalidSize), "INVALID_SIZE"); + + EXPECT_EQ(GetBytesToSizeInUnits(1024), "1 KB"); + EXPECT_EQ(GetBytesToSizeInUnits(GPGMM_KB_TO_BYTES(1024)), "1 MB"); + EXPECT_EQ(GetBytesToSizeInUnits(GPGMM_MB_TO_BYTES(1024)), "1 GB"); + + EXPECT_EQ(GetBytesToSizeInUnits(GPGMM_MB_TO_BYTES(2)), "2 MB"); + EXPECT_EQ(GetBytesToSizeInUnits(GPGMM_MB_TO_BYTES(20)), "20 MB"); + EXPECT_EQ(GetBytesToSizeInUnits(GPGMM_MB_TO_BYTES(200)), "200 MB"); + EXPECT_EQ(GetBytesToSizeInUnits(GPGMM_MB_TO_BYTES(2000)), "1 GB"); // Must be 2048 for 2GB + EXPECT_EQ(GetBytesToSizeInUnits(GPGMM_MB_TO_BYTES(2048)), "2 GB"); +}