Introduce hash key to HIP module implementation

A hash calculated via FNV-1a algorithm is introduced in ihipModule_t, the
internal of hipModule_t. The hash is used by HIP module APIs such as

- read_agent_global_from_module

to determine whether the agent-scope globals for a module have been iterated.

This commit fixes one issue that applications which load / unload modules
frequently would occasionally fail. After deep investigation of the issue it
turns out the old implementation in read_agent_global_from_module uses
hipModule_t as the key, which is not robust enough, as hipModule_t instances
are allocated dynamically so there are cases that one memory address may be
used by multiple hipModule_t instances. The real solution is to introduce a
uniquely identifiable hash for the code object associated with the HIP module.
And that's the rationale behind this commit.
This commit is contained in:
Wen-Heng (Jack) Chung
2019-01-08 17:18:06 +00:00
parent 7637504776
commit b4d658a48f
2 changed files with 32 additions and 10 deletions
+31 -10
View File
@@ -55,6 +55,21 @@ using namespace ELFIO;
using namespace hip_impl;
using namespace std;
// calculate MD5 checksum
inline std::string checksum(size_t size, const char *source) {
// FNV-1a hashing, 64-bit version
const uint64_t FNV_prime = 0x100000001b3;
const uint64_t FNV_basis = 0xcbf29ce484222325;
uint64_t hash = FNV_basis;
const char *str = static_cast<const char *>(source);
for (auto i = 0; i < size; ++i) {
hash ^= *str++;
hash *= FNV_prime;
}
return std::to_string(hash);
}
inline uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
assert(Align != 0u && "Align can't be 0.");
Skew %= Align;
@@ -332,21 +347,21 @@ pair<hipDeviceptr_t, size_t> read_global_description(ForwardIterator f, ForwardI
hipError_t read_agent_global_from_module(hipDeviceptr_t* dptr, size_t* bytes, hipModule_t hmod,
const char* name) {
static unordered_map<hipModule_t, vector<Agent_global>> agent_globals;
// the key of the map would the hash of code object associated with the
// hipModule_t instance
static unordered_map<std::string, vector<Agent_global>> agent_globals;
auto key = hmod->hash;
// TODO: this is not particularly robust.
if (agent_globals.count(hmod) == 0) {
if (agent_globals.count(key) == 0) {
static mutex mtx;
lock_guard<mutex> lck{mtx};
if (agent_globals.count(hmod) == 0) {
agent_globals.emplace(hmod, read_agent_globals(this_agent(), hmod->executable));
if (agent_globals.count(key) == 0) {
agent_globals.emplace(key, read_agent_globals(this_agent(), hmod->executable));
}
}
// TODO: This is unsafe iff some other emplacement triggers rehashing.
// It will have to be properly fleshed out in the future.
const auto it0 = agent_globals.find(hmod);
const auto it0 = agent_globals.find(key);
if (it0 == agent_globals.cend()) {
throw runtime_error{"agent_globals data structure corrupted."};
}
@@ -568,8 +583,14 @@ hipError_t ihipModuleLoadData(hipModule_t* module, const void* image) {
auto tmp = code_object_blob_for_agent(image, this_agent());
(*module)->executable = hip_impl::load_executable(
tmp.empty() ? read_elf_file_as_string(image) : tmp, (*module)->executable, this_agent());
auto content = tmp.empty() ? read_elf_file_as_string(image) : tmp;
(*module)->executable = hip_impl::load_executable(content,
(*module)->executable,
this_agent());
// compute the hash of the code object
(*module)->hash = checksum(content.length(), content.data());
return (*module)->executable.handle ? hipSuccess : hipErrorUnknown;
}