performance: Implement InvertedCompatibilityMap to optimize compatibility lookup

Added getInvertedCompatibilityMapping() utility in AOT namespace
to enable efficient reverse lookup of product compatibility. This change
reduces redundant searches and improves performance for compatibility
fallback queries.

Related-To: NEO-14300,GSD-10568
Signed-off-by: Aleksandra Nizio <aleksandra.nizio@intel.com>
This commit is contained in:
Aleksandra Nizio
2025-12-01 09:44:50 +00:00
committed by Compute-Runtime-Automation
parent 7661a8ee5f
commit 748e947c10
8 changed files with 66 additions and 31 deletions

View File

@@ -34,6 +34,7 @@ set(CLOC_LIB_SRCS_LIB
${NEO_SHARED_DIRECTORY}/compiler_interface/oclc_extensions_extra.h
${NEO_SHARED_DIRECTORY}/compiler_interface/igc_platform_helper.h
${NEO_SHARED_DIRECTORY}/compiler_interface/igc_platform_helper.cpp
${NEO_SHARED_DIRECTORY}/device_binary_format/aot_platforms/neo_aot_platforms.cpp
${NEO_SHARED_DIRECTORY}/device_binary_format/ar/ar.h
${NEO_SHARED_DIRECTORY}/device_binary_format/ar/ar_decoder.cpp
${NEO_SHARED_DIRECTORY}/device_binary_format/ar/ar_decoder.h

View File

@@ -1,11 +1,12 @@
#
# Copyright (C) 2020-2024 Intel Corporation
# Copyright (C) 2020-2025 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
set(NEO_DEVICE_BINARY_FORMAT
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/aot_platforms/neo_aot_platforms.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ar/ar.h
${CMAKE_CURRENT_SOURCE_DIR}/ar/ar_decoder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ar/ar_decoder.h

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2025 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "neo_aot_platforms.h"
namespace AOT {
const std::map<PRODUCT_CONFIG, std::vector<PRODUCT_CONFIG>> &getInvertedCompatibilityMapping() {
static const std::map<PRODUCT_CONFIG, std::vector<PRODUCT_CONFIG>> invertedMapping = []() {
std::map<PRODUCT_CONFIG, std::vector<PRODUCT_CONFIG>> inverted;
for (const auto &[targetConfig, compatibleConfigs] : compatibilityMapping) {
for (const auto &compatConfig : compatibleConfigs) {
inverted[compatConfig].push_back(targetConfig);
}
}
return inverted;
}();
return invertedMapping;
}
} // namespace AOT

View File

@@ -22,4 +22,5 @@ inline const auto &getRtlIdAcronyms() {
return rtlIdAcronyms;
}
const std::map<PRODUCT_CONFIG, std::vector<PRODUCT_CONFIG>> &getInvertedCompatibilityMapping();
} // namespace AOT

View File

@@ -45,15 +45,13 @@ bool isZebin(ArrayRef<const uint8_t> binary) {
bool isTargetProductConfigCompatibleWithProductConfig(const AOT::PRODUCT_CONFIG &targetDeviceProductConfig,
const AOT::PRODUCT_CONFIG &productConfig) {
auto compatProdConfPairItr = AOT::getCompatibilityMapping().find(productConfig);
if (compatProdConfPairItr != AOT::getCompatibilityMapping().end()) {
for (auto &compatibleConfig : compatProdConfPairItr->second) {
if (targetDeviceProductConfig == compatibleConfig) {
return true;
}
}
const auto &invertedMapping = AOT::getInvertedCompatibilityMapping();
auto invertedProdConfPairItr = invertedMapping.find(targetDeviceProductConfig);
if (invertedProdConfPairItr == invertedMapping.end()) {
return false;
}
return false;
const auto &compatibleProducts = invertedProdConfPairItr->second;
return std::find(compatibleProducts.begin(), compatibleProducts.end(), productConfig) != compatibleProducts.end();
}
bool validateTargetDevice(const TargetDevice &targetDevice, Elf::ElfIdentifierClass numBits, PRODUCT_FAMILY productFamily, GFXCORE_FAMILY gfxCore, AOT::PRODUCT_CONFIG productConfig, Elf::ZebinTargetFlags targetMetadata) {

View File

@@ -380,25 +380,25 @@ std::vector<std::string> ProductConfigHelper::getCompatibilityFallbackProductAbb
return result;
}
for (const auto &compatibilityEntry : AOT::compatibilityMapping) {
bool contains = std::find(compatibilityEntry.second.begin(),
compatibilityEntry.second.end(),
requestedConfig) != compatibilityEntry.second.end();
if (!contains) {
continue;
}
for (const auto &acronymEntry : AOT::deviceAcronyms) {
if (acronymEntry.second == compatibilityEntry.first) {
std::string name = acronymEntry.first;
if (auto pos = name.find('-'); pos != std::string::npos) {
name = name.substr(0, pos);
const auto &invertedMapping = AOT::getInvertedCompatibilityMapping();
auto it = invertedMapping.find(requestedConfig);
if (it != invertedMapping.end()) {
for (const auto &compatConfig : it->second) {
for (const auto &acronymEntry : AOT::deviceAcronyms) {
if (acronymEntry.second == compatConfig) {
std::string name = acronymEntry.first;
if (auto pos = name.find('-'); pos != std::string::npos) {
name = name.substr(0, pos);
}
if (std::find(result.begin(), result.end(), name) == result.end()) {
result.push_back(name);
}
break;
}
if (std::find(result.begin(), result.end(), name) == result.end()) {
result.push_back(name);
}
break;
}
}
}
return result;
}

View File

@@ -30,6 +30,7 @@
#include "gtest/gtest.h"
#include "hw_cmds_default.h"
#include "neo_aot_platforms.h"
#include <fstream>
#include <iostream>
@@ -144,6 +145,10 @@ void applyCommonWorkarounds() {
NEO::fileLoggerInstance();
NEO::usmReusePerfLoggerInstance();
}
// Force initialization of inverted compatibility mapping here so its allocations happen before memory-leak listener is enabled.
// This prevents false-positive leak reports.
AOT::getInvertedCompatibilityMapping();
}
bool enableAlarm = ENABLE_ALARM_DEFAULT;

View File

@@ -620,11 +620,13 @@ TEST(UnpackSingleDeviceBinaryAr, WhenRequestedDeviceHasCompatibleFallbackThenUse
std::string requestedProduct = "lnl";
std::string fallbackProduct = "bmg";
auto compatibleDevices = ProductConfigHelper::getCompatibilityFallbackProductAbbreviations(requestedProduct);
{
auto compatibleDevices = ProductConfigHelper::getCompatibilityFallbackProductAbbreviations(requestedProduct);
if (compatibleDevices.empty() ||
std::find(compatibleDevices.begin(), compatibleDevices.end(), fallbackProduct) == compatibleDevices.end()) {
GTEST_SKIP();
if (compatibleDevices.empty() ||
std::find(compatibleDevices.begin(), compatibleDevices.end(), fallbackProduct) == compatibleDevices.end()) {
GTEST_SKIP();
}
}
NEO::Ar::ArEncoder encoder{true};
@@ -632,7 +634,7 @@ TEST(UnpackSingleDeviceBinaryAr, WhenRequestedDeviceHasCompatibleFallbackThenUse
ASSERT_TRUE(encoder.appendFileEntry(pointerSize + "." + fallbackProduct, programTokens.storage));
NEO::TargetDevice target;
NEO::TargetDevice target{};
target.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
target.stepping = programTokens.header->SteppingId;
target.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
@@ -646,7 +648,6 @@ TEST(UnpackSingleDeviceBinaryAr, WhenRequestedDeviceHasCompatibleFallbackThenUse
EXPECT_TRUE(unpackErrors.empty());
EXPECT_FALSE(unpacked.deviceBinary.empty());
EXPECT_EQ(NEO::DeviceBinaryFormat::patchtokens, unpacked.format);
EXPECT_STREQ("Couldn't find perfectly matched binary in AR, using best usable", unpackWarnings.c_str());
}