P4 to Git Change 1787806 by yaxunl@yaxunl-lc10 on 2019/05/27 10:53:56

SWDEV-145570 - Support loading fat binary generated through --genco by hipModuleLoad.

	hip-clang --genco generates fat binary instead of code object. To support that
	we need to extract code object from fat binary in hipModuleLoadData. This is
	needed for hipRTC since multiple GPU archs may be passed.

Affected files ...

... //depot/stg/opencl/drivers/opencl/api/hip/hip_module.cpp#27 edit
... //depot/stg/opencl/drivers/opencl/api/hip/hip_platform.cpp#31 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/devprogram.cpp#42 edit
... //depot/stg/opencl/drivers/opencl/runtime/utils/flags.hpp#308 edit
このコミットが含まれているのは:
foreman
2019-05-27 20:11:08 -04:00
コミット bea21af6ad
2個のファイルの変更62行の追加23行の削除
+8
ファイルの表示
@@ -93,8 +93,16 @@ hipError_t hipModuleLoadData(hipModule_t *module, const void *image)
HIP_RETURN(ihipModuleLoadData(module, image)); HIP_RETURN(ihipModuleLoadData(module, image));
} }
extern bool __hipExtractCodeObjectFromFatBinary(const void* data,
const std::vector<const char*>& devices,
std::vector<std::pair<const void*, size_t>>& code_objs);
hipError_t ihipModuleLoadData(hipModule_t *module, const void *image) hipError_t ihipModuleLoadData(hipModule_t *module, const void *image)
{ {
std::vector<std::pair<const void*, size_t>> code_objs;
if (__hipExtractCodeObjectFromFatBinary(image, {hip::getCurrentContext()->devices()[0]->info().name_}, code_objs))
image = code_objs[0].first;
amd::Program* program = new amd::Program(*hip::getCurrentContext()); amd::Program* program = new amd::Program(*hip::getCurrentContext());
if (program == NULL) { if (program == NULL) {
return hipErrorOutOfMemory; return hipErrorOutOfMemory;
+54 -23
ファイルの表示
@@ -74,26 +74,23 @@ static bool isCompatibleCodeObject(const std::string& codeobj_target_id,
std::string(device_name).find("gfx906") == 0); std::string(device_name).find("gfx906") == 0);
} }
extern "C" std::vector< std::pair<hipModule_t, bool> >* __hipRegisterFatBinary(const void* data) // Extracts code objects from fat binary in data for device names given in devices.
// Returns true if code objects are extracted successfully.
bool __hipExtractCodeObjectFromFatBinary(const void* data,
const std::vector<const char*>& devices,
std::vector<std::pair<const void*, size_t>>& code_objs)
{ {
HIP_INIT(); HIP_INIT();
if(g_devices.empty()) { std::string magic((const char*)data, sizeof(CLANG_OFFLOAD_BUNDLER_MAGIC_STR) - 1);
return nullptr;
}
const __CudaFatBinaryWrapper* fbwrapper = reinterpret_cast<const __CudaFatBinaryWrapper*>(data);
if (fbwrapper->magic != __hipFatMAGIC2 || fbwrapper->version != 1) {
return nullptr;
}
std::string magic((char*)fbwrapper->binary, sizeof(CLANG_OFFLOAD_BUNDLER_MAGIC_STR) - 1);
if (magic.compare(CLANG_OFFLOAD_BUNDLER_MAGIC_STR)) { if (magic.compare(CLANG_OFFLOAD_BUNDLER_MAGIC_STR)) {
return nullptr; return false;
} }
auto programs = new std::vector< std::pair<hipModule_t, bool> >{g_devices.size()}; code_objs.resize(devices.size());
const auto obheader = reinterpret_cast<const __ClangOffloadBundleHeader*>(data);
const auto obheader = reinterpret_cast<const __ClangOffloadBundleHeader*>(fbwrapper->binary);
const auto* desc = &obheader->desc[0]; const auto* desc = &obheader->desc[0];
unsigned num_code_objs = 0;
for (uint64_t i = 0; i < obheader->numBundles; ++i, for (uint64_t i = 0; i < obheader->numBundles; ++i,
desc = reinterpret_cast<const __ClangOffloadBundleDesc*>( desc = reinterpret_cast<const __ClangOffloadBundleDesc*>(
reinterpret_cast<uintptr_t>(&desc->triple[0]) + desc->tripleSize)) { reinterpret_cast<uintptr_t>(&desc->triple[0]) + desc->tripleSize)) {
@@ -109,20 +106,54 @@ extern "C" std::vector< std::pair<hipModule_t, bool> >* __hipRegisterFatBinary(c
reinterpret_cast<uintptr_t>(obheader) + desc->offset); reinterpret_cast<uintptr_t>(obheader) + desc->offset);
size_t size = desc->size; size_t size = desc->size;
for (size_t dev = 0; dev < g_devices.size(); ++dev) { for (size_t dev = 0; dev < devices.size(); ++dev) {
amd::Context* ctx = g_devices[dev]; const char* name = devices[dev];
if (!isCompatibleCodeObject(target, ctx->devices()[0]->info().name_)) { if (!isCompatibleCodeObject(target, name)) {
continue; continue;
} }
code_objs[dev] = std::make_pair(image, size);
num_code_objs++;
}
}
if (num_code_objs == devices.size())
return true;
else
return false;
}
amd::Program* program = new amd::Program(*ctx); extern "C" std::vector< std::pair<hipModule_t, bool> >* __hipRegisterFatBinary(const void* data)
if (program == nullptr) { {
return nullptr; HIP_INIT();
}
if (CL_SUCCESS == program->addDeviceProgram(*ctx->devices()[0], image, size)) { if(g_devices.empty()) {
programs->at(dev) = std::make_pair(reinterpret_cast<hipModule_t>(as_cl(program)) , false); return nullptr;
} }
const __CudaFatBinaryWrapper* fbwrapper = reinterpret_cast<const __CudaFatBinaryWrapper*>(data);
if (fbwrapper->magic != __hipFatMAGIC2 || fbwrapper->version != 1) {
return nullptr;
}
std::vector<const char*> devices;
std::vector<std::pair<const void*, size_t>> code_objs;
for (size_t dev = 0; dev < g_devices.size(); ++dev) {
amd::Context* ctx = g_devices[dev];
devices.push_back(ctx->devices()[0]->info().name_);
}
if (!__hipExtractCodeObjectFromFatBinary((char*)fbwrapper->binary, devices, code_objs)) {
return nullptr;
}
auto programs = new std::vector< std::pair<hipModule_t, bool> >{g_devices.size()};
for (size_t dev = 0; dev < g_devices.size(); ++dev) {
amd::Context* ctx = g_devices[dev];
amd::Program* program = new amd::Program(*ctx);
if (program == nullptr) {
return nullptr;
}
if (CL_SUCCESS == program->addDeviceProgram(*ctx->devices()[0], code_objs[dev].first, code_objs[dev].second)) {
programs->at(dev) = std::make_pair(reinterpret_cast<hipModule_t>(as_cl(program)) , false);
} }
} }