0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

TensorRT条件用于实现网络子图的条件执行

星星科技指导员 来源:NVIDIA 作者:NVIDIA 2022-05-18 10:02 次阅读

11.1. Defining A Conditional

if-conditional 由条件边界层定义:

  • IConditionLayer表示predicate 并指定条件是应该执行真分支(then-branch)还是假分支(else-branch)。
  • IIfConditionalInputLayer指定两个条件分支之一的输入。
  • IIfConditionalOutputLayer指定条件的输出。

每个边界层都继承自IIfConditionalBoundaryLayer类,该类具有获取其关联IIfConditional的方法getConditional()IIfConditional实例标识条件。所有具有相同IIfConditional的条件边界层都属于该条件。

条件必须恰好有一个IConditionLayer实例、零个或多个IIfConditionalInputLayer实例,以及至少一个IIfConditionalOutputLayer实例。

IIfConditional实现了一个if-then-else流控制结构,该结构提供基于动态布尔输入的网络子图的条件执行。它由一个布尔标量predicate condition和两个分支子图定义:一个trueSubgraphcondition评估为true时执行,一个falseSubgraphcondition评估为false时执行

If condition is true then: 
	output = trueSubgraph(trueInputs);
Else
	output = falseSubgraph(falseInputs);
Emit output

真分支和假分支都必须定义,类似于许多编程语言中的三元运算符。

要定义if-conditional,使用方法INetworkDefinition::addIfConditional创建一个IIfConditional实例,然后添加边界层和分支层。

IIfConditional* simpleIf = network->addIfConditional();

IIfConditional ::setCondition方法接受一个参数条件张量。这个 0D 布尔张量(标量)可以由网络中的早期层动态计算。它用于决定执行哪个分支。IConditionLayer有一个输入(条件)并且没有输出,因为它由条件实现在内部使用。

// Create a condition predicate that is also a network input.
auto cond = network->addInput("cond", DataType::kBOOL, Dims{0});
IConditionLayer* condition = simpleIf->setCondition(*cond);

TensorRT 不支持实现条件分支的子图抽象,而是使用IIfConditionalInputLayerIIfConditionalOutputLayer来定义条件的边界。

  • IIfConditionalInputLayer将单个输入抽象为IIfConditional的一个或两个分支子图。特定IIfConditionalInputLayer的输出可以同时提供两个分支。then-branchelse-branch的输入不需要是相同的类型和形状,每个分支可以独立地包含零个或多个输入。IIfConditionalInputLayer是可选的,用于控制哪些层将成为分支的一部分(请参阅条件执行)。如果分支的所有输出都不依赖于IIfConditionalInputLayer实例,则该分支为空。当条件为false时没有要评估的层时,空的else-branch可能很有用,并且网络评估应按照条件进行(请参阅条件示例)。
// Create an if-conditional input.
// x is some arbitrary Network tensor.
IIfConditionalInputLayer* inputX = simpleIf->addInput(*x);
  • IIfConditionalOutputLayer抽象了if条件的单个输出。它有两个输入:来自真子图的输出(输入索引 0)和来自假子图的输出(输入索引 1)。IIfConditionalOutputLayer的输出可以被认为是最终输出的占位符,最终输出将在运行时确定。IIfConditionalOutputLayer的作用类似于传统 SSA 控制流图中的 $Φ(Phi)$ 函数节点。它的语义是:选择真子图或假子图的输出。IIfConditional的所有输出都必须源自IIfConditionalOutputLayer实例。没有输出的 if 条件对网络的其余部分没有影响,因此,它被认为是病态的。两个分支(子图)中的每一个也必须至少有一个输出。if-conditional的输出可以标记为网络的输出,除非if-conditional嵌套在另一个if-conditional或循环中。
// trueSubgraph and falseSubgraph represent network subgraphs
IIfConditionalOutputLayer* outputLayer = simpleIf->addOutput(
    *trueSubgraph->getOutput(0), 
    *falseSubgraph->getOutput(0));

下图提供了 if 条件抽象模型的图形表示。绿色矩形表示条件的内部,仅限于NVIDIA TensorRT 支持矩阵中的LayersFor Flow-Control Constructs部分中列出的层类型。

11.2. Conditional Execution

网络层的条件执行是一种网络评估策略,其中仅在需要分支输出的值时才执行分支层(属于条件子图的层)。在条件执行中,无论是真分支还是假分支都被执行并允许改变网络状态。

相反,在断定执行中,真分支和假分支都被执行,并且只允许其中之一改变网络评估状态,具体取决于条件断定的值(即仅其中一个的输出)子图被馈送到以下层。

条件执行有时称为惰性求值,断定执行有时称为急切求值。IIfConditionalInputLayer的实例可用于指定急切调用哪些层以及延迟调用哪些层。这是通过从每个条件输出开始向后跟踪网络层来完成的。依赖于至少一个IIfConditionalInputLayer输出的数据层被认为是条件内部的,因此被延迟评估。在没有IIfConditionalInputLayer实例添加到条件条件的极端情况下,所有层都被急切地执行,类似于ISelectLayer

下面的三个图表描述了IIfConditionalInputLayer放置的选择如何控制执行调度。

在图 A 中,真分支由 3 层(T1、T2、T3)组成。当条件评估为true时,这些层会延迟执行。

在图 B 中,输入层 I1 放置在层 T1 之后,它将 T1 移出真实分支。在评估 if 结构之前,T1 层急切地执行。

在图表 C 中,输入层 I1 被完全移除,这将 T3 移到条件之外。 T2 的输入被重新配置以创建合法网络,并且 T2 也移出真实分支。当条件评估为true时,条件不计算任何内容,因为输出已经被急切地计算(但它确实将条件相关输入复制到其输出)。

11.3. Nesting and Loops

条件分支可以嵌套其他条件,也可以嵌套循环。循环可以嵌套条件。与循环嵌套一样,TensorRT 从数据流中推断条件和循环的嵌套。例如,如果条件 B 使用在循环 A 内定义的值,则 B 被认为嵌套在 A 内。

真分支中的层与假分支中的层之间不能有交叉边,反之亦然。换句话说,一个分支的输出不能依赖于另一个分支中的层。

例如,请参阅条件示例以了解如何指定嵌套。

11.4. Limitations

两个真/假子图分支中的输出张量数必须相同。来自分支的每个输出张量的类型和形状必须相同。

请注意,这比 ONNX 规范更受限制,ONNX 规范要求真/假子图具有相同数量的输出并使用相同的输出数据类型,但允许不同的输出形状。

11.5. Conditional Examples

11.5.1. Simple If-Conditional

下面的例子展示了如何实现一个简单的条件,它有条件地对两个张量执行算术运算。Conditional

condition = true
If condition is true:
        output = x + y
Else:
        output = x - y

Example

ITensor* addCondition(INetworkDefinition& n, bool predicate)
{
    // The condition value is a constant int32 input that is cast to boolean because TensorRT doesn't support boolean constant layers.

    static const Dims scalarDims = Dims{0, {}};
    static float constexpr zero{0};
    static float constexpr one{1};

    float* const val = predicate ? &one : &zero;

    ITensor* cond = 
        n.addConstant(scalarDims, DataType::kINT32, val, 1})->getOutput(0);

    auto* cast = n.addIdentity(cond);
    cast->setOutputType(0, DataType::kBOOL);
    cast->getOutput(0)->setType(DataType::kBOOL);

    return cast->getOutput(0);
}

IBuilder* builder = createInferBuilder(gLogger);
INetworkDefinition& n = *builder->createNetworkV2(0U);
auto x = n.addInput("x", DataType::kFLOAT, Dims{1, {5}});
auto y = n.addInput("y", DataType::kFLOAT, Dims{1, {5}});
ITensor* cond = addCondition(n, true);

auto* simpleIf = n.addIfConditional();
simpleIf->setCondition(*cond);

// Add input layers to demarcate entry into true/false branches.
x = simpleIf->addInput(*x)->getOutput(0);
y = simpleIf->addInput(*y)->getOutput(0);

auto* trueSubgraph = n.addElementWise(*x, *y, ElementWiseOperation::kSUM)->getOutput(0);
auto* falseSubgraph = n.addElementWise(*x, *y, ElementWiseOperation::kSUB)->getOutput(0);

auto* output = simpleIf->addOutput(*trueSubgraph, *falseSubgraph)->getOutput(0);
n.markOutput(*output);

11.5.2. Exporting from PyTorch

以下示例展示了如何将脚本化的 PyTorch 代码导出到 ONNX。函数sum_even中的代码执行嵌套在循环中的 if 条件。

import torch.onnx
import torch
import tensorrt as trt
import numpy as np

TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
EXPLICIT_BATCH = 1 << (int)(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)

@torch.jit.script
def sum_even(items):
    s = torch.zeros(1, dtype=torch.float)
    for c in items:
        if c % 2 == 0:
            s += c
    return s

class ExampleModel(torch.nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, items):
        return sum_even(items)

def build_engine(model_file):
    builder = trt.Builder(TRT_LOGGER)
    network = builder.create_network(EXPLICIT_BATCH)
    config = builder.create_builder_config()
    parser = trt.OnnxParser(network, TRT_LOGGER)

    with open(model_file, 'rb') as model:
        assert parser.parse(model.read())
        return builder.build_engine(network, config)

def export_to_onnx():
    items = torch.zeros(4, dtype=torch.float)
    example = ExampleModel()
    torch.onnx.export(example, (items), "example.onnx", verbose=False, opset_version=13, enable_onnx_checker=False, do_constant_folding=True)

export_to_onnx()
build_engine("example.onnx")

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • NVIDIA
    +关注

    关注

    14

    文章

    4986

    浏览量

    103067
  • gpu
    gpu
    +关注

    关注

    28

    文章

    4740

    浏览量

    128951
  • 人工智能
    +关注

    关注

    1791

    文章

    47279

    浏览量

    238511
收藏 人收藏

    评论

    相关推荐

    半导体雷射震荡条件

    共振腔中雷射光来回(round trip)振荡后保持光学自再现(self-consistency)的边界条件,让我们可以求得雷射要稳定存在于共振腔必须符合两条件,第一部分为振幅条件,第二则为相位
    的头像 发表于 12-19 10:52 138次阅读
    半导体雷射震荡<b class='flag-5'>条件</b>

    正弦振荡电路的起振条件是什么

    正弦振荡电路是一种能够产生稳定正弦波形的电子电路,广泛应用于信号发生器、通信系统和电子测量设备中。要实现正弦振荡,电路必须满足一定的条件,这些条件被称为起振
    的头像 发表于 09-27 17:57 1258次阅读

    振荡器的相位条件和振幅条件的区别

    振荡器是电子电路中的一种基本组件,它能够产生周期性的电压或电流波形。振荡器的工作原理基于正反馈机制,即输出信号的一部分被反馈到输入端,以维持振荡。在设计和分析振荡器时,需要考虑两个关键条件:相位条件
    的头像 发表于 09-25 10:40 671次阅读

    Simplelink™ Wi-Fi® CC3x3x网络子系统电源管理

    电子发烧友网站提供《Simplelink™ Wi-Fi® CC3x3x网络子系统电源管理.pdf》资料免费下载
    发表于 09-23 11:17 0次下载
    Simplelink™ Wi-Fi® CC3x3x<b class='flag-5'>网络子</b>系统电源管理

    负反馈自激振荡的条件是什么

    负反馈自激振荡的条件主要涉及到相位、幅度和频率三个方面。以下是具体的条件: 一、相位条件 相位平衡 :负反馈放大电路产生自激振荡的首要条件是反馈信号与输入信号之间的相位关系。当反馈信号
    的头像 发表于 09-11 14:40 1455次阅读

    实现有源逆变必须满足哪些条件

    实现有源逆变,即让一个电力电子装置在输出端产生与输入端电压同频率、同相位的电流,同时能够向电网回馈能量,需要满足一定的条件。以下是对实现有源逆变所需满足条件的分析。 1. 电压匹配
    的头像 发表于 08-14 10:31 2427次阅读

    振荡器的起振条件和平衡条件

    振荡器作为电子电路中的重要组成部分,其起振条件和平衡条件对于理解振荡器的工作原理、设计及应用具有重要意义。以下是对振荡器的起振条件和平衡条件的详细阐述,旨在提供全面且深入的理解。
    的头像 发表于 07-30 16:14 3535次阅读

    LC振荡器的起振条件概述

    LC振荡器,也称为LC振荡电路,是由电感(L)和电容(C)构成的振荡电路,广泛应用于电子工程、通信工程和射频电路设计中。LC振荡器的起振条件是其能够自发地产生稳定振荡信号的基础,这些条件涉及电路的多个方面,包括振幅
    的头像 发表于 07-22 17:42 1680次阅读

    电路发生谐振的条件、特点及应用

    电路谐振概述 电路谐振是电路中一个非常重要的现象,它指的是在特定频率下,电路中的电压、电流或功率等物理量达到最大值的状态。谐振现象主要存在于包含电感和电容的电路中,这些元件在特定条件下能够形成
    的头像 发表于 07-15 15:55 4484次阅读

    实现智能制造的重要条件是什么

    智能制造是工业4.0的核心,它通过高度集成的信息威廉希尔官方网站 和自动化威廉希尔官方网站 ,实现生产过程的智能化、自动化和网络化。实现智能制造的重要条件有很多,以下是一些关键因素的详细分析: 威廉希尔官方网站 创新 威廉希尔官方网站 创新
    的头像 发表于 06-07 15:42 1741次阅读

    STM8S if条件非真,却能执行,为什么?

    if条件非真,却能执行,一般是单片机什么故障,需要做哪些处理可以避免这种情况的发生?
    发表于 05-06 06:08

    电路发生谐振的条件和特点

    电路发生谐振的条件和特点 电路谐振是指在电路中发生共振现象,即电路输出达到最大值的状态。它是电路中的重要现象之一,具有一定的条件和特点。下面将从谐振的概念、条件和特点,以及不同类型电路中的谐振进行
    的头像 发表于 04-08 16:13 6994次阅读

    鸿蒙TypeScript入门学习第6天:【条件语句】

    条件语句用于基于不同的条件执行不同的动作。 TypeScript 条件语句是通过一条或多条语句的
    的头像 发表于 04-01 13:51 764次阅读
    鸿蒙TypeScript入门学习第6天:【<b class='flag-5'>条件</b>语句】

    晶闸管的导通条件及关断条件?

    晶闸管(Thyristor)是一种常用的半导体器件,广泛应用于电力电子和电路控制领域。它可以用作开关、稳压器、整流器等。在进行详细介绍晶闸管的导通条件和关断条件之前,我们需要先了解一些基础知识
    的头像 发表于 03-12 15:01 4369次阅读

    晶体管放大的内部条件和外部条件的区别

    晶体管是一种半导体器件,广泛应用于电子威廉希尔官方网站 中的放大、开关、整流等电路中。晶体管的放大作用在电子威廉希尔官方网站 应用中起着至关重要的作用。晶体管放大的内部条件和外部条件包括了很多方面,下面我将详细介绍。 首先
    的头像 发表于 02-27 16:56 2379次阅读