SWDEV-562761 - Cleanup static fatbin on runtime teardown (#1873)

Этот коммит содержится в:
Pengda Xie
2025-11-24 21:57:46 -08:00
коммит произвёл GitHub
родитель 16e7ee32e6
Коммит 6c31785eaf
5 изменённых файлов: 95 добавлений и 8 удалений
+56
Просмотреть файл
@@ -361,6 +361,62 @@ hipError_t StatCO::removeFatBinary(FatBinaryInfo** module) {
return hipSuccess;
}
// =================================================================================================
void StatCO::RemoveAllFatBinaries() {
amd::ScopedLock lock(sclock_);
// Clear mapping tables that associate modules with host-side constructs
module_to_hostModule_.clear();
module_to_hostFunctions_.clear();
module_to_hostVars_.clear();
// Delete all registered variables and clear the container
for (auto const& [_, var] : vars_) {
delete var;
}
vars_.clear();
// Clean up managed variables - these require special handling for memory on each device
for (auto& [_, managed_vars] : managedVars_) {
for (auto& managed_var : managed_vars) {
// Free device-specific allocations across all devices
for (auto dev : g_devices) {
DeviceVar* dvar = nullptr;
if (managed_var->getDeviceVarPtr(&dvar, dev->deviceId()) == hipSuccess && dvar) {
// Free device memory (also deletes the device ptr)
[[maybe_unused]] hipError_t err = ihipFree(dvar->device_ptr());
assert(err == hipSuccess);
}
}
// Free the managed memory allocation itself
void** managed_ptr = static_cast<void**>(managed_var->getManagedVarPtr());
if (managed_var->getAllocFlag()) {
// Memory was allocated with ihipMallocManaged - use ihipFree
[[maybe_unused]] hipError_t err = ihipFree(*managed_ptr);
assert(err == hipSuccess);
} else {
// Memory was allocated with OS-level allocator - use OS release
amd::Os::releaseMemory(*managed_ptr, managed_var->getSize());
}
delete managed_var;
}
}
managedVars_.clear();
// Delete all registered functions and clear the container
for (auto const& [_, func] : functions_) {
delete func;
}
functions_.clear();
// Delete all fat binary info objects and clear the modules container
for (auto const& [_, fb_info] : modules_) {
delete fb_info;
}
modules_.clear();
}
hipError_t StatCO::registerStatFunction(const void* hostFunction, Function* func) {
amd::ScopedLock lock(sclock_);
+1
Просмотреть файл
@@ -156,6 +156,7 @@ class StatCO : public CodeObject {
FatBinaryInfo** addFatBinary(const void* data, bool initialized, bool& success);
hipError_t removeFatBinary(FatBinaryInfo** module);
hipError_t digestFatBinary(const void* data, FatBinaryInfo*& programs);
void RemoveAllFatBinaries();
// Register vars/funcs given to use from __hipRegister[Var/Func/ManagedVar]
hipError_t registerStatFunction(const void* hostFunction, Function* func);
+3
Просмотреть файл
@@ -813,6 +813,9 @@ void PlatformState::init() {
for (auto& it : statCO_.functions_) {
it.second->resize_dFunc(g_devices.size());
}
amd::RuntimeTearDown::RegisterTearDownCallback("PlatformState static fatbin cleanup", [this]() {
statCO_.RemoveAllFatBinaries();
});
}
hipError_t PlatformState::loadModule(hipModule_t* module, const char* fname, const void* image) {
+27 -6
Просмотреть файл
@@ -105,17 +105,29 @@ void Runtime::tearDown() {
}
// ~RuntimeTearDown() will reference listenerLock.
// listenerLock will be constructed ealier and destructed later than
// listenerLock will be constructed earlier and destructed later than
// runtime_tear_down.
amd::Monitor listenerLock("Hostcall listener lock");
std::vector<ReferenceCountedObject*> RuntimeTearDown::external_;
amd::Monitor listenerLock{};
std::vector<ReferenceCountedObject*> RuntimeTearDown::external_{};
std::vector<std::pair<std::string, RuntimeTearDown::TearDownCallback>>
RuntimeTearDown::tear_down_funcs_{};
class RuntimeTearDown runtime_tear_down{};
// =================================================================================================
RuntimeTearDown::~RuntimeTearDown() {
ClPrint(amd::LOG_INFO, amd::LOG_INIT, "Begin runtime teardown");
#if !defined(_WIN32) && !defined(BUILD_STATIC_LIBS)
// Only perform destruction if process matches the initialization,
// to avoid a call with the child process after fork()
// to avoid a call with the child process after fork().
if (amd::IS_HIP && amd::Os::getProcessId() == Runtime::pid()) {
// Execute teardown funcs in reverse order of registration.
for (auto it = tear_down_funcs_.rbegin(); it != tear_down_funcs_.rend(); ++it) {
ClPrint(amd::LOG_DEBUG, amd::LOG_INIT, "~RuntimeTearDown invoke callback: %s",
it->first.c_str());
it->second();
}
for (auto it : external_) {
ClPrint(amd::LOG_DEBUG, amd::LOG_INIT, "~RuntimeTearDown release external object: %p", it);
it->release();
}
Runtime::tearDown();
@@ -123,10 +135,19 @@ RuntimeTearDown::~RuntimeTearDown() {
#endif
}
void RuntimeTearDown::RegisterObject(ReferenceCountedObject* obj) { external_.push_back(obj); }
// =================================================================================================
void RuntimeTearDown::RegisterObject(ReferenceCountedObject* obj) {
external_.push_back(obj);
ClPrint(amd::LOG_DEBUG, amd::LOG_INIT, "RuntimeTearDown registered external object: %p", obj);
}
class RuntimeTearDown runtime_tear_down;
// =================================================================================================
void RuntimeTearDown::RegisterTearDownCallback(const std::string& msg, TearDownCallback func) {
tear_down_funcs_.emplace_back(msg, std::move(func));
ClPrint(amd::LOG_DEBUG, amd::LOG_INIT, "RuntimeTearDown registered callback: %s", msg.c_str());
}
// =================================================================================================
uint ReferenceCountedObject::retain() {
uint prev = referenceCount_.fetch_add(1, std::memory_order_relaxed);
assert(prev != 0 && "An object with count==0 is invalid");
+8 -2
Просмотреть файл
@@ -21,6 +21,7 @@
#ifndef RUNTIME_HPP_
#define RUNTIME_HPP_
#include <functional>
#include "top.hpp"
#include "thread/thread.hpp"
@@ -61,13 +62,18 @@ class Runtime : AllStatic {
/*@}*/
class RuntimeTearDown : public HeapObject {
static std::vector<ReferenceCountedObject*> external_;
public:
using TearDownCallback = std::function<void()>;
RuntimeTearDown() {}
~RuntimeTearDown();
static void RegisterObject(ReferenceCountedObject* obj);
static void RegisterTearDownCallback(const std::string& msg, TearDownCallback func);
private:
static std::vector<ReferenceCountedObject*> external_;
static std::vector<std::pair<std::string, TearDownCallback>> tear_down_funcs_;
};
} // namespace amd