概述#
cuDNN 库公开了开源前端 Python 和 C++ API 层,它们提供了一种简化的编程模型,足以满足大多数用例。 这些层提供了 cuDNN 后端的所有图功能,同时添加了抽象和实用程序,以便于使用。 在前端 API 中,您可以描述通过持久图对象形成子图的多个操作。 您不必担心指定中间虚拟张量的形状和大小。
Python 前端 API 层和 C++ 前端 API 层在功能上是等效的。 因此,您可以根据您的语言偏好选择使用哪个 API 层。
构建和运行 cuDNN 图工作流程#
创建 cuDNN 图并指定全局属性。 诸如计算精度和输入/输出数据类型之类的全局属性有助于推断未明确提及的属性。
创建并添加输入张量。
创建并添加操作节点。 这些操作的输出是张量类型,可以按顺序用作下一个节点的输入。
验证操作图。 此步骤确保图构建良好,并且没有悬空张量或节点。
构建 cuDNN 操作图。 此步骤将图降级为 cuDNN 方言。
根据您选择的启发式类型创建执行计划。
(可选)检查操作图的支持情况。
(可选)按您的自定义标准过滤计划。
构建(一个或所有)执行计划。
(可选)在过滤后的计划上运行自动调优。
使用相关数据指针执行图。
API#
前端 API 遵循构建图的功能样式。 操作接收输入张量并返回输出张量。 这也允许操作的组合。
目的 |
C++ API |
Python API |
---|---|---|
创建张量 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
创建图#
实例化 cudnn_frontend::graph::Graph
类的对象,它将容纳张量和操作。
可以在对象上设置可选的图级别属性
cudnn_frontend::graph::Graph& set_io_data_type(cudnn_frontend::DataType_t)
cudnn_frontend::graph::Graph& set_intermediate_data_type(cudnn_frontend::DataType_t)
cudnn_frontend::graph::Graph& set_compute_data_type(cudnn_frontend::DataType_t)
这些属性旨在用作默认值,以防未为组成张量和操作提供它们。
定义张量#
您可以创建输入张量,以在图中提供操作。 要在图中添加张量,请使用
std::shared_ptr<cudnn_frontend::graph::Tensor_attributes> cudnn_frontend::graph::tensor(cudnn_frontend::graph::Tensor_attributes)
由于 API 返回共享指针,因此用户和前端图都是张量的所有者。
张量属性是一个轻量级结构,带有用于每个属性的设置器。
cudnn_frontend::graph::Tensor_attributes& set_data_type(cudnn_frontend::DataType_t)
cudnn_frontend::graph::Tensor_attributes& set_dim(std::vector<int64_t>&)
cudnn_frontend::graph::Tensor_attributes& set_stride(std::vector<int64_t>&)
cudnn_frontend::graph::Tensor_attributes& set_is_virtual(bool)
cudnn_frontend::graph::Tensor_attributes& set_is_pass_by_value(bool)
cudnn_frontend::graph::Tensor_attributes& set_reordering_type(cudnn_frontend::TensorReordering_t)
cudnn_frontend::graph::Tensor_attributes& set_name(std::string&)
定义操作#
操作通过位置参数接收强制性输入张量。 可选的输入张量使用操作属性中的相应设置器提供。
操作返回输出张量的有序数组。 任何可选输出(如果不存在)都将使其共享指针指向 std::nullptr
。
有关更多详细信息,请参阅操作部分。
验证图#
validate
API 确保 API 用法正确,检查悬空张量等等。 在内部,任何未指定的属性(如维度、步幅等)都会被推断出来。
cudnn_frontend::error_t cudnn_frontend::graph::Graph::validate()
构建后端图#
此方法为图的所有组成部分创建 cuDNN 后端描述符。
cudnn_frontend::error_t cudnn_frontend::graph::Graph::build_operation_graph(cudnnHandle_t handle)
创建执行计划#
此方法在内部查询启发式方法以获取给定启发式模式的引擎配置。
cudnn_frontend::error_t cudnn_frontend::graph::Graph::get_execution_plans(std::vector<heur_mode_t>)
获取执行计划计数#
此方法返回 cuDNN 启发式方法返回的执行计划数。 每个计划都获得一个从 0
到 #plans-1
的索引,其中 0
具有最高优先级。
cudnn_frontend::int64_t cudnn_frontend::Graph::get_execution_plan_count() const;
检查图支持#
此方法保证使用查询的计划执行图将成功。
cudnn_frontend::error_t cudnn_frontend::graph::Graph::check_support(cudnnHandle_t h);
构建执行计划#
此函数构建使用 create_execution_plan(...)
API 查询的执行计划。
此 API 有两种变体
根据策略构建执行计划。 允许 cuDNN 启发式方法构建并返回最佳执行计划。
cudnn_frontend::error_t cudnn_frontend::graph::Graph::build_plan( cudnnHandle_t const &handle, cudnn_frontend::BuildPlanPolicy_t const policy, bool const do_multithreaded_builds );
构建单个计划索引。 主要用例是在自动调优时并行构建执行计划。 此处要使用的计划索引可以使用
get_execution_plan_count(...)
API 查询。cudnn_frontend::error_t cudnn_frontend::Graph::build_plan_at_index( cudnnHandle_t const &handle, int64_t plan_index );
过滤计划(可选)#
您可以根据数值、行为注释或不提供所需功能正确性的计划来过滤计划。
cudnn_frontend::graph::Graph& cudnn_frontend::graph::Plans::select_numeric_notes(std::vector<cudnn_frontend::NumericalNote_t> const&); cudnn_frontend::graph::Graph& cudnn_frontend::graph::Plans::select_behavior_notes(std::vector<cudnn_frontend::BehaviorNote_t> const&); cudnn_frontend::graph::Graph& cudnn_frontend::graph::Plans::deselect_numeric_notes(std::vector<cudnn_frontend::NumericalNote_t> const&); cudnn_frontend::graph::Graph& cudnn_frontend::graph::Plans::deselect_behavior_notes(std::vector<cudnn_frontend::BehaviorNote_t> const&); cudnn_frontend::graph::Graph& cudnn_frontend::graph::Plans::deselect_workspace_greater_than(int64_t const workspace);
自动调优#
自动调优提供了一种为给定图执行不同执行计划的方法,并测量运行时条件下的相对性能。 这通常有助于验证和改进启发式方法提供的结果。
执行图#
执行图需要指向所有输入输出张量的设备指针和用户分配的设备工作区指针。
存在两种执行方式,对应于 build_plans(...)
API。 此 API 已经设置了候选执行计划。
当以下情况时,候选执行计划会在内部设置:
使用
build_policy_t::HEURISTIC_CHOICE
,或者如果使用
plan_index
通过build_plan
API 构建任何计划。cudnn_frontend::error_t cudnn_frontend::graph::Graph::execute( cudnnHandle_t handle, std::unordered_map<std::shared_ptr<Tensor>, void *> var_pack, void* workspace );
execute API 还接受计划索引以定位特定计划。 这可以在自动调优时使用,并结合使用 build_plan_at_index(...)
API。
cudnn_frontend::error_t cudnn_frontend::graph::Graph::execute( cudnnHandle_t handle, std::unordered_map<std::shared_ptr<Tensor>, void *> var_pack, void* workspace, int64_t plan_index );
其他 API#
使用 get_workspace
执行当前选定的执行计划。
您还可以接收计划索引以查询工作区。 这可以在自动调优时使用,并结合使用 build_plan_at_index(...)
API。
int64_t get_workspace_size() const int64_t get_workspace_size_plan_index(int64_t plan_index) const
使用 get_autotune_workspace
在所有计划上运行自动调优。
get_autotune_workspace_size() const
序列化#
前端 API 提供两种序列化方式。 一种是在初始图规范之后(在调用验证之前)进行检查点,另一种是在构建执行计划之后(以节省计划创建)。
void serialize(json &j) const
void deserialize(const json &j)
以上两个 API 旨在捕获用户指定的输入张量和节点到图中。 这可以用于生成日志(用于调试)或可视化正在创建的图。
error_t serialize(std::vector<uint8_t> &data) const
error_t deserialize(cudnnHandle_t handle, std::vector<uint8_t> const &data)
可以使用以上两个 API 将完全构建的图序列化为二进制数据 blob。
注意
并非所有引擎配置都支持序列化。
用户有责任确保传递到变体包的张量的 UID 在序列化前后保持一致。
错误处理#
C++ API 返回一个错误对象,其中包含错误代码和错误消息。
Python API 抛出一个异常,其中包含类似错误消息,以便在 Python API 中处理。
操作#
有关不同操作类型的 API,请参阅操作部分。