Merge pull request #1140 from scchan/program_state_stage_2-rebase-20190524

migrate more program_state logic from header into shared library (phase II)

[ROCm/hip commit: 7013f87885]
This commit is contained in:
Maneesh Gupta
2019-06-05 16:09:01 +05:30
committed by GitHub
8 changed files with 309 additions and 269 deletions
@@ -22,7 +22,6 @@ THE SOFTWARE.
#pragma once
#include "code_object_bundle.hpp"
#include "concepts.hpp"
#include "helpers.hpp"
#include "program_state.hpp"
@@ -57,10 +56,10 @@ template <
std::size_t n,
typename... Ts,
typename std::enable_if<n == sizeof...(Ts)>::type* = nullptr>
inline std::vector<std::uint8_t> make_kernarg(
inline hip_impl::kernarg make_kernarg(
const std::tuple<Ts...>&,
const kernargs_size_align&,
std::vector<std::uint8_t> kernarg) {
hip_impl::kernarg kernarg) {
return kernarg;
}
@@ -68,10 +67,10 @@ template <
std::size_t n,
typename... Ts,
typename std::enable_if<n != sizeof...(Ts)>::type* = nullptr>
inline std::vector<std::uint8_t> make_kernarg(
inline hip_impl::kernarg make_kernarg(
const std::tuple<Ts...>& formals,
const kernargs_size_align& size_align,
std::vector<std::uint8_t> kernarg) {
hip_impl::kernarg kernarg) {
using T = typename std::tuple_element<n, std::tuple<Ts...>>::type;
static_assert(
@@ -96,7 +95,7 @@ inline std::vector<std::uint8_t> make_kernarg(
}
template <typename... Formals, typename... Actuals>
inline std::vector<std::uint8_t> make_kernarg(
inline hip_impl::kernarg make_kernarg(
void (*kernel)(Formals...), std::tuple<Actuals...> actuals) {
static_assert(sizeof...(Formals) == sizeof...(Actuals),
"The count of formal arguments must match the count of actuals.");
@@ -104,7 +103,7 @@ inline std::vector<std::uint8_t> make_kernarg(
if (sizeof...(Formals) == 0) return {};
std::tuple<Formals...> to_formals{std::move(actuals)};
std::vector<std::uint8_t> kernarg;
hip_impl::kernarg kernarg;
kernarg.reserve(sizeof(to_formals));
auto& ps = hip_impl::get_program_state();
@@ -84,12 +84,21 @@ struct is_callable_impl<F(Ts...), 4u, void_t_<decltype(std::declval<F>()(std::de
// Not callable.
template <FunctionalProcedure F>
struct is_callable_impl<F, 5u> : std::false_type {};
#else
#elif (__cplusplus < 201703L)
template <typename, typename = void>
struct is_callable_impl : std::false_type {};
template <FunctionalProcedure F, typename... Ts>
struct is_callable_impl<F(Ts...), void_t_<std::result_of_t<F(Ts...)> > > : std::true_type {};
#else
// C++17
template <typename, typename = void>
struct is_callable_impl : std::false_type {};
template <FunctionalProcedure F, typename... Ts>
struct is_callable_impl<F(Ts...), void_t_<std::invoke_result<F(Ts...)> > > : std::true_type {};
#endif
template <typename Call>
struct is_callable : is_callable_impl<Call> {};
@@ -2599,180 +2599,41 @@ hipError_t hipModuleGetFunction(hipFunction_t* function, hipModule_t module, con
hipError_t hipFuncGetAttributes(struct hipFuncAttributes* attr, const void* func);
struct Agent_global {
Agent_global() : name(nullptr), address(nullptr), byte_cnt(0) {}
Agent_global(const char* name, hipDeviceptr_t address, uint32_t byte_cnt)
: name(nullptr), address(address), byte_cnt(byte_cnt) {
if (name)
this->name = strdup(name);
}
Agent_global& operator=(Agent_global&& t) {
if (this == &t) return *this;
if (name) free(name);
name = t.name;
address = t.address;
byte_cnt = t.byte_cnt;
t.name = nullptr;
t.address = nullptr;
t.byte_cnt = 0;
return *this;
}
Agent_global(Agent_global&& t)
: name(nullptr), address(nullptr), byte_cnt(0) {
*this = std::move(t);
}
// not needed, delete them to prevent bugs
Agent_global(const Agent_global&) = delete;
Agent_global& operator=(Agent_global& t) = delete;
~Agent_global() { if (name) free(name); }
char* name;
hipDeviceptr_t address;
uint32_t byte_cnt;
};
#if !__HIP_VDI__
#if defined(__cplusplus)
} // extern "C"
#endif
namespace hip_impl {
hsa_executable_t executable_for(hipModule_t);
const char* hash_for(hipModule_t);
class agent_globals_impl;
class agent_globals {
public:
agent_globals();
~agent_globals();
agent_globals(const agent_globals&) = delete;
template<typename ForwardIterator>
std::pair<hipDeviceptr_t, std::size_t> read_global_description(
ForwardIterator f, ForwardIterator l, const char* name) {
const auto it = std::find_if(f, l, [=](const Agent_global& x) {
return strcmp(x.name, name) == 0;
});
hipError_t read_agent_global_from_module(hipDeviceptr_t* dptr, size_t* bytes,
hipModule_t hmod, const char* name);
hipError_t read_agent_global_from_process(hipDeviceptr_t* dptr, size_t* bytes,
const char* name);
private:
agent_globals_impl* impl;
};
return it == l ?
std::make_pair(nullptr, 0u) : std::make_pair(it->address, it->byte_cnt);
}
std::vector<Agent_global> read_agent_globals(hsa_agent_t agent,
hsa_executable_t executable);
hsa_agent_t this_agent();
class agent_globals_impl {
private:
std::pair<
std::mutex,
std::unordered_map<
std::string, std::vector<Agent_global>>> globals_from_module;
std::unordered_map<
hsa_agent_t,
std::pair<
std::once_flag,
std::vector<Agent_global>>> globals_from_process;
public:
hipError_t read_agent_global_from_module(hipDeviceptr_t* dptr, size_t* bytes,
hipModule_t hmod, const char* name) {
// the key of the map would the hash of code object associated with the
// hipModule_t instance
std::string key(hash_for(hmod));
if (globals_from_module.second.count(key) == 0) {
std::lock_guard<std::mutex> lck{globals_from_module.first};
if (globals_from_module.second.count(key) == 0) {
globals_from_module.second.emplace(
key, read_agent_globals(this_agent(), executable_for(hmod)));
}
}
const auto it0 = globals_from_module.second.find(key);
if (it0 == globals_from_module.second.cend()) {
hip_throw(
std::runtime_error{"agent_globals data structure corrupted."});
}
std::tie(*dptr, *bytes) = read_global_description(it0->second.cbegin(),
it0->second.cend(), name);
return *dptr ? hipSuccess : hipErrorNotFound;
inline
__attribute__((visibility("hidden")))
agent_globals& get_agent_globals() {
static agent_globals ag;
return ag;
}
extern "C"
inline
__attribute__((visibility("hidden")))
hipError_t read_agent_global_from_process(hipDeviceptr_t* dptr, size_t* bytes,
const char* name) {
auto agent = this_agent();
std::call_once(globals_from_process[agent].first, [this](hsa_agent_t aa) {
std::vector<Agent_global> tmp0;
for (auto&& executable : hip_impl::get_program_state().executables(aa)) {
auto tmp1 = read_agent_globals(aa, executable);
tmp0.insert(tmp0.end(), make_move_iterator(tmp1.begin()),
make_move_iterator(tmp1.end()));
}
globals_from_process[aa].second = move(move(tmp0));
}, agent);
const auto it = globals_from_process.find(agent);
if (it == globals_from_process.cend()) return hipErrorNotInitialized;
std::tie(*dptr, *bytes) = read_global_description(it->second.second.cbegin(),
it->second.second.cend(), name);
return *dptr ? hipSuccess : hipErrorNotFound;
const char* name) {
return get_agent_globals().read_agent_global_from_process(dptr, bytes, name);
}
};
class agent_globals {
public:
agent_globals() : impl(new agent_globals_impl()) {
if (!impl)
hip_throw(
std::runtime_error{"Error when constructing agent global data structures."});
}
~agent_globals() { delete impl; }
hipError_t read_agent_global_from_module(hipDeviceptr_t* dptr, size_t* bytes,
hipModule_t hmod, const char* name) {
return impl->read_agent_global_from_module(dptr, bytes, hmod, name);
}
hipError_t read_agent_global_from_process(hipDeviceptr_t* dptr, size_t* bytes,
const char* name) {
return impl->read_agent_global_from_process(dptr, bytes, name);
}
private:
agent_globals_impl* impl;
};
inline
__attribute__((visibility("hidden")))
agent_globals& get_agent_globals() {
static agent_globals ag;
return ag;
}
extern "C"
inline
__attribute__((visibility("hidden")))
hipError_t read_agent_global_from_process(hipDeviceptr_t* dptr, size_t* bytes,
const char* name) {
return get_agent_globals().read_agent_global_from_process(dptr, bytes, name);
}
} // Namespace hip_impl.
#if defined(__cplusplus)
@@ -30,41 +30,25 @@ THE SOFTWARE.
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>
struct ihipModuleSymbol_t;
using hipFunction_t = ihipModuleSymbol_t*;
namespace std {
template<>
struct hash<hsa_agent_t> {
size_t operator()(hsa_agent_t x) const {
return hash<decltype(x.handle)>{}(x.handle);
}
};
template<>
struct hash<hsa_isa_t> {
size_t operator()(hsa_isa_t x) const {
return hash<decltype(x.handle)>{}(x.handle);
}
};
} // namespace std
inline constexpr bool operator==(hsa_agent_t x, hsa_agent_t y) {
return x.handle == y.handle;
}
inline constexpr bool operator==(hsa_isa_t x, hsa_isa_t y) {
return x.handle == y.handle;
}
namespace hip_impl {
[[noreturn]]
void hip_throw(const std::exception&);
struct kernarg_impl;
class kernarg {
public:
kernarg();
kernarg(kernarg&&);
~kernarg();
std::uint8_t* data();
std::size_t size();
void reserve(std::size_t);
void resize(std::size_t);
private:
kernarg_impl* impl;
};
class kernargs_size_align;
class program_state_impl;
@@ -72,6 +56,7 @@ class program_state {
public:
program_state();
~program_state();
program_state(const program_state&) = delete;
hipFunction_t kernel_descriptor(std::uintptr_t,
hsa_agent_t);
@@ -83,12 +68,8 @@ public:
void* global_addr_by_name(const char* name);
// to fix later
const std::vector<hsa_executable_t>& executables(hsa_agent_t agent);
program_state(const program_state&) = delete;
private:
friend class agent_globals_impl;
program_state_impl* impl;
};