SWDEV-545953 - Add Implementation for hipStreamGetId (#434)

Authored-by: Satyanvesh Dittakavi <Satyanvesh.Dittakavi@amd.com>
This commit is contained in:
systems-assistant[bot]
2025-08-26 22:47:55 +05:30
committed by GitHub
parent 832af6d472
commit 7601798fa7
9 changed files with 6376 additions and 11594 deletions
+2
View File
@@ -26,6 +26,8 @@ Full documentation for HIP is available at [rocm.docs.amd.com](https://rocm.docs
- `hipMemPrefetchAsync_v2` prefetches memory to the specified location
- `hipMemAdvise_v2` advise about the usage of a given memory range
- `hipGetDriverEntryPoint ` gets function pointer of a HIP API.
- `hipSetValidDevices` sets a default list of devices that can be used by HIP
- `hipStreamGetId` queries the id of a stream
* Changed HIP APIs
- `hipMemAllocationType` now has hip exclusive enum hipMemAllocationTypeUncached
- `hipMemCreate` now checks for hipMemAllocationTypeUncached enum from
@@ -727,6 +727,7 @@ typedef hipError_t (*t_hipStreamGetCaptureInfo_v2)(
hipGraph_t* graph_out, const hipGraphNode_t** dependencies_out, size_t* numDependencies_out);
typedef hipError_t (*t_hipStreamGetDevice)(hipStream_t stream, hipDevice_t* device);
typedef hipError_t (*t_hipStreamGetFlags)(hipStream_t stream, unsigned int* flags);
typedef hipError_t (*t_hipStreamGetId)(hipStream_t stream, unsigned long long* streamId);
typedef hipError_t (*t_hipStreamGetPriority)(hipStream_t stream, int* priority);
typedef hipError_t (*t_hipStreamIsCapturing)(hipStream_t stream,
hipStreamCaptureStatus* pCaptureStatus);
@@ -1631,6 +1632,7 @@ struct HipDispatchTable {
t_hipMemGetHandleForAddressRange hipMemGetHandleForAddressRange_fn;
// HIP_RUNTIME_API_TABLE_STEP_VERSION = 13
// removed HIP_MEMSET_NODE_PARAMS replaced by hipMemsetParams
t_hipModuleGetFunctionCount hipModuleGetFunctionCount_fn;
t_hipMemsetD2D8 hipMemsetD2D8_fn;
t_hipMemsetD2D8Async hipMemsetD2D8Async_fn;
@@ -1649,8 +1651,9 @@ struct HipDispatchTable {
t_hipGetDriverEntryPoint_spt hipGetDriverEntryPoint_spt_fn;
t_hipMemPrefetchAsync_v2 hipMemPrefetchAsync_v2_fn;
t_hipMemAdvise_v2 hipMemAdvise_v2_fn;
t_hipStreamGetId hipStreamGetId_fn;
// HIP_RUNTIME_API_TABLE_STEP_VERSION = 14
// removed HIP_MEMSET_NODE_PARAMS replaced by hipMemsetParams
// DO NOT EDIT ABOVE!
// HIP_RUNTIME_API_TABLE_STEP_VERSION == 14
File diff suppressed because it is too large Load Diff
+1
View File
@@ -510,3 +510,4 @@ hipGetDriverEntryPoint
hipGetDriverEntryPoint_spt
hipMemPrefetchAsync_v2
hipMemAdvise_v2
hipStreamGetId
+4 -1
View File
@@ -608,6 +608,7 @@ hipError_t hipStreamGetCaptureInfo_v2(hipStream_t stream, hipStreamCaptureStatus
size_t* numDependencies_out);
hipError_t hipStreamGetDevice(hipStream_t stream, hipDevice_t* device);
hipError_t hipStreamGetFlags(hipStream_t stream, unsigned int* flags);
hipError_t hipStreamGetId(hipStream_t stream, unsigned long long* streamId);
hipError_t hipStreamGetPriority(hipStream_t stream, int* priority);
hipError_t hipStreamIsCapturing(hipStream_t stream, hipStreamCaptureStatus* pCaptureStatus);
hipError_t hipStreamQuery(hipStream_t stream);
@@ -1261,6 +1262,7 @@ void UpdateDispatchTable(HipDispatchTable* ptrDispatchTable) {
ptrDispatchTable->hipStreamGetCaptureInfo_v2_fn = hip::hipStreamGetCaptureInfo_v2;
ptrDispatchTable->hipStreamGetDevice_fn = hip::hipStreamGetDevice;
ptrDispatchTable->hipStreamGetFlags_fn = hip::hipStreamGetFlags;
ptrDispatchTable->hipStreamGetId_fn = hip::hipStreamGetId;
ptrDispatchTable->hipStreamGetPriority_fn = hip::hipStreamGetPriority;
ptrDispatchTable->hipStreamIsCapturing_fn = hip::hipStreamIsCapturing;
ptrDispatchTable->hipStreamQuery_fn = hip::hipStreamQuery;
@@ -2058,13 +2060,14 @@ HIP_ENFORCE_ABI(HipDispatchTable, hipGetDriverEntryPoint_fn, 491);
HIP_ENFORCE_ABI(HipDispatchTable, hipGetDriverEntryPoint_spt_fn, 492);
HIP_ENFORCE_ABI(HipDispatchTable, hipMemPrefetchAsync_v2_fn, 493);
HIP_ENFORCE_ABI(HipDispatchTable, hipMemAdvise_v2_fn, 494);
HIP_ENFORCE_ABI(HipDispatchTable, hipStreamGetId_fn, 495);
// if HIP_ENFORCE_ABI entries are added for each new function pointer in the table, the number below
// will be +1 of the number in the last HIP_ENFORCE_ABI line. E.g.:
//
// HIP_ENFORCE_ABI(<table>, <functor>, 8)
//
// HIP_ENFORCE_ABI_VERSIONING(<table>, 9) <- 8 + 1 = 9
HIP_ENFORCE_ABI_VERSIONING(HipDispatchTable, 495)
HIP_ENFORCE_ABI_VERSIONING(HipDispatchTable, 496)
static_assert(HIP_RUNTIME_API_TABLE_MAJOR_VERSION == 0 && HIP_RUNTIME_API_TABLE_STEP_VERSION == 14,
"If you get this error, add new HIP_ENFORCE_ABI(...) code for the new function "
+1
View File
@@ -626,6 +626,7 @@ global:
hipGetDriverEntryPoint_spt;
hipMemPrefetchAsync_v2;
hipMemAdvise_v2;
hipStreamGetId;
local:
*;
} hip_6.5;
+397 -389
View File
@@ -47,22 +47,22 @@
#define KCYN "\x1B[36m"
#define KWHT "\x1B[37m"
namespace hip {
extern std::once_flag g_ihipInitialized;
namespace hip{
extern std::once_flag g_ihipInitialized;
}
typedef struct hipArray {
void* data; // FIXME: generalize this
struct hipChannelFormatDesc desc;
unsigned int type;
unsigned int width;
unsigned int height;
unsigned int depth;
enum hipArray_Format Format;
unsigned int NumChannels;
bool isDrv;
unsigned int textureType;
unsigned int flags;
} hipArray;
void* data; // FIXME: generalize this
struct hipChannelFormatDesc desc;
unsigned int type;
unsigned int width;
unsigned int height;
unsigned int depth;
enum hipArray_Format Format;
unsigned int NumChannels;
bool isDrv;
unsigned int textureType;
unsigned int flags;
}hipArray;
namespace hip {
enum MemcpyType {
@@ -87,16 +87,16 @@ struct UserObject;
class Stream;
#define IHIP_IPC_EVENT_HANDLE_SIZE 32
#define IHIP_IPC_EVENT_RESERVED_SIZE LP64_SWITCH(28, 24)
#define IHIP_IPC_EVENT_RESERVED_SIZE LP64_SWITCH(28,24)
typedef struct ihipIpcEventHandle_st {
// hsa_amd_ipc_signal_t ipc_handle; ///< ipc signal handle on ROCr
// char ipc_handle[IHIP_IPC_EVENT_HANDLE_SIZE];
// char reserved[IHIP_IPC_EVENT_RESERVED_SIZE];
char shmem_name[IHIP_IPC_EVENT_HANDLE_SIZE];
} ihipIpcEventHandle_t;
//hsa_amd_ipc_signal_t ipc_handle; ///< ipc signal handle on ROCr
//char ipc_handle[IHIP_IPC_EVENT_HANDLE_SIZE];
//char reserved[IHIP_IPC_EVENT_RESERVED_SIZE];
char shmem_name[IHIP_IPC_EVENT_HANDLE_SIZE];
}ihipIpcEventHandle_t;
const char* ihipGetErrorName(hipError_t hip_error);
} // namespace hip
}
#define HIP_INIT(noReturn) \
{ \
@@ -122,14 +122,15 @@ const char* ihipGetErrorName(hipError_t hip_error);
}
#define HIP_API_PRINT(...) \
uint64_t startTimeUs = 0; \
HIPPrintDuration(amd::LOG_INFO, amd::LOG_API, &startTimeUs, "%s %s ( %s ) %s", KGRN, __func__, \
ToString(__VA_ARGS__).c_str(), KNRM);
#define HIP_API_PRINT(...) \
uint64_t startTimeUs = 0; \
HIPPrintDuration(amd::LOG_INFO, amd::LOG_API, &startTimeUs, \
"%s %s ( %s ) %s", KGRN, \
__func__, ToString( __VA_ARGS__ ).c_str(), KNRM);
#define HIP_ERROR_PRINT(err, ...) \
ClPrint(amd::LOG_INFO, amd::LOG_API, "%s: Returned %s : %s", __func__, \
hip::ihipGetErrorName(err), ToString(__VA_ARGS__).c_str());
#define HIP_ERROR_PRINT(err, ...) \
ClPrint(amd::LOG_INFO, amd::LOG_API, "%s: Returned %s : %s", \
__func__, hip::ihipGetErrorName(err), ToString( __VA_ARGS__ ).c_str());
#define HIP_INIT_API_INTERNAL(noReturn, cid, ...) \
HIP_INIT(noReturn) \
@@ -138,15 +139,16 @@ const char* ihipGetErrorName(hipError_t hip_error);
// This macro should be called at the beginning of every HIP API.
#define HIP_INIT_API(cid, ...) \
if (amd::Device::IsGPUInError()) { \
if (amd::Device::IsGPUInError()) { \
HIP_RETURN(ConvertCLErrorIntoHIPError(amd::Device::GetGPUError())); \
} \
HIP_INIT_API_INTERNAL(0, cid, __VA_ARGS__) \
if (hip::g_devices.size() == 0) { \
HIP_RETURN(hipErrorNoDevice); \
}
} \
#define HIP_INIT_API_NO_RETURN(cid, ...) HIP_INIT_API_INTERNAL(1, cid, __VA_ARGS__)
#define HIP_INIT_API_NO_RETURN(cid, ...) \
HIP_INIT_API_INTERNAL(1, cid, __VA_ARGS__)
#define HIP_RETURN_DURATION(ret, ...) \
hip::tls.last_command_error_ = ret; \
@@ -156,7 +158,7 @@ const char* ihipGetErrorName(hipError_t hip_error);
hip::tls.last_command_error_ = hip_error; \
} else { \
if (hip::tls.last_command_error_ != hipSuccess && \
hip::tls.last_command_error_ != hipErrorNotReady) { \
hip::tls.last_command_error_ != hipErrorNotReady) { \
hip::tls.last_error_ = hip::tls.last_command_error_; \
} \
} \
@@ -173,29 +175,29 @@ const char* ihipGetErrorName(hipError_t hip_error);
hip::tls.last_command_error_ = hip_error; \
} else { \
if (hip::tls.last_command_error_ != hipSuccess && \
hip::tls.last_command_error_ != hipErrorNotReady) { \
hip::tls.last_command_error_ != hipErrorNotReady) { \
hip::tls.last_error_ = hip::tls.last_command_error_; \
} \
} \
HIP_ERROR_PRINT(hip::tls.last_command_error_, __VA_ARGS__) \
return hip::tls.last_command_error_;
#define HIP_RETURN_ONFAIL(func) \
do { \
hipError_t herror = (func); \
if (herror != hipSuccess) { \
HIP_RETURN(herror); \
} \
#define HIP_RETURN_ONFAIL(func) \
do { \
hipError_t herror = (func); \
if (herror != hipSuccess) { \
HIP_RETURN(herror); \
} \
} while (0);
// Cannot be use in place of HIP_RETURN.
// Refrain from using for external HIP APIs
#define IHIP_RETURN_ONFAIL(func) \
do { \
hipError_t herror = (func); \
if (herror != hipSuccess) { \
return herror; \
} \
#define IHIP_RETURN_ONFAIL(func) \
do { \
hipError_t herror = (func); \
if (herror != hipSuccess) { \
return herror; \
} \
} while (0);
// During stream capture some actions, such as a call to hipMalloc, may be unsafe and prohibited
@@ -256,15 +258,15 @@ const char* ihipGetErrorName(hipError_t hip_error);
return hipErrorStreamCaptureInvalidated; \
}
#define PER_THREAD_DEFAULT_STREAM(stream) \
if (stream == nullptr || stream == hipStreamLegacy) { \
stream = getPerThreadDefaultStream(); \
#define PER_THREAD_DEFAULT_STREAM(stream) \
if (stream == nullptr || stream == hipStreamLegacy) { \
stream = getPerThreadDefaultStream(); \
}
namespace hc {
class accelerator;
class accelerator_view;
}; // namespace hc
};
struct ihipExec_t {
dim3 gridDim_;
@@ -276,420 +278,426 @@ struct ihipExec_t {
namespace hip {
class stream_per_thread {
private:
private:
std::vector<hipStream_t> m_streams;
public:
public:
stream_per_thread();
stream_per_thread(const stream_per_thread&) = delete;
void operator=(const stream_per_thread&) = delete;
stream_per_thread(const stream_per_thread& ) = delete;
void operator=(const stream_per_thread& ) = delete;
~stream_per_thread();
hipStream_t get();
void clear_spt();
};
class Device;
class MemoryPool;
class Event;
class Stream : public amd::HostQueue {
public:
enum Priority : int { High = -1, Normal = 0, Low = 1 };
class Device;
class MemoryPool;
class Event;
class Stream : public amd::HostQueue {
public:
enum Priority : int { High = -1, Normal = 0, Low = 1 };
private:
mutable amd::Monitor lock_;
Device* device_;
Priority priority_;
unsigned int flags_;
bool null_;
const std::vector<uint32_t> cuMask_;
private:
mutable amd::Monitor lock_;
Device* device_;
Priority priority_;
unsigned int flags_;
bool null_;
const std::vector<uint32_t> cuMask_;
uint64_t stream_id_;
/// Stream capture related parameters
/// Stream capture related parameters
/// Current capture status of the stream
hipStreamCaptureStatus captureStatus_;
/// Graph that is constructed with capture
hip::Graph* pCaptureGraph_;
/// Based on mode stream capture places restrictions on API calls that can be made within or
/// concurrently
hipStreamCaptureMode captureMode_{hipStreamCaptureModeGlobal};
bool originStream_;
/// Origin sream has no parent. Parent stream for the derived captured streams with event
/// dependencies
hipStream_t parentStream_ = nullptr;
/// Last graph node captured in the stream
std::vector<hip::GraphNode*> lastCapturedNodes_;
/// dependencies removed via API hipStreamUpdateCaptureDependencies
std::vector<hip::GraphNode*> removedDependencies_;
/// Derived streams/Paralell branches from the origin stream
std::vector<hipStream_t> parallelCaptureStreams_;
/// Capture events
std::unordered_set<hipEvent_t> captureEvents_;
unsigned long long captureID_;
/// Current capture status of the stream
hipStreamCaptureStatus captureStatus_;
/// Graph that is constructed with capture
hip::Graph* pCaptureGraph_;
/// Based on mode stream capture places restrictions on API calls that can be made within or
/// concurrently
hipStreamCaptureMode captureMode_{hipStreamCaptureModeGlobal};
bool originStream_;
/// Origin sream has no parent. Parent stream for the derived captured streams with event
/// dependencies
hipStream_t parentStream_ = nullptr;
/// Last graph node captured in the stream
std::vector<hip::GraphNode*> lastCapturedNodes_;
/// dependencies removed via API hipStreamUpdateCaptureDependencies
std::vector<hip::GraphNode*> removedDependencies_;
/// Derived streams/Paralell branches from the origin stream
std::vector<hipStream_t> parallelCaptureStreams_;
/// Capture events
std::unordered_set<hipEvent_t> captureEvents_;
unsigned long long captureID_;
static inline CommandQueue::Priority convertToQueuePriority(Priority p) {
return p == Priority::High ? amd::CommandQueue::Priority::High
: p == Priority::Low ? amd::CommandQueue::Priority::Low
: amd::CommandQueue::Priority::Normal;
}
static inline CommandQueue::Priority convertToQueuePriority(Priority p) {
return p == Priority::High ? amd::CommandQueue::Priority::High : p == Priority::Low ?
amd::CommandQueue::Priority::Low : amd::CommandQueue::Priority::Normal;
}
/// Generates unique stream Id for the lifetime of the process
uint64_t GenerateStreamId() {
static std::atomic<uint64_t> uniqueId{0};
return ++uniqueId;
}
public:
Stream(Device* dev, Priority p = Priority::Normal, unsigned int f = 0, bool null_stream = false,
const std::vector<uint32_t>& cuMask = {},
hipStreamCaptureStatus captureStatus = hipStreamCaptureStatusNone);
public:
Stream(Device* dev, Priority p = Priority::Normal, unsigned int f = 0, bool null_stream = false,
const std::vector<uint32_t>& cuMask = {},
hipStreamCaptureStatus captureStatus = hipStreamCaptureStatusNone);
/// Creates the hip stream object, including AMD host queue
bool Create();
/// Get device ID associated with the current stream;
int DeviceId() const;
/// Get HIP device associated with the stream
Device* GetDevice() const { return device_; }
/// Get device ID associated with a stream;
static int DeviceId(const hipStream_t hStream);
/// Returns if stream is null stream
bool Null() const { return null_; }
/// Returns the lock object for the current stream
amd::Monitor& Lock() const { return lock_; }
/// Returns the creation flags for the current stream
unsigned int Flags() const { return flags_; }
/// Returns the priority for the current stream
Priority GetPriority() const { return priority_; }
/// Returns the CU mask for the current stream
const std::vector<uint32_t> GetCUMask() const { return cuMask_; }
/// Creates the hip stream object, including AMD host queue
bool Create();
/// Get device ID associated with the current stream;
int DeviceId() const;
/// Get HIP device associated with the stream
Device* GetDevice() const { return device_; }
/// Get device ID associated with a stream;
static int DeviceId(const hipStream_t hStream);
/// Returns if stream is null stream
bool Null() const { return null_; }
/// Returns the lock object for the current stream
amd::Monitor& Lock() const { return lock_; }
/// Returns the creation flags for the current stream
unsigned int Flags() const { return flags_; }
/// Returns the priority for the current stream
Priority GetPriority() const { return priority_; }
/// Returns the CU mask for the current stream
const std::vector<uint32_t> GetCUMask() const { return cuMask_; }
/// Check whether any blocking stream running
static bool StreamCaptureBlocking();
/// Fetch the stream Id
uint64_t GetStreamId() const { return stream_id_; }
/// Check whether any blocking stream running
static bool StreamCaptureBlocking();
static void Destroy(hip::Stream* stream, bool forceDestroy = false);
static void Destroy(hip::Stream* stream, bool forceDestroy = false);
virtual bool terminate();
virtual bool terminate();
/// Check Stream Capture status to make sure it is done
static bool StreamCaptureOngoing(hipStream_t hStream);
/// Check Stream Capture status to make sure it is done
static bool StreamCaptureOngoing(hipStream_t hStream);
/// Returns capture status of the current stream
hipStreamCaptureStatus GetCaptureStatus() const { return captureStatus_; }
/// Returns capture mode of the current stream
hipStreamCaptureMode GetCaptureMode() const { return captureMode_; }
/// Returns if stream is origin stream
bool IsOriginStream() const { return originStream_; }
void SetOriginStream() { originStream_ = true; }
/// Returns captured graph
hip::Graph* GetCaptureGraph() const { return pCaptureGraph_; }
/// Returns last captured graph node
const std::vector<hip::GraphNode*>& GetLastCapturedNodes() const { return lastCapturedNodes_; }
/// Set last captured graph node
void SetLastCapturedNode(hip::GraphNode* graphNode) {
lastCapturedNodes_.clear();
lastCapturedNodes_.push_back(graphNode);
}
/// returns updated dependencies removed
const std::vector<hip::GraphNode*>& GetRemovedDependencies() { return removedDependencies_; }
/// Append captured node via the wait event cross stream
void AddCrossCapturedNode(std::vector<hip::GraphNode*> graphNodes, bool replace = false) {
// replace dependencies as per flag hipStreamSetCaptureDependencies
if (replace == true) {
for (auto node : lastCapturedNodes_) {
removedDependencies_.push_back(node);
}
/// Returns capture status of the current stream
hipStreamCaptureStatus GetCaptureStatus() const { return captureStatus_; }
/// Returns capture mode of the current stream
hipStreamCaptureMode GetCaptureMode() const { return captureMode_; }
/// Returns if stream is origin stream
bool IsOriginStream() const { return originStream_; }
void SetOriginStream() { originStream_ = true; }
/// Returns captured graph
hip::Graph* GetCaptureGraph() const { return pCaptureGraph_; }
/// Returns last captured graph node
const std::vector<hip::GraphNode*>& GetLastCapturedNodes() const { return lastCapturedNodes_; }
/// Set last captured graph node
void SetLastCapturedNode(hip::GraphNode* graphNode) {
lastCapturedNodes_.clear();
lastCapturedNodes_.push_back(graphNode);
}
for (auto node : graphNodes) {
if (std::find(lastCapturedNodes_.begin(), lastCapturedNodes_.end(), node) ==
lastCapturedNodes_.end()) {
lastCapturedNodes_.push_back(node);
/// returns updated dependencies removed
const std::vector<hip::GraphNode*>& GetRemovedDependencies() {
return removedDependencies_;
}
/// Append captured node via the wait event cross stream
void AddCrossCapturedNode(std::vector<hip::GraphNode*> graphNodes, bool replace = false) {
// replace dependencies as per flag hipStreamSetCaptureDependencies
if (replace == true) {
for (auto node : lastCapturedNodes_) {
removedDependencies_.push_back(node);
}
lastCapturedNodes_.clear();
}
for (auto node : graphNodes) {
if (std::find(lastCapturedNodes_.begin(), lastCapturedNodes_.end(), node) ==
lastCapturedNodes_.end()) {
lastCapturedNodes_.push_back(node);
}
}
}
}
/// Set graph that is being captured
void SetCaptureGraph(hip::Graph* pGraph) {
pCaptureGraph_ = pGraph;
captureStatus_ = hipStreamCaptureStatusActive;
}
/// Reset graph to nullptr when capture is invalidated, but keep the status
void ResetCaptureGraph() { pCaptureGraph_ = nullptr; }
void SetCaptureId() {
// ID is generated in Begin Capture i.e.. when capture status is active
captureID_ = GenerateCaptureID();
}
void SetCaptureId(unsigned long long captureId) {
// ID is given from parent stream
captureID_ = captureId;
}
/// reset capture parameters
hipError_t EndCapture();
/// Set capture status
void SetCaptureStatus(hipStreamCaptureStatus captureStatus) { captureStatus_ = captureStatus; }
/// Set capture mode
void SetCaptureMode(hipStreamCaptureMode captureMode) { captureMode_ = captureMode; }
/// Set parent stream
void SetParentStream(hipStream_t parentStream) { parentStream_ = parentStream; }
/// Get parent stream
hipStream_t GetParentStream() const { return parentStream_; }
/// Generate ID for stream capture unique over the lifetime of the process
static unsigned long long GenerateCaptureID() {
static std::atomic<unsigned long long> uid(0);
return ++uid;
}
/// Get Capture ID
unsigned long long GetCaptureID() { return captureID_; }
void SetCaptureEvent(hipEvent_t e) {
amd::ScopedLock lock(lock_);
captureEvents_.emplace(e);
}
bool IsEventCaptured(hipEvent_t e) {
amd::ScopedLock lock(lock_);
auto it = captureEvents_.find(e);
if (it != captureEvents_.end()) {
return true;
/// Set graph that is being captured
void SetCaptureGraph(hip::Graph* pGraph) {
pCaptureGraph_ = pGraph;
captureStatus_ = hipStreamCaptureStatusActive;
}
return false;
}
void EraseCaptureEvent(hipEvent_t e) {
amd::ScopedLock lock(lock_);
auto it = captureEvents_.find(e);
if (it != captureEvents_.end()) {
captureEvents_.erase(it);
/// Reset graph to nullptr when capture is invalidated, but keep the status
void ResetCaptureGraph() { pCaptureGraph_ = nullptr; }
void SetCaptureId() {
// ID is generated in Begin Capture i.e.. when capture status is active
captureID_ = GenerateCaptureID();
}
}
void SetParallelCaptureStream(hipStream_t s) {
auto it = std::find(parallelCaptureStreams_.begin(), parallelCaptureStreams_.end(), s);
if (it == parallelCaptureStreams_.end()) {
parallelCaptureStreams_.push_back(s);
void SetCaptureId(unsigned long long captureId) {
// ID is given from parent stream
captureID_ = captureId;
}
}
void EraseParallelCaptureStream(hipStream_t s) {
auto it = std::find(parallelCaptureStreams_.begin(), parallelCaptureStreams_.end(), s);
if (it != parallelCaptureStreams_.end()) {
parallelCaptureStreams_.erase(it);
/// reset capture parameters
hipError_t EndCapture();
/// Set capture status
void SetCaptureStatus(hipStreamCaptureStatus captureStatus) { captureStatus_ = captureStatus; }
/// Set capture mode
void SetCaptureMode(hipStreamCaptureMode captureMode) { captureMode_ = captureMode; }
/// Set parent stream
void SetParentStream(hipStream_t parentStream) { parentStream_ = parentStream; }
/// Get parent stream
hipStream_t GetParentStream() const { return parentStream_; }
/// Generate ID for stream capture unique over the lifetime of the process
static unsigned long long GenerateCaptureID() {
static std::atomic<unsigned long long> uid(0);
return ++uid;
}
/// Get Capture ID
unsigned long long GetCaptureID() { return captureID_; }
void SetCaptureEvent(hipEvent_t e) {
amd::ScopedLock lock(lock_);
captureEvents_.emplace(e); }
bool IsEventCaptured(hipEvent_t e) {
amd::ScopedLock lock(lock_);
auto it = captureEvents_.find(e);
if (it != captureEvents_.end()) {
return true;
}
return false;
}
void EraseCaptureEvent(hipEvent_t e) {
amd::ScopedLock lock(lock_);
auto it = captureEvents_.find(e);
if (it != captureEvents_.end()) {
captureEvents_.erase(it);
}
}
void SetParallelCaptureStream(hipStream_t s) {
auto it = std::find(parallelCaptureStreams_.begin(), parallelCaptureStreams_.end(), s);
if (it == parallelCaptureStreams_.end()) {
parallelCaptureStreams_.push_back(s);
}
}
void EraseParallelCaptureStream(hipStream_t s) {
auto it = std::find(parallelCaptureStreams_.begin(), parallelCaptureStreams_.end(), s);
if (it != parallelCaptureStreams_.end()) {
parallelCaptureStreams_.erase(it);
}
}
}
/// The stream should be destroyed via release() rather than delete
private:
~Stream() {};
};
/// The stream should be destroyed via release() rather than delete
private:
~Stream() {};
};
/// HIP Device class
class Device : public amd::ReferenceCountedObject {
// Device lock
amd::Monitor lock_{true};
// Guards device stream set
std::shared_mutex streamSetLock;
std::unordered_set<hip::Stream*> streamSet;
/// ROCclr context
amd::Context* context_;
/// Device's ID
/// Store it here so we don't have to loop through the device list every time
int deviceId_;
/// ROCclr host queue for default streams
Stream* null_stream_ = nullptr;
/// Store device flags
unsigned int flags_;
/// Maintain list of user enabled peers
std::list<int> userEnabledPeers;
/// HIP Device class
class Device : public amd::ReferenceCountedObject {
// Device lock
amd::Monitor lock_{true};
// Guards device stream set
std::shared_mutex streamSetLock;
std::unordered_set<hip::Stream*> streamSet;
/// ROCclr context
amd::Context* context_;
/// Device's ID
/// Store it here so we don't have to loop through the device list every time
int deviceId_;
/// ROCclr host queue for default streams
Stream* null_stream_ = nullptr;
/// Store device flags
unsigned int flags_;
/// Maintain list of user enabled peers
std::list<int> userEnabledPeers;
/// True if this device is active
bool isActive_;
/// True if this device is active
bool isActive_;
MemoryPool* default_mem_pool_; //!< Default memory pool for this device
MemoryPool* current_mem_pool_;
MemoryPool* graph_mem_pool_; //!< Memory pool, associated with graphs for this device
MemoryPool* default_mem_pool_; //!< Default memory pool for this device
MemoryPool* current_mem_pool_;
MemoryPool* graph_mem_pool_; //!< Memory pool, associated with graphs for this device
std::set<MemoryPool*> mem_pools_;
std::set<MemoryPool*> mem_pools_;
public:
Device(amd::Context* ctx, int devId)
: context_(ctx),
public:
Device(amd::Context* ctx, int devId): context_(ctx),
deviceId_(devId),
flags_(hipDeviceScheduleSpin),
flags_(hipDeviceScheduleSpin),
isActive_(false),
default_mem_pool_(nullptr),
current_mem_pool_(nullptr),
graph_mem_pool_(nullptr) {
assert(ctx != nullptr);
}
~Device();
graph_mem_pool_(nullptr)
{ assert(ctx != nullptr); }
~Device();
bool Create();
amd::Context* asContext() const { return context_; }
int deviceId() const { return deviceId_; }
void retain() const { context_->retain(); }
void release() const { context_->release(); }
const std::vector<amd::Device*>& devices() const { return context_->devices(); }
hipError_t EnablePeerAccess(int peerDeviceId) {
amd::ScopedLock lock(lock_);
bool found = (std::find(userEnabledPeers.begin(), userEnabledPeers.end(), peerDeviceId) !=
userEnabledPeers.end());
if (found) {
return hipErrorPeerAccessAlreadyEnabled;
}
userEnabledPeers.push_back(peerDeviceId);
return hipSuccess;
}
hipError_t DisablePeerAccess(int peerDeviceId) {
amd::ScopedLock lock(lock_);
bool found = (std::find(userEnabledPeers.begin(), userEnabledPeers.end(), peerDeviceId) !=
userEnabledPeers.end());
if (found) {
userEnabledPeers.remove(peerDeviceId);
bool Create();
amd::Context* asContext() const { return context_; }
int deviceId() const { return deviceId_; }
void retain() const { context_->retain(); }
void release() const { context_->release(); }
const std::vector<amd::Device*>& devices() const { return context_->devices(); }
hipError_t EnablePeerAccess(int peerDeviceId){
amd::ScopedLock lock(lock_);
bool found = (std::find(userEnabledPeers.begin(), userEnabledPeers.end(), peerDeviceId) != userEnabledPeers.end());
if (found) {
return hipErrorPeerAccessAlreadyEnabled;
}
userEnabledPeers.push_back(peerDeviceId);
return hipSuccess;
} else {
return hipErrorPeerAccessNotEnabled;
}
}
unsigned int getFlags() const { return flags_; }
void setFlags(unsigned int flags) { flags_ = flags; }
void Reset();
hipError_t DisablePeerAccess(int peerDeviceId) {
amd::ScopedLock lock(lock_);
bool found = (std::find(userEnabledPeers.begin(), userEnabledPeers.end(), peerDeviceId) != userEnabledPeers.end());
if (found) {
userEnabledPeers.remove(peerDeviceId);
return hipSuccess;
} else {
return hipErrorPeerAccessNotEnabled;
}
}
unsigned int getFlags() const { return flags_; }
void setFlags(unsigned int flags) { flags_ = flags; }
void Reset();
hip::Stream* NullStream(bool wait = true);
Stream* GetNullStream() const { return null_stream_; };
hip::Stream* NullStream(bool wait = true);
Stream* GetNullStream() const {return null_stream_;};
void SetActiveStatus() { isActive_ = true; }
bool GetActiveStatus() {
amd::ScopedLock lock(lock_);
/// Either stream is active or device is active
if (isActive_) return true;
if (existsActiveStreamForDevice()) {
void SetActiveStatus() {
isActive_ = true;
return true;
}
return false;
}
/// Set the current memory pool on the device
void SetCurrentMemoryPool(MemoryPool* pool = nullptr) {
current_mem_pool_ = (pool == nullptr) ? default_mem_pool_ : pool;
}
bool GetActiveStatus() {
amd::ScopedLock lock(lock_);
/// Either stream is active or device is active
if (isActive_) return true;
if (existsActiveStreamForDevice()) {
isActive_ = true;
return true;
}
return false;
}
/// Get the current memory pool on the device
MemoryPool* GetCurrentMemoryPool() const { return current_mem_pool_; }
/// Set the current memory pool on the device
void SetCurrentMemoryPool(MemoryPool* pool = nullptr) {
current_mem_pool_ = (pool == nullptr) ? default_mem_pool_ : pool;
}
/// Get the default memory pool on the device
MemoryPool* GetDefaultMemoryPool() const { return default_mem_pool_; }
/// Get the current memory pool on the device
MemoryPool* GetCurrentMemoryPool() const { return current_mem_pool_; }
/// Get the graph memory pool on the device
MemoryPool* GetGraphMemoryPool() const { return graph_mem_pool_; }
/// Get the default memory pool on the device
MemoryPool* GetDefaultMemoryPool() const { return default_mem_pool_; }
/// Add memory pool to the device
void AddMemoryPool(MemoryPool* pool);
/// Get the graph memory pool on the device
MemoryPool* GetGraphMemoryPool() const { return graph_mem_pool_; }
/// Remove memory pool from the device
void RemoveMemoryPool(MemoryPool* pool);
/// Add memory pool to the device
void AddMemoryPool(MemoryPool* pool);
/// Free memory from the device
bool FreeMemory(amd::Memory* memory, Stream* stream, Event* event = nullptr);
/// Remove memory pool from the device
void RemoveMemoryPool(MemoryPool* pool);
/// Release freed memory from all pools on the current device
void ReleaseFreedMemory();
/// Free memory from the device
bool FreeMemory(amd::Memory* memory, Stream* stream, Event* event = nullptr);
/// Removes a destroyed stream from the safe list of memory pools
void RemoveStreamFromPools(Stream* stream);
/// Release freed memory from all pools on the current device
void ReleaseFreedMemory();
/// Add safe streams into the memppools for reuse
void AddSafeStream(Stream* event_stream, Stream* wait_stream);
/// Removes a destroyed stream from the safe list of memory pools
void RemoveStreamFromPools(Stream* stream);
/// Returns true if memory pool is valid on this device
bool IsMemoryPoolValid(MemoryPool* pool);
void AddStream(Stream* stream);
/// Add safe streams into the memppools for reuse
void AddSafeStream(Stream* event_stream, Stream* wait_stream);
void RemoveStream(Stream* stream);
/// Returns true if memory pool is valid on this device
bool IsMemoryPoolValid(MemoryPool* pool);
void AddStream(Stream* stream);
bool StreamExists(Stream* stream);
void RemoveStream(Stream* stream);
void destroyAllStreams();
bool StreamExists(Stream* stream);
void SyncAllStreams(bool cpu_wait = true, bool wait_blocking_streams_only = false);
void destroyAllStreams();
bool StreamCaptureBlocking();
void SyncAllStreams( bool cpu_wait = true, bool wait_blocking_streams_only = false);
bool existsActiveStreamForDevice();
bool StreamCaptureBlocking();
bool existsActiveStreamForDevice();
/// Wait all active streams on the blocking queue. The method enqueues a wait command and
/// doesn't stall the current thread
void WaitActiveStreams(hip::Stream* blocking_stream, bool wait_null_stream = false);
};
void WaitActiveStreams(hip::Stream* blocking_stream, bool wait_null_stream = false);
};
/// Thread Local Storage Variables Aggregator Class
class TlsAggregator {
public:
Device* device_;
std::stack<Device*> ctxt_stack_;
hipError_t last_error_, last_command_error_;
std::vector<hip::Stream*> capture_streams_;
hipStreamCaptureMode stream_capture_mode_;
std::stack<ihipExec_t> exec_stack_;
stream_per_thread stream_per_thread_obj_;
bool isSetDeviceCalled;
/// Thread Local Storage Variables Aggregator Class
class TlsAggregator {
public:
Device* device_;
std::stack<Device*> ctxt_stack_;
hipError_t last_error_, last_command_error_;
std::vector<hip::Stream*> capture_streams_;
hipStreamCaptureMode stream_capture_mode_;
std::stack<ihipExec_t> exec_stack_;
stream_per_thread stream_per_thread_obj_;
bool isSetDeviceCalled;
TlsAggregator()
: device_(nullptr),
last_error_(hipSuccess),
last_command_error_(hipSuccess),
stream_capture_mode_(hipStreamCaptureModeGlobal),
isSetDeviceCalled(false) {}
~TlsAggregator() {}
};
extern thread_local TlsAggregator tls;
TlsAggregator(): device_(nullptr),
last_error_(hipSuccess),
last_command_error_(hipSuccess),
stream_capture_mode_(hipStreamCaptureModeGlobal),
isSetDeviceCalled(false) {
}
~TlsAggregator() {
}
};
extern thread_local TlsAggregator tls;
/// Device representing the host - for pinned memory
extern amd::Context* host_context;
/// Device representing the host - for pinned memory
extern amd::Context* host_context;
extern void init(bool* status);
extern void init(bool* status);
extern Device* getCurrentDevice();
extern Device* getCurrentDevice();
extern void setCurrentDevice(unsigned int index);
extern void setCurrentDevice(unsigned int index);
/// Get ROCclr queue associated with hipStream
/// Note: This follows the CUDA spec to sync with default streams
/// and Blocking streams
extern hip::Stream* getStream(hipStream_t stream, bool wait = true);
/// Get default stream associated with the ROCclr context
extern hip::Stream* getNullStream(amd::Context&, bool wait = true);
/// Get default stream of the thread
extern hip::Stream* getNullStream(bool wait = true);
/// Get device ID associated with the ROCclr context
int getDeviceID(amd::Context& ctx);
/// Check if stream is valid
extern bool isValid(hipStream_t& stream);
extern bool isValid(hipEvent_t event);
extern amd::Monitor hipArraySetLock;
extern std::unordered_set<hipArray*> hipArraySet;
/// Get ROCclr queue associated with hipStream
/// Note: This follows the CUDA spec to sync with default streams
/// and Blocking streams
extern hip::Stream* getStream(hipStream_t stream, bool wait = true);
/// Get default stream associated with the ROCclr context
extern hip::Stream* getNullStream(amd::Context&, bool wait = true);
/// Get default stream of the thread
extern hip::Stream* getNullStream(bool wait = true);
/// Get device ID associated with the ROCclr context
int getDeviceID(amd::Context& ctx);
/// Check if stream is valid
extern bool isValid(hipStream_t& stream);
extern bool isValid(hipEvent_t event);
extern amd::Monitor hipArraySetLock;
extern std::unordered_set<hipArray*> hipArraySet;
extern void WaitThenDecrementSignal(hipStream_t stream, hipError_t status, void* user_data);
extern void WaitThenDecrementSignal(hipStream_t stream, hipError_t status, void* user_data);
extern std::vector<hip::Device*> g_devices;
extern hipError_t ihipDeviceGetCount(int* count);
extern int ihipGetDevice();
extern std::vector<hip::Device*> g_devices;
extern hipError_t ihipDeviceGetCount(int* count);
extern int ihipGetDevice();
extern hipError_t ihipMalloc(void** ptr, size_t sizeBytes, unsigned int flags);
extern hipError_t ihipHostMalloc(void** ptr, size_t sizeBytes, unsigned int flags);
extern amd::Memory* getMemoryObject(const void* ptr, size_t& offset, size_t size = 0);
extern amd::Memory* getMemoryObjectWithOffset(const void* ptr, const size_t size = 0);
extern void getStreamPerThread(hipStream_t& stream);
extern hipStream_t getPerThreadDefaultStream();
extern hipError_t ihipUnbindTexture(textureReference* texRef);
extern hipError_t ihipHostRegister(void* hostPtr, size_t sizeBytes, unsigned int flags);
extern hipError_t ihipHostUnregister(void* hostPtr);
extern hipError_t ihipGetDeviceProperties(hipDeviceProp_t* props, hipDevice_t device);
extern hipError_t ihipMalloc(void** ptr, size_t sizeBytes, unsigned int flags);
extern hipError_t ihipHostMalloc(void** ptr, size_t sizeBytes, unsigned int flags);
extern amd::Memory* getMemoryObject(const void* ptr, size_t& offset, size_t size = 0);
extern amd::Memory* getMemoryObjectWithOffset(const void* ptr, const size_t size = 0);
extern void getStreamPerThread(hipStream_t& stream);
extern hipStream_t getPerThreadDefaultStream();
extern hipError_t ihipUnbindTexture(textureReference* texRef);
extern hipError_t ihipHostRegister(void* hostPtr, size_t sizeBytes, unsigned int flags);
extern hipError_t ihipHostUnregister(void* hostPtr);
extern hipError_t ihipGetDeviceProperties(hipDeviceProp_t* props, hipDevice_t device);
extern hipError_t ihipDeviceGet(hipDevice_t* device, int deviceId);
extern hipError_t ihipStreamOperation(hipStream_t stream, cl_command_type cmdType, void* ptr,
uint64_t value, uint64_t mask, unsigned int flags,
size_t sizeBytes);
hipError_t ihipMemcpy(void* dst, const void* src, size_t sizeBytes, hipMemcpyKind kind,
hip::Stream& stream, bool isHostAsync = false, bool isGPUAsync = true);
hipError_t ihipMemcpy3D(const hipMemcpy3DParms* p, hipStream_t stream = nullptr,
bool isAsync = false);
constexpr bool kOptionChangeable = true;
constexpr bool kNewDevProg = false;
extern hipError_t ihipDeviceGet(hipDevice_t* device, int deviceId);
extern hipError_t ihipStreamOperation(hipStream_t stream, cl_command_type cmdType, void* ptr,
uint64_t value, uint64_t mask, unsigned int flags,
size_t sizeBytes);
hipError_t ihipMemcpy(void* dst, const void* src, size_t sizeBytes, hipMemcpyKind kind,
hip::Stream& stream, bool isHostAsync = false, bool isGPUAsync = true);
hipError_t ihipMemcpy3D(const hipMemcpy3DParms* p, hipStream_t stream = nullptr,
bool isAsync = false);
constexpr bool kOptionChangeable = true;
constexpr bool kNewDevProg = false;
constexpr bool kMarkerDisableFlush = true; //!< Avoids command batch flush in ROCclr
constexpr bool kMarkerDisableFlush = true; //!< Avoids command batch flush in ROCclr
extern std::vector<hip::Stream*> g_captureStreams;
extern amd::Monitor g_captureStreamsLock;
extern amd::Monitor g_streamSetLock;
extern std::unordered_set<hip::Stream*> g_allCapturingStreams;
} // namespace hip
extern std::vector<hip::Stream*> g_captureStreams;
extern amd::Monitor g_captureStreamsLock;
extern amd::Monitor g_streamSetLock;
extern std::unordered_set<hip::Stream*> g_allCapturingStreams;
} // namespace hip
#endif // HIP_SRC_HIP_INTERNAL_H
+24
View File
@@ -42,6 +42,7 @@ Stream::Stream(hip::Device* dev, Priority p, unsigned int f, bool null_stream,
originStream_(false),
captureID_(0) {
device_->AddStream(this);
stream_id_ = GenerateStreamId();
}
// ================================================================================================
@@ -340,6 +341,29 @@ hipError_t hipStreamGetFlags_spt(hipStream_t stream, unsigned int* flags) {
HIP_RETURN(hipStreamGetFlags_common(stream, flags));
}
// ================================================================================================
hipError_t hipStreamGetId_common(hipStream_t stream, unsigned long long* streamId) {
if (streamId == nullptr) {
HIP_RETURN(hipErrorInvalidValue);
}
if (!hip::isValid(stream)) {
HIP_RETURN(hipErrorInvalidResourceHandle);
}
getStreamPerThread(stream);
constexpr bool wait = false;
hip::Stream* hip_stream = hip::getStream(stream, wait);
*streamId = hip_stream->GetStreamId();
HIP_RETURN(hipSuccess);
}
// ================================================================================================
hipError_t hipStreamGetId(hipStream_t stream, unsigned long long* streamId) {
HIP_INIT_API(hipStreamGetId, stream, streamId);
HIP_RETURN(hipStreamGetId_common(stream, streamId));
}
// ================================================================================================
hipError_t hipStreamSynchronize_common(hipStream_t stream) {
getStreamPerThread(stream);
@@ -1428,6 +1428,9 @@ hipError_t hipStreamGetDevice(hipStream_t stream, hipDevice_t* device) {
hipError_t hipStreamGetFlags(hipStream_t stream, unsigned int* flags) {
return hip::GetHipDispatchTable()->hipStreamGetFlags_fn(stream, flags);
}
hipError_t hipStreamGetId(hipStream_t stream, unsigned long long* streamId) {
return hip::GetHipDispatchTable()->hipStreamGetId_fn(stream, streamId);
}
hipError_t hipStreamGetPriority(hipStream_t stream, int* priority) {
return hip::GetHipDispatchTable()->hipStreamGetPriority_fn(stream, priority);
}