0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

TensorRT條件用于實現(xiàn)網(wǎng)絡子圖的條件執(zhí)行

星星科技指導員 ? 來源:NVIDIA ? 作者:NVIDIA ? 2022-05-18 10:02 ? 次閱讀

11.1. Defining A Conditional

if-conditional 由條件邊界層定義:

  • IConditionLayer表示predicate 并指定條件是應該執(zhí)行真分支(then-branch)還是假分支(else-branch)。
  • IIfConditionalInputLayer指定兩個條件分支之一的輸入。
  • IIfConditionalOutputLayer指定條件的輸出。

每個邊界層都繼承自IIfConditionalBoundaryLayer類,該類具有獲取其關聯(lián)IIfConditional的方法getConditional()。IIfConditional實例標識條件。所有具有相同IIfConditional的條件邊界層都屬于該條件。

條件必須恰好有一個IConditionLayer實例、零個或多個IIfConditionalInputLayer實例,以及至少一個IIfConditionalOutputLayer實例。

IIfConditional實現(xiàn)了一個if-then-else流控制結構,該結構提供基于動態(tài)布爾輸入的網(wǎng)絡子圖的條件執(zhí)行。它由一個布爾標量predicate condition和兩個分支子圖定義:一個trueSubgraphcondition評估為true時執(zhí)行,一個falseSubgraphcondition評估為false時執(zhí)行

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

真分支和假分支都必須定義,類似于許多編程語言中的三元運算符。

要定義if-conditional,使用方法INetworkDefinition::addIfConditional創(chuàng)建一個IIfConditional實例,然后添加邊界層和分支層。

IIfConditional* simpleIf = network->addIfConditional();

IIfConditional ::setCondition方法接受一個參數(shù)條件張量。這個 0D 布爾張量(標量)可以由網(wǎng)絡中的早期層動態(tài)計算。它用于決定執(zhí)行哪個分支。IConditionLayer有一個輸入(條件)并且沒有輸出,因為它由條件實現(xiàn)在內(nèi)部使用。

// 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 不支持實現(xiàn)條件分支的子圖抽象,而是使用IIfConditionalInputLayerIIfConditionalOutputLayer來定義條件的邊界。

  • IIfConditionalInputLayer將單個輸入抽象為IIfConditional的一個或兩個分支子圖。特定IIfConditionalInputLayer的輸出可以同時提供兩個分支。then-branchelse-branch的輸入不需要是相同的類型和形狀,每個分支可以獨立地包含零個或多個輸入。IIfConditionalInputLayer是可選的,用于控制哪些層將成為分支的一部分(請參閱條件執(zhí)行)。如果分支的所有輸出都不依賴于IIfConditionalInputLayer實例,則該分支為空。當條件為false時沒有要評估的層時,空的else-branch可能很有用,并且網(wǎng)絡評估應按照條件進行(請參閱條件示例)。
// Create an if-conditional input.
// x is some arbitrary Network tensor.
IIfConditionalInputLayer* inputX = simpleIf->addInput(*x);
  • IIfConditionalOutputLayer抽象了if條件的單個輸出。它有兩個輸入:來自真子圖的輸出(輸入索引 0)和來自假子圖的輸出(輸入索引 1)。IIfConditionalOutputLayer的輸出可以被認為是最終輸出的占位符,最終輸出將在運行時確定。IIfConditionalOutputLayer的作用類似于傳統(tǒng) SSA 控制流圖中的 $Φ(Phi)$ 函數(shù)節(jié)點。它的語義是:選擇真子圖或假子圖的輸出。IIfConditional的所有輸出都必須源自IIfConditionalOutputLayer實例。沒有輸出的 if 條件對網(wǎng)絡的其余部分沒有影響,因此,它被認為是病態(tài)的。兩個分支(子圖)中的每一個也必須至少有一個輸出。if-conditional的輸出可以標記為網(wǎng)絡的輸出,除非if-conditional嵌套在另一個if-conditional或循環(huán)中。
// trueSubgraph and falseSubgraph represent network subgraphs
IIfConditionalOutputLayer* outputLayer = simpleIf->addOutput(
    *trueSubgraph->getOutput(0), 
    *falseSubgraph->getOutput(0));

下圖提供了 if 條件抽象模型的圖形表示。綠色矩形表示條件的內(nèi)部,僅限于NVIDIA TensorRT 支持矩陣中的LayersFor Flow-Control Constructs部分中列出的層類型。

11.2. Conditional Execution

網(wǎng)絡層的條件執(zhí)行是一種網(wǎng)絡評估策略,其中僅在需要分支輸出的值時才執(zhí)行分支層(屬于條件子圖的層)。在條件執(zhí)行中,無論是真分支還是假分支都被執(zhí)行并允許改變網(wǎng)絡狀態(tài)。

相反,在斷定執(zhí)行中,真分支和假分支都被執(zhí)行,并且只允許其中之一改變網(wǎng)絡評估狀態(tài),具體取決于條件斷定的值(即僅其中一個的輸出)子圖被饋送到以下層。

條件執(zhí)行有時稱為惰性求值,斷定執(zhí)行有時稱為急切求值。IIfConditionalInputLayer的實例可用于指定急切調(diào)用哪些層以及延遲調(diào)用哪些層。這是通過從每個條件輸出開始向后跟蹤網(wǎng)絡層來完成的。依賴于至少一個IIfConditionalInputLayer輸出的數(shù)據(jù)層被認為是條件內(nèi)部的,因此被延遲評估。在沒有IIfConditionalInputLayer實例添加到條件條件的極端情況下,所有層都被急切地執(zhí)行,類似于ISelectLayer。

下面的三個圖表描述了IIfConditionalInputLayer放置的選擇如何控制執(zhí)行調(diào)度。

在圖 A 中,真分支由 3 層(T1、T2、T3)組成。當條件評估為true時,這些層會延遲執(zhí)行。

在圖 B 中,輸入層 I1 放置在層 T1 之后,它將 T1 移出真實分支。在評估 if 結構之前,T1 層急切地執(zhí)行。

在圖表 C 中,輸入層 I1 被完全移除,這將 T3 移到條件之外。 T2 的輸入被重新配置以創(chuàng)建合法網(wǎng)絡,并且 T2 也移出真實分支。當條件評估為true時,條件不計算任何內(nèi)容,因為輸出已經(jīng)被急切地計算(但它確實將條件相關輸入復制到其輸出)。

11.3. Nesting and Loops

條件分支可以嵌套其他條件,也可以嵌套循環(huán)。循環(huán)可以嵌套條件。與循環(huán)嵌套一樣,TensorRT 從數(shù)據(jù)流中推斷條件和循環(huán)的嵌套。例如,如果條件 B 使用在循環(huán) A 內(nèi)定義的值,則 B 被認為嵌套在 A 內(nèi)。

真分支中的層與假分支中的層之間不能有交叉邊,反之亦然。換句話說,一個分支的輸出不能依賴于另一個分支中的層。

例如,請參閱條件示例以了解如何指定嵌套。

11.4. Limitations

兩個真/假子圖分支中的輸出張量數(shù)必須相同。來自分支的每個輸出張量的類型和形狀必須相同。

請注意,這比 ONNX 規(guī)范更受限制,ONNX 規(guī)范要求真/假子圖具有相同數(shù)量的輸出并使用相同的輸出數(shù)據(jù)類型,但允許不同的輸出形狀。

11.5. Conditional Examples

11.5.1. Simple If-Conditional

下面的例子展示了如何實現(xiàn)一個簡單的條件,它有條件地對兩個張量執(zhí)行算術運算。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。函數(shù)sum_even中的代碼執(zhí)行嵌套在循環(huán)中的 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")

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • NVIDIA
    +關注

    關注

    14

    文章

    4862

    瀏覽量

    102722
  • gpu
    gpu
    +關注

    關注

    28

    文章

    4678

    瀏覽量

    128616
  • 人工智能
    +關注

    關注

    1791

    文章

    46698

    瀏覽量

    237196
收藏 人收藏

    評論

    相關推薦

    實現(xiàn)有源逆變必須滿足哪些條件

    實現(xiàn)有源逆變,即讓一個電力電子裝置在輸出端產(chǎn)生與輸入端電壓同頻率、同相位的電流,同時能夠向電網(wǎng)回饋能量,需要滿足一定的條件。以下是對實現(xiàn)有源逆變所需滿足條件的分析。 1. 電壓匹配
    的頭像 發(fā)表于 08-14 10:31 ?1120次閱讀

    STM8S if條件非真,卻能執(zhí)行,為什么?

    if條件非真,卻能執(zhí)行,一般是單片機什么故障,需要做哪些處理可以避免這種情況的發(fā)生?
    發(fā)表于 05-06 06:08

    鴻蒙TypeScript入門學習第6天:【條件語句】

    條件語句用于基于不同的條件執(zhí)行不同的動作。 TypeScript 條件語句是通過一條或多條語句的
    的頭像 發(fā)表于 04-01 13:51 ?704次閱讀
    鴻蒙TypeScript入門學習第6天:【<b class='flag-5'>條件</b>語句】

    晶閘管的導通條件及關斷條件?

    晶閘管(Thyristor)是一種常用的半導體器件,廣泛應用于電力電子和電路控制領域。它可以用作開關、穩(wěn)壓器、整流器等。在進行詳細介紹晶閘管的導通條件和關斷條件之前,我們需要先了解一些基礎知識
    的頭像 發(fā)表于 03-12 15:01 ?3939次閱讀

    java死鎖產(chǎn)生的條件

    Java死鎖是指多個線程因為互相等待對方釋放資源而無法繼續(xù)執(zhí)行的情況。當線程處于死鎖狀態(tài)時,程序會無限期地等待資源,無法繼續(xù)執(zhí)行下去,從而導致整個系統(tǒng)的停滯。要理解并避免Java死鎖的產(chǎn)生,首先需要
    的頭像 發(fā)表于 12-04 13:42 ?425次閱讀

    if函數(shù)多個條件怎么用

    在Excel中,如果我們需要根據(jù)多個條件執(zhí)行不同的操作,我們可以使用IF函數(shù)的嵌套或邏輯運算符來實現(xiàn)。 IF函數(shù)是一個常用的邏輯函數(shù),它用于根據(jù)特定
    的頭像 發(fā)表于 12-03 10:35 ?2197次閱讀

    if函數(shù)多個條件并列怎么輸入

    3 :執(zhí)行代碼塊 在上述示例中,條件1、條件2和條件3都需要被滿足,才能執(zhí)行if語句后面的代碼塊。如果其中任何一個
    的頭像 發(fā)表于 12-03 10:31 ?3609次閱讀

    case怎么使用多個條件

    在編寫代碼時,我們經(jīng)常需要根據(jù)不同的條件執(zhí)行不同的操作。在Python中,我們可以使用 if 語句來實現(xiàn)這一目的。 if 語句允許我們設置多個條件,并且根據(jù)不同的
    的頭像 發(fā)表于 11-30 14:34 ?1122次閱讀

    sql語句多個條件怎么連接

    在SQL中,多個條件可以使用邏輯運算符連接,常用的邏輯運算符有AND、OR和NOT。這些運算符可以幫助我們在查詢中指定多個條件以過濾數(shù)據(jù),從而獲得我們需要的結果集。 AND運算符用于同時滿足多個
    的頭像 發(fā)表于 11-23 11:34 ?2269次閱讀

    sql where條件執(zhí)行順序

    SQL語句中的WHERE條件是用來篩選數(shù)據(jù)的,它決定了哪些數(shù)據(jù)會被返回給用戶。WHERE條件執(zhí)行順序是影響SQL語句性能的一個重要因素,正確地理解和優(yōu)化WHERE條件
    的頭像 發(fā)表于 11-23 11:31 ?2123次閱讀

    sql怎么在where條件判斷

    在SQL中,WHERE條件用于篩選符合特定條件的記錄。它提供了一種在查詢中過濾數(shù)據(jù)的方法,使您能夠根據(jù)所需的特定條件對查詢結果進行更精確的控制。 在WHERE子句中,您可以使用各種操作
    的頭像 發(fā)表于 11-23 11:30 ?1827次閱讀

    sql語句where條件查詢

    SQL是一種用于管理和操作關系型數(shù)據(jù)庫的編程語言。其中,WHERE子句是用于過濾查詢結果的重要部分。通過WHERE條件,我們可以指定一系列條件,以僅返回滿足
    的頭像 發(fā)表于 11-23 11:28 ?1105次閱讀

    python if語句多個條件怎么用

    所有條件都必須為True才會執(zhí)行if語句中的代碼塊,or運算符表示只要有一個條件為True就會執(zhí)行代碼塊,而not運算符則用于反轉(zhuǎn)
    的頭像 發(fā)表于 11-21 16:45 ?2844次閱讀

    python中if三個條件怎么寫

    確定程序的執(zhí)行路徑。這時,我們可以使用 if-elif-else 結構來處理多個條件。 if-elif-else 結構是一個被廣泛使用的控制結構,在許多編程語言中都有類似的實現(xiàn)。它允許我們依次測試多個
    的頭像 發(fā)表于 11-21 16:42 ?1311次閱讀

    python if 多條件并列判斷

    Python中的if語句允許我們根據(jù)條件執(zhí)行不同的代碼塊。有時候我們需要同時判斷多個條件是否滿足,并根據(jù)結果執(zhí)行不同的代碼塊。在這篇文章中,我們將會進行詳盡、詳實且細致的介紹。 首先,
    的頭像 發(fā)表于 11-21 16:40 ?1702次閱讀