CUDNN Frontend API  8.3.0
cudnn_frontend_OperationGraph.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #pragma once
24 
25 #include <algorithm>
26 #include <array>
27 #include <functional>
28 #include <memory>
29 #include <sstream>
30 #include <utility>
31 #include <vector>
32 
33 #include <cudnn.h>
34 #include <cudnn_backend.h>
35 
37 #include "cudnn_frontend_utils.h"
38 
39 namespace cudnn_frontend {
40 
53  public:
55  std::string
56  describe() const override {
57  std::stringstream ss;
58  ss << "CUDNN_BACKEND_OPERATIONGRAPH_DESCRIPTOR :";
59  return ss.str();
60  }
61 
62  OperationGraph_v8(OperationGraph_v8 &&from) = default;
64  operator= (OperationGraph_v8 &&from) = default;
65 
66  ~OperationGraph_v8() = default;
67 
72  auto
74  getEngineCount(void) const -> int64_t {
75  int64_t global_count = -1;
76  auto status = cudnnBackendGetAttribute(pointer->get_backend_descriptor(),
77  CUDNN_ATTR_OPERATIONGRAPH_ENGINE_GLOBAL_COUNT,
78  CUDNN_TYPE_INT64,
79  1,
80  NULL,
81  &global_count);
82  if (status != CUDNN_STATUS_SUCCESS) {
84  status,
85  "CUDNN_BACKEND_OPERATIONGRAPH_DESCRIPTOR: GetAttribute "
86  "CUDNN_ATTR_OPERATIONGRAPH_ENGINE_GLOBAL_COUNT Failed");
87  }
88  return global_count;
89  }
92  uint64_t
93  getOpCount() const {
94  return numOps;
95  }
96 
97  std::string const &
98  getTag() const {
99  return opGraphTag;
100  }
101 
104  if (numOps != 1) {
105  return {};
106  } else {
107  return feature_vectors[0];
108  }
109 
110  }
111 
112  private:
113  OperationGraph_v8() = default;
114  OperationGraph_v8(OperationGraph_v8 const &) = delete;
116  operator=(OperationGraph_v8 const &) = delete;
117 
118  cudnnHandle_t handle = nullptr;
119  std::array<ManagedOpaqueDescriptor, 10> ops{};
120  int64_t numOps = -1;
121  std::string opGraphTag = "";
122  std::vector<feature_vector_t> feature_vectors;
123 };
124 
129  public:
134  auto
136  setHandle(cudnnHandle_t handle_) -> OperationGraphBuilder_v8 & {
137  m_operationGraph.handle = handle_;
138  return *this;
139  }
141  auto
142  setOperationGraph(int64_t numOps_, Operation_v8 const **ops_) -> OperationGraphBuilder_v8 & {
143  m_operationGraph.numOps = numOps_;
144  m_operationGraph.feature_vectors.resize(numOps_);
145  for (auto i = 0u; i < numOps_; i++) {
146  m_operationGraph.ops[i] = ops_[i]->get_desc();
147  m_operationGraph.opGraphTag += ops_[i]->getTag() + '_';
148  m_operationGraph.feature_vectors[i] = ops_[i]->getFeatureVector();
149  }
150  return *this;
151  }
157  build() {
158  if (m_operationGraph.numOps <= 0) {
160  &m_operationGraph,
161  CUDNN_STATUS_BAD_PARAM,
162  "CUDNN_BACKEND_OPERATIONGRAPH_DESCRIPTOR: Check and Set the CUDNN_ATTR_OPERATIONGRAPH_OPS Count field");
163  return std::move(m_operationGraph);
164  }
165  if (m_operationGraph.ops[0] == nullptr) {
167  &m_operationGraph,
168  CUDNN_STATUS_BAD_PARAM,
169  "CUDNN_BACKEND_OPERATIONGRAPH_DESCRIPTOR: Check and set CUDNN_ATTR_OPERATIONGRAPH_OPS field");
170  return std::move(m_operationGraph);
171  }
172  if (m_operationGraph.handle == nullptr) {
174  &m_operationGraph,
175  CUDNN_STATUS_BAD_PARAM,
176  "CUDNN_BACKEND_OPERATIONGRAPH_DESCRIPTOR: Check and Set CUDNN_ATTR_OPERATIONGRAPH_HANDLE");
177  return std::move(m_operationGraph);
178  }
179 
180  // Create a descriptor. Memory allocation happens here.
181  auto status = m_operationGraph.initialize_managed_backend_pointer(CUDNN_BACKEND_OPERATIONGRAPH_DESCRIPTOR);
182  if (status != CUDNN_STATUS_SUCCESS) {
184  &m_operationGraph, status, "CUDNN_BACKEND_OPERATIONGRAPH_DESCRIPTOR: cudnnCreate Failed");
185  return std::move(m_operationGraph);
186  }
187 
188  std::array<cudnnBackendDescriptor_t, 10> ops_raw{nullptr};
189  for (auto i = 0u; i < m_operationGraph.numOps; i++) {
190  ops_raw[i] = m_operationGraph.ops[i]->get_backend_descriptor();
191  }
192 
193  status = cudnnBackendSetAttribute(m_operationGraph.pointer->get_backend_descriptor(),
194  CUDNN_ATTR_OPERATIONGRAPH_OPS,
195  CUDNN_TYPE_BACKEND_DESCRIPTOR,
196  m_operationGraph.numOps,
197  ops_raw.data());
198  if (status != CUDNN_STATUS_SUCCESS) {
200  &m_operationGraph,
201  status,
202  "CUDNN_BACKEND_OPERATIONGRAPH_DESCRIPTOR: SetAttribute CUDNN_ATTR_OPERATIONGRAPH_OPS Failed");
203  return std::move(m_operationGraph);
204  }
205  status = cudnnBackendSetAttribute(m_operationGraph.pointer->get_backend_descriptor(),
206  CUDNN_ATTR_OPERATIONGRAPH_HANDLE,
207  CUDNN_TYPE_HANDLE,
208  1,
209  &m_operationGraph.handle);
210  if (status != CUDNN_STATUS_SUCCESS) {
212  &m_operationGraph,
213  status,
214  "CUDNN_BACKEND_OPERATIONGRAPH_DESCRIPTOR: SetAttribute CUDNN_ATTR_OPERATIONGRAPH_HANDLE Failed");
215  return std::move(m_operationGraph);
216  }
217 
218  // Finalizing the descriptor
219  status = cudnnBackendFinalize(m_operationGraph.pointer->get_backend_descriptor());
220  if (status != CUDNN_STATUS_SUCCESS) {
222  &m_operationGraph, status, "CUDNN_BACKEND_OPERATIONGRAPH_DESCRIPTOR: cudnnFinalize Failed");
223  return std::move(m_operationGraph);
224  }
225 
226  getLogger() << "[cudnn_frontend] " << m_operationGraph << std::endl;
227  return std::move(m_operationGraph);
228  }
229 
230  explicit OperationGraphBuilder_v8() = default;
231  ~OperationGraphBuilder_v8() = default;
235  operator=(OperationGraphBuilder_v8 const &) = delete;
236 
237  private:
239 };
240 
243 }
std::vector< int64_t > feature_vector_t
Detailed feature_vector. Generally the Tensor and Operation properties.
OperationGraph_v8 & operator=(OperationGraph_v8 &&from)=default
ConditionalStreamer & getLogger()
static void set_error_and_throw_exception(BackendDescriptor const *desc, cudnnStatus_t status, const char *message)
auto setHandle(cudnnHandle_t handle_) -> OperationGraphBuilder_v8 &
Set cudnnHandle for the operations.
auto setOperationGraph(int64_t numOps_, Operation_v8 const **ops_) -> OperationGraphBuilder_v8 &
Set numoperations and the operations.
auto getEngineCount(void) const -> int64_t
Query the total count of the engines for the Operation Set.
std::string describe() const override
Return a string describing the backend Descriptor.
std::array< ManagedOpaqueDescriptor, 10 > ops
std::vector< feature_vector_t > feature_vectors
cudnnStatus_t status
Shared pointer of the OpaqueBackendPointer.