SWDEV-469422 - hipGraph move to classes from structs

Change-Id: I0f9c8ef1161c0c92ebe0cce6844b2feacfee83f5
This commit is contained in:
Anusha GodavarthySurya
2025-01-17 09:10:35 +00:00
committed by Anusha Godavarthy Surya
parent 29cc394510
commit 32e5b00c30
3 changed files with 108 additions and 99 deletions
+4 -4
View File
@@ -1601,7 +1601,7 @@ hipError_t hipGraphLaunch_common(hip::GraphExec* graphExec, hipStream_t stream)
if (graphExec == nullptr || !hip::GraphExec::isGraphExecValid(graphExec)) {
return hipErrorInvalidValue;
}
if (graphExec->clonedNodes_.empty()) {
if (graphExec->GetNodeCount() == 0) {
return hipSuccess;
}
if (!hip::isValid(stream)) {
@@ -2286,7 +2286,7 @@ hipError_t hipGraphClone(hipGraph_t* pGraphClone, hipGraph_t originalGraph) {
if (!hip::Graph::isGraphValid(g)) {
HIP_RETURN(hipErrorInvalidValue);
}
for (auto n : g->vertices_) {
for (auto n : g->GetNodes()) {
if (n->GetType() == hipGraphNodeTypeMemAlloc ||
n->GetType() == hipGraphNodeTypeMemFree) {
HIP_RETURN(hipErrorNotSupported);
@@ -2664,8 +2664,8 @@ hipError_t hipGraphExecUpdate(hipGraphExec_t hGraphExec, hipGraph_t hGraph,
if (newGraphNodes[i]->GetType() == oldGraphExecNodes[i]->GetType()) {
if (newGraphNodes[i]->GetType() != hipGraphNodeTypeHost &&
newGraphNodes[i]->GetType() != hipGraphNodeTypeEmpty) {
if (newGraphNodes[i]->GetParentGraph()->device_ !=
oldGraphExecNodes[i]->GetParentGraph()->device_) {
if (newGraphNodes[i]->GetParentGraph()->Device() !=
oldGraphExecNodes[i]->GetParentGraph()->Device()) {
*updateResult_out = hipGraphExecUpdateErrorUnsupportedFunctionChange;
*hErrorNode_out = reinterpret_cast<hipGraphNode_t>(newGraphNodes[i]);
return hipErrorGraphExecUpdateFailure;
+1 -1
View File
@@ -551,7 +551,7 @@ bool Graph::RunOneNode(Node node, bool wait) {
if (node->GetType() == hipGraphNodeTypeGraph) {
// Process child graph separately, since, there is no connection
auto child = reinterpret_cast<hip::ChildGraphNode*>(node)->GetChildGraph();
if (!reinterpret_cast<hip::ChildGraphNode*>(node)->graphCaptureStatus_) {
if (!reinterpret_cast<hip::ChildGraphNode*>(node)->GetGraphCaptureStatus()) {
child->RunNodes(node->stream_id_, &streams_, &waitList);
}
} else {
+103 -94
View File
@@ -41,20 +41,22 @@ typedef struct ihipExtKernelEvents {
} ihipExtKernelEvents;
namespace hip {
struct Graph;
struct GraphNode;
struct GraphExec;
struct UserObject;
class Graph;
class GraphNode;
class GraphExec;
class UserObject;
class GraphKernelNode;
typedef GraphNode* Node;
struct UserObject : public amd::ReferenceCountedObject {
class UserObject : public amd::ReferenceCountedObject {
typedef void (*UserCallbackDestructor)(void* data);
static std::unordered_set<UserObject*> ObjectSet_;
static amd::Monitor UserObjectLock_;
public:
// Graphs owns this user object.
// In case if User object is about to be deleted (last release()), Pointer refering to it
// should be cleared from Graph's list of user object.
std::unordered_set<Graph*> owning_graphs_;
public:
UserObject(UserCallbackDestructor callback, void* data, unsigned int flags)
: ReferenceCountedObject(), callback_(callback), data_(data), flags_(flags) {
amd::ScopedLock lock(UserObjectLock_);
@@ -108,9 +110,11 @@ struct UserObject : public amd::ReferenceCountedObject {
UserObject& operator=(const UserObject&) = delete;
//! Disable copy constructor
UserObject(const UserObject& obj) = delete;
static std::unordered_set<UserObject*> ObjectSet_;
static amd::Monitor UserObjectLock_;
};
struct hipGraphNodeDOTAttribute {
class hipGraphNodeDOTAttribute {
protected:
std::string style_;
std::string shape_;
@@ -147,7 +151,8 @@ struct hipGraphNodeDOTAttribute {
virtual void PrintAttributes(std::ostream& out, hipGraphDebugDotFlags flag) {}
};
class GraphKernelArgManager : public amd::ReferenceCountedObject, public amd::GraphKernelArgManager {
class GraphKernelArgManager : public amd::ReferenceCountedObject,
public amd::GraphKernelArgManager {
public:
GraphKernelArgManager() : amd::ReferenceCountedObject() {}
~GraphKernelArgManager() {
@@ -184,38 +189,10 @@ class GraphKernelArgManager : public amd::ReferenceCountedObject, public amd::Gr
using KernelArgImpl = device::Settings::KernelArgImpl;
};
struct GraphNode : public hipGraphNodeDOTAttribute {
protected:
// Declare Graph and GraphExec as friends of node for simpler access to GraphNode fields
friend class Graph;
friend class GraphExec;
hip::Stream* stream_ = nullptr;
unsigned int id_;
hipGraphNodeType type_;
std::vector<amd::Command*> commands_;
std::vector<Node> edges_;
std::vector<Node> dependencies_;
bool visited_;
size_t inDegree_; //!< count of in coming edges (@todo: remove, it's dependencies_.size())
size_t outDegree_; //!< count of outgoing edges (@todo: remove, it's edges_.size())
int32_t stream_id_ = -1; //! Stream ID on which this node will be executed
int32_t launch_id_ = -1; //! Launch ID of this node in the entire graph execution sequence
static int nextID;
struct Graph* parentGraph_;
static std::unordered_set<GraphNode*> nodeSet_;
static amd::Monitor nodeSetLock_;
static amd::Monitor WorkerThreadLock_;
unsigned int isEnabled_;
bool signal_is_required_ = false; //!< This node requires a signal on the command
std::vector<uint8_t *> gpuPackets_; //!< GPU Packet to enqueue during graph launch
std::string capturedKernelName_;
size_t alignedKernArgSize_ = 256; //!< Aligned size required for kernel args
size_t kernargSegmentByteSize_ = 512; //!< Kernel arg segment byte size
size_t kernargSegmentAlignment_ = 256; //!< Kernel arg segment alignment
class GraphNode : public hipGraphNodeDOTAttribute {
public:
GraphNode(hipGraphNodeType type, std::string style = "", std::string shape = "",
std::string label = "")
std::string label = "")
: type_(type),
visited_(false),
inDegree_(0),
@@ -263,7 +240,7 @@ struct GraphNode : public hipGraphNodeDOTAttribute {
return true;
}
// Return gpu packet address to update with actual packet under capture.
std::vector<uint8_t *>& GetAqlPackets() { return gpuPackets_; }
std::vector<uint8_t*>& GetAqlPackets() { return gpuPackets_; }
void SetKernelName(const std::string& kernelName) { capturedKernelName_ = kernelName; }
const std::string& GetKernelName() const { return capturedKernelName_; }
size_t GetKerArgSize() const { return alignedKernArgSize_; }
@@ -290,9 +267,7 @@ struct GraphNode : public hipGraphNodeDOTAttribute {
}
hip::Stream* GetQueue() const { return stream_; }
virtual void SetStream(hip::Stream* stream) {
stream_ = stream;
}
virtual void SetStream(hip::Stream* stream) { stream_ = stream; }
//! Updates the grpah node with the execution stream
void SetStream(
const std::vector<hip::Stream*>& streams //!< A pool of streams to use in graph's execution
@@ -468,40 +443,44 @@ struct GraphNode : public hipGraphNodeDOTAttribute {
out << "\"";
out << "];";
}
protected:
// Declare Graph and GraphExec as friends of node for simpler access to GraphNode fields
friend class Graph;
friend class GraphExec;
hip::Stream* stream_ = nullptr;
unsigned int id_;
hipGraphNodeType type_;
std::vector<amd::Command*> commands_;
std::vector<Node> edges_;
std::vector<Node> dependencies_;
bool visited_;
size_t inDegree_; //!< count of in coming edges (@todo: remove, it's dependencies_.size())
size_t outDegree_; //!< count of outgoing edges (@todo: remove, it's edges_.size())
int32_t stream_id_ = -1; //! Stream ID on which this node will be executed
int32_t launch_id_ = -1; //! Launch ID of this node in the entire graph execution sequence
static int nextID;
Graph* parentGraph_;
static std::unordered_set<GraphNode*> nodeSet_;
static amd::Monitor nodeSetLock_;
static amd::Monitor WorkerThreadLock_;
unsigned int isEnabled_;
bool signal_is_required_ = false; //!< This node requires a signal on the command
std::vector<uint8_t*> gpuPackets_; //!< GPU Packet to enqueue during graph launch
std::string capturedKernelName_;
size_t alignedKernArgSize_ = 256; //!< Aligned size required for kernel args
size_t kernargSegmentByteSize_ = 512; //!< Kernel arg segment byte size
size_t kernargSegmentAlignment_ = 256; //!< Kernel arg segment alignment
};
struct Graph {
// Mark GraphExec as friend for faster access to the Graph fields.
// (@todo GrpahExec should be derived from Graph)
friend class GraphExec;
std::vector<Node> vertices_;
const Graph* pOriginalGraph_ = nullptr;
class Graph {
public:
//!< Contains mem alloc dptrs whose corresponding free node is not added to the graph.
std::unordered_set<void*> memAllocNodePtrs_;
static std::unordered_set<Graph*> graphSet_;
static amd::Monitor graphSetLock_;
//!<graphUserObj_.second stores refcount owned by this graph for user object,
std::unordered_map<UserObject*, int> graphUserObj_;
unsigned int id_;
static int nextID;
int max_streams_ = 0; //!< Maximum number of streams used in the graph launch
uint32_t memalloc_nodes_ = 0; //!< Count of unreleased Memalloc nodes
std::vector<Node> roots_; //!< Root nodes, used in parallel launches
std::vector<Node> leafs_; //!< The list of leaf nodes on every parallel stream
//!< Used as a temporary storage for the waiting nodes
//!< to reduce the stack pressure in recursion
std::vector<Node> wait_order_;
std::vector<hip::Stream*> streams_; //!< The list of streams, used in the execution
int32_t current_id_ = 0; //!< The current node ID in the graph execution sequence
hip::Device* device_; //!< HIP device object
hip::MemoryPool* mem_pool_; //!< Memory pool, associated with this graph
std::unordered_set<GraphNode*> capturedNodes_;
bool graphInstantiated_;
std::unordered_set<void*> memAllocNodePtrs_;
std::unordered_map<Node, Node> clonedNodes_;
public:
Graph(hip::Device* device, const Graph* original = nullptr)
: pOriginalGraph_(original)
, id_(nextID++)
, device_(device) {
: pOriginalGraph_(original), id_(nextID++), device_(device) {
amd::ScopedLock lock(graphSetLock_);
graphSet_.insert(this);
mem_pool_ = device->GetGraphMemoryPool();
@@ -720,30 +699,47 @@ struct Graph {
graphInstantiated_ = graphInstantiate;
}
// returns count of unreleased memalloc nodes
//! returns count of unreleased memalloc nodes
uint32_t GetMemAllocNodeCount() const { return memalloc_nodes_; }
//! Increments the graph memory alloc node count
void IncrementMemAllocNodeCount() { memalloc_nodes_++; }
//! Decrements the graph memory alloc node count
void DecrementMemAllocNodeCount() { memalloc_nodes_--; }
//! returns device object
hip::Device* Device() { return device_; }
protected:
int max_streams_ = 0; //!< Maximum number of streams used in the graph launch
private:
friend class GraphExec;
std::vector<Node> vertices_;
const Graph* pOriginalGraph_ = nullptr;
//!< graphUserObj_.second stores refcount owned by this graph for user object,
std::unordered_map<UserObject*, int> graphUserObj_;
unsigned int id_;
static int nextID;
uint32_t memalloc_nodes_ = 0; //!< Count of unreleased Memalloc nodes
std::vector<Node> roots_; //!< Root nodes, used in parallel launches
std::vector<Node> leafs_; //!< The list of leaf nodes on every parallel stream
//!< Used as a temporary storage for the waiting nodes
//!< to reduce the stack pressure in recursion
std::vector<Node> wait_order_;
std::vector<hip::Stream*> streams_; //!< The list of streams, used in the execution
int32_t current_id_ = 0; //!< The current node ID in the graph execution sequence
hip::Device* device_; //!< HIP device object
hip::MemoryPool* mem_pool_; //!< Memory pool, associated with this graph
std::unordered_set<GraphNode*> capturedNodes_;
bool graphInstantiated_;
std::unordered_map<Node, Node> clonedNodes_;
};
struct GraphKernelNode;
struct GraphExec : public amd::ReferenceCountedObject, public Graph {
//! Topological order of the graph doesn't include nodes embedded as part of the child graph
std::vector<Node> topoOrder_;
std::vector<hip::Stream*> parallel_streams_;
hip::Stream* capture_stream_;
class GraphExec : public amd::ReferenceCountedObject, public Graph {
public:
static std::unordered_set<GraphExec*> graphExecSet_;
static amd::Monitor graphExecSetLock_;
uint64_t flags_ = 0;
GraphKernelArgManager* kernArgManager_ = nullptr; //!< Kernel Arg manager for graph.
int instantiateDeviceId_ = -1;
bool hasHiddenHeap_ = false; //!< Hidden heap indicator for Kernel node
bool repeatLaunch_ = false;
public:
GraphExec(uint64_t flags = 0)
: ReferenceCountedObject(),
Graph(hip::getCurrentDevice()),
flags_(flags) {
: ReferenceCountedObject(), Graph(hip::getCurrentDevice()), flags_(flags) {
amd::ScopedLock lock(graphExecSetLock_);
graphExecSet_.insert(this);
}
@@ -804,10 +800,20 @@ struct GraphExec : public amd::ReferenceCountedObject, public Graph {
void GetKernelArgSizeForGraph(size_t& kernArgSizeForGraph);
hipError_t EnqueueGraphWithSingleList(hip::Stream* hip_stream);
bool TopologicalOrder() { return Graph::TopologicalOrder(topoOrder_); }
protected:
//! Topological order of the graph doesn't include nodes embedded as part of the child graph
std::vector<Node> topoOrder_;
std::vector<hip::Stream*> parallel_streams_;
hip::Stream* capture_stream_;
uint64_t flags_ = 0;
GraphKernelArgManager* kernArgManager_ = nullptr; //!< Kernel Arg manager for graph.
int instantiateDeviceId_ = -1;
bool hasHiddenHeap_ = false; //!< Hidden heap indicator for Kernel node
bool repeatLaunch_ = false;
};
struct ChildGraphNode : public GraphNode, public GraphExec {
bool graphCaptureStatus_;
class ChildGraphNode : public GraphNode, public GraphExec {
public:
ChildGraphNode(Graph* g) : GraphNode(hipGraphNodeTypeGraph, "solid", "rectangle"), GraphExec() {
g->clone(this);
@@ -878,6 +884,9 @@ struct ChildGraphNode : public GraphNode, public GraphExec {
virtual void GenerateDOT(std::ostream& fout, hipGraphDebugDotFlags flag) override {
Graph::GenerateDOT(fout, flag);
}
private:
bool graphCaptureStatus_;
};
class GraphKernelNode : public GraphNode {
@@ -2337,7 +2346,7 @@ class GraphMemAllocNode final : public GraphNode {
queue()->device().SetMemAccess(vaddr_sub_obj->getSvmPtr(), aligned_size,
amd::Device::VmmAccess::kReadWrite);
va_->retain();
graph_->memalloc_nodes_++; // Increment count of unreleased mem alloc nodes
graph_->IncrementMemAllocNodeCount(); // Increment count of unreleased mem alloc nodes
ClPrint(amd::LOG_INFO, amd::LOG_MEM_POOL,
"Graph MemAlloc execute [%p-%p], %p", vaddr_sub_obj->getSvmPtr(),
reinterpret_cast<char*>(vaddr_sub_obj->getSvmPtr()) + aligned_size, memory());
@@ -2483,7 +2492,7 @@ class GraphMemFreeNode : public GraphNode {
LogError("Memory didn't belong to any pool!");
}
amd::MemObjMap::AddMemObj(ptr(), vaddr_mem_obj);
graph_->memalloc_nodes_--; // Decrement count of unreleased memalloc nodes
graph_->DecrementMemAllocNodeCount(); // Decrement count of unreleased memalloc nodes
ClPrint(amd::LOG_INFO, amd::LOG_MEM_POOL, "Graph MemFree execute: %p, %p",
ptr(), vaddr_sub_obj);
}