SWDEV-433371 - use comgr to unbundle code objects
1.Make runtime use comgr to unbundle code objects 2.Support compressed/uncompressed modes 3.Remove HIP_USE_RUNTIME_UNBUNDLER and HIPRTC_USE_RUNTIME_UNBUNDLER to simplify logics 4.Add comgr wrapper for amd_comgr_action_info_set_bundle_entry_ids() Change-Id: Ic41b1ad1b64cca1e31986437983a5146d52a7329
This commit is contained in:
+69
-244
@@ -50,57 +50,46 @@ FatBinaryInfo::FatBinaryInfo(const char* fname, const void* image) : fdesc_(amd:
|
||||
}
|
||||
|
||||
FatBinaryInfo::~FatBinaryInfo() {
|
||||
|
||||
// Different devices in the same model have the same binary_image_
|
||||
std::set<const void*> toDelete;
|
||||
// Release per device fat bin info.
|
||||
for (auto* fbd: fatbin_dev_info_) {
|
||||
if (fbd != nullptr) {
|
||||
if (fbd->binary_image_ && fbd->binary_offset_ == 0 && fbd->binary_image_ != image_) {
|
||||
// binary_image_ was allocated in CodeObject::extractCodeObjectFromFatBinary
|
||||
toDelete.insert(fbd->binary_image_);
|
||||
}
|
||||
delete fbd;
|
||||
}
|
||||
}
|
||||
|
||||
if (!HIP_USE_RUNTIME_UNBUNDLER) {
|
||||
// Using COMGR Unbundler
|
||||
if (ufd_ && amd::Os::isValidFileDesc(ufd_->fdesc_)) {
|
||||
// Check for ufd_ != nullptr, since sometimes, we never create unique_file_desc.
|
||||
if (ufd_->fsize_ && image_mapped_
|
||||
&& !amd::Os::MemoryUnmapFile(image_, ufd_->fsize_)) {
|
||||
LogPrintfError("Cannot unmap file for fdesc: %d fsize: %d", ufd_->fdesc_, ufd_->fsize_);
|
||||
assert(false);
|
||||
}
|
||||
if (!PlatformState::instance().CloseUniqueFileHandle(ufd_)) {
|
||||
LogPrintfError("Cannot close file for fdesc: %d", ufd_->fdesc_);
|
||||
assert(false);
|
||||
}
|
||||
for (auto itemData : toDelete) {
|
||||
LogPrintfInfo("~FatBinaryInfo(%p) will delete binary_image_ %p", this, itemData);
|
||||
delete[] reinterpret_cast<const char*>(itemData);
|
||||
}
|
||||
|
||||
// Using COMGR Unbundler
|
||||
if (ufd_ && amd::Os::isValidFileDesc(ufd_->fdesc_)) {
|
||||
// Check for ufd_ != nullptr, since sometimes, we never create unique_file_desc.
|
||||
if (ufd_->fsize_ && image_mapped_
|
||||
&& !amd::Os::MemoryUnmapFile(image_, ufd_->fsize_)) {
|
||||
LogPrintfError("Cannot unmap file for fdesc: %d fsize: %d", ufd_->fdesc_, ufd_->fsize_);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fname_ = std::string();
|
||||
fdesc_ = amd::Os::FDescInit();
|
||||
fsize_ = 0;
|
||||
image_ = nullptr;
|
||||
uri_ = std::string();
|
||||
|
||||
if (0 == PlatformState::instance().UfdMapSize()) {
|
||||
LogError("All Unique FDs are closed");
|
||||
if (!PlatformState::instance().CloseUniqueFileHandle(ufd_)) {
|
||||
LogPrintfError("Cannot close file for fdesc: %d", ufd_->fdesc_);
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Using Runtime Unbundler
|
||||
if (amd::Os::isValidFileDesc(fdesc_)) {
|
||||
if (fsize_ && !amd::Os::MemoryUnmapFile(image_, fsize_)) {
|
||||
LogPrintfError("Cannot unmap file for fdesc: %d fsize: %d", fdesc_, fsize_);
|
||||
assert(false);
|
||||
}
|
||||
if (!amd::Os::CloseFileHandle(fdesc_)) {
|
||||
LogPrintfError("Cannot close file for fdesc: %d", fdesc_);
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
fname_ = std::string();
|
||||
fdesc_ = amd::Os::FDescInit();
|
||||
fsize_ = 0;
|
||||
image_ = nullptr;
|
||||
uri_ = std::string();
|
||||
|
||||
fname_ = std::string();
|
||||
fdesc_ = amd::Os::FDescInit();
|
||||
fsize_ = 0;
|
||||
image_ = nullptr;
|
||||
uri_ = std::string();
|
||||
if (0 == PlatformState::instance().UfdMapSize()) {
|
||||
LogError("All Unique FDs are closed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,11 +103,8 @@ void ListAllDeviceWithNoCOFromBundle(const std::unordered_map<std::string,
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t FatBinaryInfo::ExtractFatBinaryUsingCOMGR(const std::vector<hip::Device*>& devices) {
|
||||
amd_comgr_data_t data_object {0};
|
||||
amd_comgr_status_t comgr_status = AMD_COMGR_STATUS_SUCCESS;
|
||||
hipError_t FatBinaryInfo::ExtractFatBinary(const std::vector<hip::Device*>& devices) {
|
||||
hipError_t hip_status = hipSuccess;
|
||||
|
||||
// If image was passed as a pointer to our hipMod* api, we can try to extract the file name
|
||||
// if it was mapped by the app. Otherwise use the COMGR data API.
|
||||
if (fname_.size() == 0) {
|
||||
@@ -163,107 +149,52 @@ hipError_t FatBinaryInfo::ExtractFatBinaryUsingCOMGR(const std::vector<hip::Devi
|
||||
fname_.c_str());
|
||||
|
||||
do {
|
||||
std::vector<std::pair<const void*, size_t>> code_objs;
|
||||
// Copy device names
|
||||
std::vector<std::string> device_names;
|
||||
device_names.reserve(devices.size());
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
device_names.push_back(devices[dev_idx]->devices()[0]->isa().isaName());
|
||||
}
|
||||
hip_status = CodeObject::extractCodeObjectFromFatBinary(
|
||||
image_, 0, device_names, code_objs);
|
||||
if (hip_status == hipErrorNoBinaryForGpu || hip_status == hipSuccess) {
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
if (code_objs[dev_idx].first) {
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]
|
||||
= new FatBinaryDeviceInfo(code_objs[dev_idx].first, code_objs[dev_idx].second, 0);
|
||||
|
||||
// If the image ptr is not clang offload bundle then just directly point the image.
|
||||
if (!CodeObject::IsClangOffloadMagicBundle(image_)) {
|
||||
for (size_t dev_idx=0; dev_idx < devices.size(); ++dev_idx) {
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]
|
||||
= new FatBinaryDeviceInfo(image_, CodeObject::ElfSize(image_), 0);
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]->program_
|
||||
= new amd::Program(*devices[dev_idx]->asContext());
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]->program_
|
||||
= new amd::Program(*devices[dev_idx]->asContext());
|
||||
if (fatbin_dev_info_[devices[dev_idx]->deviceId()]->program_ == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// This is the case of hipErrorNoBinaryForGpu which will finally fail app
|
||||
LogPrintfError("Cannot find CO in the bundle %s for ISA: %s", fname_.c_str(),
|
||||
device_names[dev_idx].c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hip_status == hipErrorInvalidKernelFile) {
|
||||
hip_status = hipSuccess;
|
||||
// If the image ptr is not clang offload bundle then just directly point the image.
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()] =
|
||||
new FatBinaryDeviceInfo(image_, CodeObject::ElfSize(image_), 0);
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]->program_ =
|
||||
new amd::Program(*devices[dev_idx]->asContext());
|
||||
if (fatbin_dev_info_[devices[dev_idx]->deviceId()]->program_ == nullptr) {
|
||||
hip_status = hipErrorOutOfMemory;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Create a data object, if it fails return error
|
||||
if ((comgr_status = amd_comgr_create_data(AMD_COMGR_DATA_KIND_FATBIN, &data_object))
|
||||
!= AMD_COMGR_STATUS_SUCCESS) {
|
||||
LogPrintfError("Creating data object failed with status %d ", comgr_status);
|
||||
hip_status = hipErrorInvalidValue;
|
||||
break;
|
||||
}
|
||||
|
||||
#if !defined(_WIN32)
|
||||
// Using the file descriptor and file size, map the data object.
|
||||
if (amd::Os::isValidFileDesc(fdesc_)) {
|
||||
guarantee(fsize_ > 0, "Cannot have a file size of 0, fdesc: %d fname: %s",
|
||||
fdesc_, fname_.c_str());
|
||||
if ((comgr_status = amd_comgr_set_data_from_file_slice(data_object, fdesc_, foffset_,
|
||||
fsize_)) != AMD_COMGR_STATUS_SUCCESS) {
|
||||
LogPrintfError("Setting data from file slice failed with status %d ", comgr_status);
|
||||
hip_status = hipErrorInvalidValue;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (image_ != nullptr) {
|
||||
// Using the image ptr, map the data object.
|
||||
if ((comgr_status = amd_comgr_set_data(data_object, 4096,
|
||||
reinterpret_cast<const char*>(image_))) != AMD_COMGR_STATUS_SUCCESS) {
|
||||
LogPrintfError("Setting data from file slice failed with status %d ", comgr_status);
|
||||
hip_status = hipErrorInvalidValue;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
guarantee(false, "Cannot have both fname_ and image_ as nullptr");
|
||||
}
|
||||
|
||||
// Find the unique number of ISAs needed for this COMGR query.
|
||||
std::unordered_map<std::string, std::pair<size_t, size_t>> unique_isa_names;
|
||||
for (auto device : devices) {
|
||||
std::string device_name = device->devices()[0]->isa().isaName();
|
||||
unique_isa_names.insert({device_name, std::make_pair<size_t, size_t>(0,0)});
|
||||
}
|
||||
|
||||
// Create a query list using COMGR info for unique ISAs.
|
||||
std::vector<amd_comgr_code_object_info_t> query_list_array;
|
||||
query_list_array.reserve(unique_isa_names.size());
|
||||
for (const auto &isa_name : unique_isa_names) {
|
||||
auto &item = query_list_array.emplace_back();
|
||||
item.isa = isa_name.first.c_str();
|
||||
item.size = 0;
|
||||
item.offset = 0;
|
||||
}
|
||||
|
||||
// Look up the code object info passing the query list.
|
||||
if ((comgr_status = amd_comgr_lookup_code_object(data_object, query_list_array.data(),
|
||||
unique_isa_names.size())) != AMD_COMGR_STATUS_SUCCESS) {
|
||||
LogPrintfError("Setting data from file slice failed with status %d ", comgr_status);
|
||||
hip_status = hipErrorInvalidValue;
|
||||
break;
|
||||
}
|
||||
|
||||
for (const auto &item : query_list_array) {
|
||||
auto unique_it = unique_isa_names.find(item.isa);
|
||||
guarantee(unique_isa_names.cend() != unique_it, "Cannot find unique isa ");
|
||||
unique_it->second = std::pair<size_t, size_t>
|
||||
(static_cast<size_t>(item.size),
|
||||
static_cast<size_t>(item.offset));
|
||||
}
|
||||
|
||||
for (auto device : devices) {
|
||||
std::string device_name = device->devices()[0]->isa().isaName();
|
||||
auto dev_it = unique_isa_names.find(device_name);
|
||||
// If the size is 0, then COMGR API could not find the CO for this GPU device/ISA
|
||||
if (dev_it->second.first == 0) {
|
||||
LogPrintfError("Cannot find CO in the bundle %s for ISA: %s",
|
||||
fname_.c_str(), device_name.c_str());
|
||||
hip_status = hipErrorNoBinaryForGpu;
|
||||
ListAllDeviceWithNoCOFromBundle(unique_isa_names);
|
||||
break;
|
||||
}
|
||||
guarantee(unique_isa_names.cend() != dev_it,
|
||||
"Cannot find the device name in the unique device name");
|
||||
fatbin_dev_info_[device->deviceId()]
|
||||
= new FatBinaryDeviceInfo(reinterpret_cast<address>(const_cast<void*>(image_))
|
||||
+ dev_it->second.second, dev_it->second.first,
|
||||
dev_it->second.second);
|
||||
fatbin_dev_info_[device->deviceId()]->program_
|
||||
= new amd::Program(*(device->asContext()));
|
||||
else {
|
||||
LogPrintfError(
|
||||
"CodeObject::extractCodeObjectFromFatBinary failed with status %d\n",
|
||||
hip_status);
|
||||
}
|
||||
} while(0);
|
||||
|
||||
@@ -286,115 +217,9 @@ hipError_t FatBinaryInfo::ExtractFatBinaryUsingCOMGR(const std::vector<hip::Devi
|
||||
fsize_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (data_object.handle) {
|
||||
if ((comgr_status = amd_comgr_release_data(data_object)) != AMD_COMGR_STATUS_SUCCESS) {
|
||||
LogPrintfError("Releasing COMGR data failed with status %d ", comgr_status);
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
}
|
||||
|
||||
return hip_status;
|
||||
}
|
||||
|
||||
hipError_t FatBinaryInfo::ExtractFatBinary(const std::vector<hip::Device*>& devices) {
|
||||
if (!HIP_USE_RUNTIME_UNBUNDLER) {
|
||||
return ExtractFatBinaryUsingCOMGR(devices);
|
||||
}
|
||||
|
||||
hipError_t hip_error = hipSuccess;
|
||||
std::vector<std::pair<const void*, size_t>> code_objs;
|
||||
|
||||
// Copy device names for Extract Code object File
|
||||
std::vector<std::string> device_names;
|
||||
device_names.reserve(devices.size());
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
device_names.push_back(devices[dev_idx]->devices()[0]->isa().isaName());
|
||||
}
|
||||
|
||||
// We are given file name, get the file desc and file size
|
||||
if (fname_.size() > 0) {
|
||||
// Get File Handle & size of the file.
|
||||
if (!amd::Os::GetFileHandle(fname_.c_str(), &fdesc_, &fsize_)) {
|
||||
return hipErrorFileNotFound;
|
||||
}
|
||||
if (fsize_ == 0) {
|
||||
return hipErrorInvalidImage;
|
||||
}
|
||||
|
||||
// Extract the code object from file
|
||||
hip_error = CodeObject::ExtractCodeObjectFromFile(fdesc_, fsize_, &image_,
|
||||
device_names, code_objs);
|
||||
|
||||
} else if (image_ != nullptr) {
|
||||
// We are directly given image pointer directly, try to extract file desc & file Size
|
||||
hip_error = CodeObject::ExtractCodeObjectFromMemory(image_,
|
||||
device_names, code_objs, uri_);
|
||||
} else {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
if (hip_error == hipErrorNoBinaryForGpu) {
|
||||
if (fname_.size() > 0) {
|
||||
LogPrintfError("hipErrorNoBinaryForGpu: Couldn't find binary for file: %s", fname_.c_str());
|
||||
} else {
|
||||
LogPrintfError("hipErrorNoBinaryForGpu: Couldn't find binary for ptr: 0x%x", image_);
|
||||
}
|
||||
|
||||
// For the condition: unable to find code object for all devices,
|
||||
// still extract available images to those devices owning them.
|
||||
// This helps users to work with ROCm if there is any supported
|
||||
// GFX on system.
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
if (code_objs[dev_idx].first) {
|
||||
// Calculate the offset wrt binary_image and the original image
|
||||
size_t offset_l
|
||||
= (reinterpret_cast<address>(const_cast<void*>(code_objs[dev_idx].first))
|
||||
- reinterpret_cast<address>(const_cast<void*>(image_)));
|
||||
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]
|
||||
= new FatBinaryDeviceInfo(code_objs[dev_idx].first, code_objs[dev_idx].second, offset_l);
|
||||
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]->program_
|
||||
= new amd::Program(*devices[dev_idx]->asContext());
|
||||
if (fatbin_dev_info_[devices[dev_idx]->deviceId()]->program_ == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hip_error;
|
||||
}
|
||||
|
||||
if (hip_error == hipErrorInvalidKernelFile) {
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
// the image type is no CLANG_OFFLOAD_BUNDLER, image for current device directly passed
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]
|
||||
= new FatBinaryDeviceInfo(image_, CodeObject::ElfSize(image_), 0);
|
||||
}
|
||||
} else if(hip_error == hipSuccess) {
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
// Calculate the offset wrt binary_image and the original image
|
||||
size_t offset_l
|
||||
= (reinterpret_cast<address>(const_cast<void*>(code_objs[dev_idx].first))
|
||||
- reinterpret_cast<address>(const_cast<void*>(image_)));
|
||||
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]
|
||||
= new FatBinaryDeviceInfo(code_objs[dev_idx].first, code_objs[dev_idx].second, offset_l);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]->program_
|
||||
= new amd::Program(*devices[dev_idx]->asContext());
|
||||
if (fatbin_dev_info_[devices[dev_idx]->deviceId()]->program_ == NULL) {
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
}
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t FatBinaryInfo::AddDevProgram(const int device_id) {
|
||||
// Device Id bounds Check
|
||||
DeviceIdCheck(device_id);
|
||||
|
||||
Fai riferimento in un nuovo problema
Block a user