1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        ONNX初探

        共 24591字,需瀏覽 50分鐘

         ·

        2021-01-23 19:55

        0x0. 背景

        最近看了一些ONNX的資料,一個(gè)最大的感受就是這些資料太凌亂了。大多數(shù)都是在介紹ONNX模型轉(zhuǎn)換中碰到的坑點(diǎn)以及解決辦法。很少有文章可以系統(tǒng)的介紹ONNX的背景,分析ONNX格式,ONNX簡(jiǎn)化方法等。所以,綜合了相當(dāng)多資料之后我準(zhǔn)備寫一篇ONNX相關(guān)的文章,希望對(duì)大家有用。

        0x1. 什么是ONNX?

        簡(jiǎn)單描述一下官方介紹,開放神經(jīng)網(wǎng)絡(luò)交換(Open Neural Network Exchange)簡(jiǎn)稱ONNX是微軟和Facebook提出用來(lái)表示深度學(xué)習(xí)模型的開放格式。所謂開放就是ONNX定義了一組和環(huán)境,平臺(tái)均無(wú)關(guān)的標(biāo)準(zhǔn)格式,來(lái)增強(qiáng)各種AI模型的可交互性。

        換句話說(shuō),無(wú)論你使用何種訓(xùn)練框架訓(xùn)練模型(比如TensorFlow/Pytorch/OneFlow/Paddle),在訓(xùn)練完畢后你都可以將這些框架的模型統(tǒng)一轉(zhuǎn)換為ONNX這種統(tǒng)一的格式進(jìn)行存儲(chǔ)。注意ONNX文件不僅僅存儲(chǔ)了神經(jīng)網(wǎng)絡(luò)模型的權(quán)重,同時(shí)也存儲(chǔ)了模型的結(jié)構(gòu)信息以及網(wǎng)絡(luò)中每一層的輸入輸出和一些其它的輔助信息。我們直接從onnx的官方模型倉(cāng)庫(kù)拉一個(gè)yolov3-tiny的onnx模型(地址為:https://github.com/onnx/models/tree/master/vision/object_detection_segmentation/tiny-yolov3/model)用Netron可視化一下看看ONNX模型長(zhǎng)什么樣子。

        yolov3-tiny onnx的可視化結(jié)果

        這里我們可以看到ONNX的版本信息,這個(gè)ONNX模型是由Keras導(dǎo)出來(lái)的,以及模型的輸入輸出等信息,如果你對(duì)模型的輸入輸出有疑問(wèn)可以直接看:https://github.com/onnx/models/blob/master/vision/object_detection_segmentation/tiny-yolov3/README.md

        在獲得ONNX模型之后,模型部署人員自然就可以將這個(gè)模型部署到兼容ONNX的運(yùn)行環(huán)境中去。這里一般還會(huì)設(shè)計(jì)到額外的模型轉(zhuǎn)換工作,典型的比如在Android端利用NCNN部署ONNX格式模型,那么就需要將ONNX利用NCNN的轉(zhuǎn)換工具轉(zhuǎn)換到NCNN所支持的binparam格式。

        但在實(shí)際使用ONNX的過(guò)程中,大多數(shù)人對(duì)ONNX了解得并不多,僅僅認(rèn)為它只是一個(gè)完成模型轉(zhuǎn)換和部署工具人而已,我們可以利用它完成模型轉(zhuǎn)換和部署。正是因?yàn)閷?duì)ONNX的不了解,在模型轉(zhuǎn)換過(guò)程中出現(xiàn)的各種不兼容或者不支持讓很多人浪費(fèi)了大量時(shí)間。這篇文章將從理論和實(shí)踐2個(gè)方面談一談ONNX。

        0x2.  ProtoBuf簡(jiǎn)介

        在分析ONNX組織格式前我們需要了解Protobuf, 如果你比較了解Protobuf可以略過(guò)此節(jié)。ONNX作為一個(gè)文件格式,我們自然需要一定的規(guī)則去讀取我們想要的信息或者是寫入我們需要保存信息。ONNX使用的是Protobuf這個(gè)序列化數(shù)據(jù)結(jié)構(gòu)去存儲(chǔ)神經(jīng)網(wǎng)絡(luò)的權(quán)重信息。熟悉Caffe或者Caffe2的同學(xué)應(yīng)該知道,它們的模型存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)協(xié)議也是Protobuf。這個(gè)從安裝ONNX包的時(shí)候也可以看到:

        安裝onnx時(shí)依賴了protobuf

        Protobuf是一種輕便高效的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)格式,可以用于結(jié)構(gòu)化數(shù)據(jù)串行化,或者說(shuō)序列化。它很適合做數(shù)據(jù)存儲(chǔ)或數(shù)據(jù)交換格式。可用于通訊協(xié)議、數(shù)據(jù)存儲(chǔ)等領(lǐng)域的語(yǔ)言無(wú)關(guān)、平臺(tái)無(wú)關(guān)、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)格式。目前提供了 C++、Java、Python 三種語(yǔ)言的 API(摘自官方介紹)。

        Protobuf協(xié)議是一個(gè)以*.proto后綴文件為基礎(chǔ)的,這個(gè)文件描述了用戶自定義的數(shù)據(jù)結(jié)構(gòu)。如果需要了解更多細(xì)節(jié)請(qǐng)參考0x7節(jié)的資料3,這里只是想表達(dá)ONNX是基于Protobuf來(lái)做數(shù)據(jù)存儲(chǔ)和傳輸,那么自然onnx.proto就是ONNX格式文件了,接下來(lái)我們就分析一下ONNX格式。

        0x3. ONNX格式分析

        這一節(jié)我們來(lái)分析一下ONNX的組織格式,上面提到ONNX中最核心的部分就是onnx.protohttps://github.com/onnx/onnx/blob/master/onnx/onnx.proto)這個(gè)文件了,它定義了ONNX這個(gè)數(shù)據(jù)協(xié)議的規(guī)則和一些其它信息?,F(xiàn)在是2021年1月,這個(gè)文件有700多行,我們沒有必要把這個(gè)文件里面的每一行都貼出來(lái),我們只要搞清楚里面的核心部分即可。在這個(gè)文件里面以message關(guān)鍵字開頭的對(duì)象是我們需要關(guān)心的。我們列一下最核心的幾個(gè)對(duì)象并解釋一下它們之間的關(guān)系。

        • ModelProto
        • GraphProto
        • NodeProto
        • ValueInfoProto
        • TensorProto
        • AttributeProto

        當(dāng)我們加載了一個(gè)ONNX之后,我們獲得的就是一個(gè)ModelProto,它包含了一些版本信息,生產(chǎn)者信息和一個(gè)GraphProto。在GraphProto里面又包含了四個(gè)repeated數(shù)組,它們分別是node(NodeProto類型),input(ValueInfoProto類型),output(ValueInfoProto類型)和initializer(TensorProto類型),其中node中存放了模型中所有的計(jì)算節(jié)點(diǎn),input存放了模型的輸入節(jié)點(diǎn),output存放了模型中所有的輸出節(jié)點(diǎn),initializer存放了模型的所有權(quán)重參數(shù)。

        我們知道要完整的表達(dá)一個(gè)神經(jīng)網(wǎng)絡(luò),不僅僅要知道網(wǎng)絡(luò)的各個(gè)節(jié)點(diǎn)信息,還要知道它們的拓?fù)潢P(guān)系。這個(gè)拓?fù)潢P(guān)系在ONNX中是如何表示的呢?ONNX的每個(gè)計(jì)算節(jié)點(diǎn)都會(huì)有inputoutput兩個(gè)數(shù)組,這兩個(gè)數(shù)組是string類型,通過(guò)inputoutput的指向關(guān)系,我們就可以利用上述信息快速構(gòu)建出一個(gè)深度學(xué)習(xí)模型的拓?fù)鋱D。這里要注意一下,GraphProto中的input數(shù)組不僅包含我們一般理解中的圖片輸入的那個(gè)節(jié)點(diǎn),還包含了模型中所有的權(quán)重。例如,Conv層里面的W權(quán)重實(shí)體是保存在initializer中的,那么相應(yīng)的會(huì)有一個(gè)同名的輸入在input中,其背后的邏輯應(yīng)該是把權(quán)重也看成模型的輸入,并通過(guò)initializer中的權(quán)重實(shí)體來(lái)對(duì)這個(gè)輸入做初始化,即一個(gè)賦值的過(guò)程。

        最后,每個(gè)計(jì)算節(jié)點(diǎn)中還包含了一個(gè)AttributeProto數(shù)組,用來(lái)描述該節(jié)點(diǎn)的屬性,比如Conv節(jié)點(diǎn)或者說(shuō)卷積層的屬性包含grouppad,strides等等,每一個(gè)計(jì)算節(jié)點(diǎn)的屬性,輸入輸出信息都詳細(xì)記錄在https://github.com/onnx/onnx/blob/master/docs/Operators.md

        0x4. onnx.helper

        現(xiàn)在我們知道ONNX是把一個(gè)網(wǎng)絡(luò)的每一層或者說(shuō)一個(gè)算子當(dāng)成節(jié)點(diǎn)node,使用這些Node去構(gòu)建一個(gè)Graph,即一個(gè)網(wǎng)絡(luò)。最后將Graph和其它的生產(chǎn)者信息,版本信息等合并在一起生成一個(gè)Model,也即是最終的ONNX模型文件。在構(gòu)建ONNX模型的時(shí)候,https://github.com/onnx/onnx/blob/master/onnx/helper.py這個(gè)文件非常重要,我們可以利用它提供的make_nodemake_graph,make_tensor等等接口完成一個(gè)ONNX模型的構(gòu)建,一個(gè)示例如下:

        import onnx
        from onnx import helper
        from onnx import AttributeProto, TensorProto, GraphProto


        # The protobuf definition can be found here:
        # https://github.com/onnx/onnx/blob/master/onnx/onnx.proto


        # Create one input (ValueInfoProto)
        X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [32])
        pads = helper.make_tensor_value_info('pads', TensorProto.FLOAT, [14])

        value = helper.make_tensor_value_info('value', AttributeProto.FLOAT, [1])


        # Create one output (ValueInfoProto)
        Y = helper.make_tensor_value_info('Y', TensorProto.FLOAT, [34])

        # Create a node (NodeProto) - This is based on Pad-11
        node_def = helper.make_node(
            'Pad'# node name
            ['X''pads''value'], # inputs
            ['Y'], # outputs
            mode='constant'# attributes
        )

        # Create the graph (GraphProto)
        graph_def = helper.make_graph(
            [node_def],
            'test-model',
            [X, pads, value],
            [Y],
        )

        # Create the model (ModelProto)
        model_def = helper.make_model(graph_def, producer_name='onnx-example')

        print('The model is:\n{}'.format(model_def))
        onnx.checker.check_model(model_def)
        print('The model is checked!')

        這個(gè)官方示例為我們演示了如何使用onnx.helpermake_tensormake_tensor_value_info,make_attribute,make_node,make_graph,make_node等方法來(lái)完整構(gòu)建了一個(gè)ONNX模型。需要注意的是在上面的例子中,輸入數(shù)據(jù)是一個(gè)一維Tensor,初始維度為[2],這也是為什么經(jīng)過(guò)維度為[1,4]的Pad操作之后獲得的輸出Tensor維度為[3,4]。另外由于Pad操作是沒有帶任何權(quán)重信息的,所以當(dāng)你打印ONNX模型時(shí),ModelProtoGraphProto是沒有initializer這個(gè)屬性的。

        0x5. onnx-simplifier

        原本這里是要總結(jié)一些使用ONNX進(jìn)行模型部署經(jīng)常碰到一些因?yàn)榘姹炯嫒菪?,或者各種框架OP沒有對(duì)齊等原因?qū)е碌母鞣NBUG。但是這樣會(huì)顯得文章很長(zhǎng),所以這里以一個(gè)經(jīng)典的Pytorch轉(zhuǎn)ONNX的reshape問(wèn)題為例子,來(lái)嘗試講解一下大老師的onnx-simplifier是怎么處理的,個(gè)人認(rèn)為這個(gè)問(wèn)題是基于ONNX進(jìn)行模型部署最經(jīng)典的問(wèn)題。希望在解決這個(gè)問(wèn)題的過(guò)程中大家能有所收獲。

        問(wèn)題發(fā)生在當(dāng)我們想把下面這段代碼導(dǎo)出ONNX模型時(shí):

        import torch


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

            def forward(self, x):
                return x.view((x.shape[0], x.shape[1], x.shape[3], x.shape[2]))


        net = JustReshape()
        model_name = 'just_reshape.onnx'
        dummy_input = torch.randn(2345)
        torch.onnx.export(net, dummy_input, model_name, input_names=['input'], output_names=['output'])

        由于這個(gè)模型輸入維度是固定的,所以我們期望模型是這樣的:

        我們期待的ONNX模型

        但是,即使使用了ONNX的polished工具也只能獲得下面的模型:

        實(shí)際上轉(zhuǎn)出來(lái)的ONNX模型

        要解決這個(gè)問(wèn)題,有兩種方法,第一種是做一個(gè)強(qiáng)制類型轉(zhuǎn)換,將x.shape[0]類似的變量強(qiáng)制轉(zhuǎn)換為常量即int(x.shape[0]),或者使用大老師的onnx-simplifer來(lái)解決這一問(wèn)題。

        之前一直好奇onnx-simplifer是怎么做的,最近對(duì)ONNX有了一些理解之后也能逐步看懂做法了。我來(lái)嘗試解釋一下。onnx-simplifer的核心思路就是利用onnxruntime推斷一遍ONNX的計(jì)算圖,然后使用常量輸出替代冗余的運(yùn)算OP。主體代碼為:

        def simplify(model: Union[str, onnx.ModelProto], check_n: int = 0, perform_optimization: bool = True,
                     skip_fuse_bn: bool = False, input_shapes: Optional[TensorShapes] = None, skipped_optimizers: Optional[Sequence[str]] = None, skip_shape_inference=False)
         \
                -> Tuple[onnx.ModelProto, bool]:

            if input_shapes is None:
                input_shapes = {}
            if type(model) == str:
                # 加載ONNX模型
                model = onnx.load(model)
            # 檢查ONNX模型格式是否正確,圖結(jié)構(gòu)是否完整,節(jié)點(diǎn)是否正確等
            onnx.checker.check_model(model)
            # 深拷貝一份原始ONNX模型
            model_ori = copy.deepcopy(model)
            if not skip_shape_inference:
                # 獲取ONNX模型中特征圖的尺寸
                model = infer_shapes(model)

            input_shapes = check_and_update_input_shapes(model, input_shapes)

            if perform_optimization:
                model = optimize(model, skip_fuse_bn, skipped_optimizers)

            const_nodes = get_constant_nodes(model)
            res = forward_for_node_outputs(
                model, const_nodes, input_shapes=input_shapes)
            const_nodes = clean_constant_nodes(const_nodes, res)
            model = eliminate_const_nodes(model, const_nodes, res)
            onnx.checker.check_model(model)

            if not skip_shape_inference:
                model = infer_shapes(model)
            if perform_optimization:
                model = optimize(model, skip_fuse_bn, skipped_optimizers)

            check_ok = check(model_ori, model, check_n, input_shapes=input_shapes)

            return model, check_ok

        上面有一行:model = infer_shapes(model) 是獲取ONNX模型中特征圖的尺寸,它的具體實(shí)現(xiàn)如下:

        def infer_shapes(model: onnx.ModelProto) -> onnx.ModelProto:
            try:
                model = onnx.shape_inference.infer_shapes(model)
            except:
                pass
            return model

        我們保存一下調(diào)用了這個(gè)接口之后的ONNX模型,并將其可視化看一下:

        相比于原始的ONNX模型,現(xiàn)在我們知道了每一層特征圖的shape信息

        相對(duì)于原始的ONNX模型,現(xiàn)在每一條線都新增了一個(gè)shape信息,代表它的前一個(gè)特征圖的shape是怎樣的。

        接著,程序使用到了check_and_update_input_shapes接口,這個(gè)接口的代碼示例如下,它可以用來(lái)判斷輸入的格式是否正確以及輸入模型是否存在所有的指定輸入節(jié)點(diǎn)。

        def check_and_update_input_shapes(model: onnx.ModelProto, input_shapes: TensorShapes) -> TensorShapes:
            input_names = get_input_names(model)
            if None in input_shapes:
                if len(input_names) == 1:
                    input_shapes[input_names[0]] = input_shapes[None]
                    del input_shapes[None]
                else:
                    raise RuntimeError(
                        'The model has more than 1 inputs, please use the format "input_name:dim0,dim1,...,dimN" in --input-shape')
            for x in input_shapes:
                if x not in input_names:
                    raise RuntimeError(
                        'The model doesn\'t have input named "{}"'.format(x))
            return input_shapes

        在這個(gè)例子中,如果我們指定input_shapes為:{'input': [2, 3, 4, 5]},那么這個(gè)函數(shù)的輸出也為{'input': [2, 3, 4, 5]}。如果不指定,輸出就是{}。驗(yàn)證這個(gè)函數(shù)的調(diào)用代碼如下所示:

        構(gòu)造input_shapes參數(shù),傳入simplify

        確定了輸入沒有問(wèn)題之后,程序會(huì)根據(jù)用戶指定是否優(yōu)化ONNX模型進(jìn)入優(yōu)化函數(shù),函數(shù)定義如下:

        def optimize(model: onnx.ModelProto, skip_fuse_bn: bool, skipped_optimizers: Optional[Sequence[str]]) -> onnx.ModelProto:
            """
            :model參數(shù): 待優(yōu)化的ONXX模型.
            :return: 優(yōu)化之后的ONNX模型.
            簡(jiǎn)化之前, 使用這個(gè)方法產(chǎn)生會(huì)在'forward_all'用到的ValueInfo
            簡(jiǎn)化之后,使用這個(gè)方法去折疊前一步產(chǎn)生的常量到initializer中并且消除沒被使用的常量
            """


            onnx.checker.check_model(model)
            onnx.helper.strip_doc_string(model)
            optimizers_list = [
                'eliminate_deadend',
                'eliminate_nop_dropout',
                'eliminate_nop_cast',
                'eliminate_nop_monotone_argmax''eliminate_nop_pad',
                'extract_constant_to_initializer''eliminate_unused_initializer',
                'eliminate_nop_transpose',
                'eliminate_nop_flatten''eliminate_identity',
                'fuse_add_bias_into_conv',
                'fuse_consecutive_concats',
                'fuse_consecutive_log_softmax',
                'fuse_consecutive_reduce_unsqueeze''fuse_consecutive_squeezes',
                'fuse_consecutive_transposes''fuse_matmul_add_bias_into_gemm',
                'fuse_pad_into_conv''fuse_transpose_into_gemm''eliminate_duplicate_initializer'
            ]
            if not skip_fuse_bn:
                optimizers_list.append('fuse_bn_into_conv')
            if skipped_optimizers is not None:
                for opt in skipped_optimizers:
                    try:
                        optimizers_list.remove(opt)
                    except ValueError:
                        pass

            model = onnxoptimizer.optimize(model, optimizers_list,
                                           fixed_point=True)
            onnx.checker.check_model(model)
            return model

        這個(gè)函數(shù)的功能是對(duì)原始的ONNX模型做一些圖優(yōu)化工作,比如merge_bn,fuse_add_bias_into_conv等等。我們使用onnx.save保存一下這個(gè)例子中圖優(yōu)化后的模型,可以發(fā)現(xiàn)它和優(yōu)化前的可視化效果是一樣的,如下圖所示:

        optimize 之后的ONNX模型可視化

        這是因?yàn)樵谶@個(gè)模型中是沒有上面列舉到的那些可以做圖優(yōu)化的情況,但是當(dāng)我們打印一下ONNX模型我們會(huì)發(fā)現(xiàn)optimize過(guò)后的ONNX模型多出一些initializer數(shù)組:

        相比optimize前的模型多出了一些initializer數(shù)組

        這些數(shù)組存儲(chǔ)的就是這個(gè)圖中那些常量OP的具體值,通過(guò)這個(gè)處理我們就可以調(diào)用get_constant_nodes函數(shù)來(lái)獲取ONNX模型的常量OP了,這個(gè)函數(shù)的詳細(xì)解釋如下:

        def get_constant_nodes(m: onnx.ModelProto) -> List[onnx.NodeProto]:
            const_nodes = []
            # 如果節(jié)點(diǎn)的name在ONNX的GraphProto的initizlizer數(shù)組里面,它就是靜態(tài)的tensor
            const_tensors = [x.name for x in m.graph.initializer]
            # 顯示的常量OP也加進(jìn)來(lái)
            const_tensors.extend([node.output[0]
                                  for node in m.graph.node if node.op_type == 'Constant'])
            # 一些節(jié)點(diǎn)的輸出shape是由輸入節(jié)點(diǎn)決定的,我們認(rèn)為這個(gè)節(jié)點(diǎn)的輸出shape并不是常量,
            # 所以我們不需要簡(jiǎn)化這種節(jié)點(diǎn)
            dynamic_tensors = []
            # 判斷是否為動(dòng)態(tài)OP
            def is_dynamic(node):
                if node.op_type in ['NonMaxSuppression''NonZero''Unique'and node.input[0not in const_tensors:
                    return True
                if node.op_type in ['Reshape''Expand''Upsample''ConstantOfShape'and len(node.input) > 1 and node.input[1not in const_tensors:
                    return True
                if node.op_type in ['Resize'and ((len(node.input) > 2 and node.input[2not in const_tensors) or (len(node.input) > 3 and node.input[3not in const_tensors)):
                    return True
                return False
            for node in m.graph.node:
                if any(x in dynamic_tensors for x in node.input):
                    dynamic_tensors.extend(node.output)
                elif node.op_type == 'Shape':
                    const_nodes.append(node)
                    const_tensors.extend(node.output)
                elif is_dynamic(node):
                    dynamic_tensors.extend(node.output)
                elif all([x in const_tensors for x in node.input]):
                    const_nodes.append(node)
                    const_tensors.extend(node.output)
            # 深拷貝
            return copy.deepcopy(const_nodes)

        在這個(gè)例子中,我們打印一下執(zhí)行這個(gè)獲取常量OP函數(shù)之后,Graph中有哪些OP被看成了常量OP。

        紅色框中的所有節(jié)點(diǎn)都是常量節(jié)點(diǎn)

        獲取了模型中所有的常量OP之后,我們需要把所有的靜態(tài)節(jié)點(diǎn)擴(kuò)展到ONNX Graph的輸出節(jié)點(diǎn)列表中,然后利用onnxruntme執(zhí)行一次forward:

        def forward_for_node_outputs(model: onnx.ModelProto, nodes: List[onnx.NodeProto],
                                     input_shapes: Optional[TensorShapes] = None)
         -> Dict[str, np.ndarray]:

            if input_shapes is None:
                input_shapes = {}
            model = copy.deepcopy(model)
            # nodes 是Graph中所有的靜態(tài)OP
            add_features_to_output(model, nodes)
            res = forward(model, input_shapes=input_shapes)
            return res

        其中add_features_to_output的定義如下:

        def add_features_to_output(m: onnx.ModelProto, nodes: List[onnx.NodeProto]) -> None:
            """
            Add features to output in pb, so that ONNX Runtime will output them.
            :param m: the model that will be run in ONNX Runtime
            :param nodes: nodes whose outputs will be added into the graph outputs
            """

            # ONNX模型的graph擴(kuò)展輸出節(jié)點(diǎn),獲取所有靜態(tài)OP的輸出和原始輸出節(jié)點(diǎn)的輸出
            for node in nodes:
                for output in node.output:
                    m.graph.output.extend([onnx.ValueInfoProto(name=output)])

        最后的forward函數(shù)就是利用onnxruntime推理獲得我們指定的輸出節(jié)點(diǎn)的值。這個(gè)函數(shù)這里不進(jìn)行解釋。推理完成之后,進(jìn)入下一個(gè)函數(shù)clean_constant_nodes,這個(gè)函數(shù)的定義如下:

        def clean_constant_nodes(const_nodes: List[onnx.NodeProto], res: Dict[str, np.ndarray]):
            """
            It seems not needed since commit 6f2a72, but maybe it still prevents some unknown bug
            :param const_nodes: const nodes detected by `get_constant_nodes`
            :param res: The dict containing all tensors, got by `forward_all`
            :return: The constant nodes which have an output in res
            """

            return [node for node in const_nodes if node.output[0in res]

        這個(gè)函數(shù)是用來(lái)清洗那些沒有被onnxruntime推理的靜態(tài)節(jié)點(diǎn),但通過(guò)上面的optimize邏輯,我們的graph中其實(shí)已經(jīng)不存在這個(gè)情況了(沒有被onnxruntime推理的靜態(tài)節(jié)點(diǎn)在圖優(yōu)化階段會(huì)被優(yōu)化掉),因此這個(gè)函數(shù)理論上是可以刪除的。這個(gè)地方是為了避免刪除掉有可能引發(fā)其它問(wèn)題就保留了。

        不過(guò)從一些實(shí)際經(jīng)驗(yàn)來(lái)看,還是保留吧,畢竟不能保證ONNX的圖優(yōu)化就完全正確,前段時(shí)間剛發(fā)現(xiàn)了TensorRT圖優(yōu)化出了一個(gè)BUG。保留這個(gè)函數(shù)可以提升一些程序的穩(wěn)定性。

        TensorRT存在一個(gè)BUG,這個(gè)結(jié)構(gòu)的relu會(huì)被tensorrt的優(yōu)化器給移動(dòng)到eltwise之后

        接下來(lái)就是這個(gè)onnx-simplifier最核心的步驟了,即將常量節(jié)點(diǎn)從原始的ONNX Graph中移除,函數(shù)接口為eliminate_const_nodes

        def eliminate_const_nodes(model: onnx.ModelProto, const_nodes: List[onnx.NodeProto],
                                  res: Dict[str, np.ndarray])
         -> onnx.ModelProto:

            """
            :model參數(shù): 原始ONNX模型
            :const_nodes參數(shù): 使用`get_constant_nodes`獲得的靜態(tài)OP
            :res參數(shù): 包含所有輸出Tensor的字典
            :return: 簡(jiǎn)化后的模型. 所有冗余操作都已刪除.
            """

            for i, node in enumerate(model.graph.node):
                if node in const_nodes:
                    for output in node.output:
                        new_node = copy.deepcopy(node)
                        new_node.name = "node_" + output
                        new_node.op_type = 'Constant'
                        new_attr = onnx.helper.make_attribute(
                            'value',
                            onnx.numpy_helper.from_array(res[output], name=output)
                        )
                        del new_node.input[:]
                        del new_node.attribute[:]
                        del new_node.output[:]
                        new_node.output.extend([output])
                        new_node.attribute.extend([new_attr])
                        insert_elem(model.graph.node, i + 1, new_node)
                    del model.graph.node[i]

            return model

        運(yùn)行這個(gè)函數(shù)之后我們獲得的ONNX模型可視化結(jié)果是這樣子的:

        將常量節(jié)點(diǎn)從原始的ONNX刪除后

        注意,這里獲得的ONNX模型中雖然常量節(jié)點(diǎn)已經(jīng)從Graph中斷開了,即相當(dāng)于這個(gè)DAG里面多了一些單獨(dú)的點(diǎn),但是這些點(diǎn)還是存在的。因此,我們?cè)賵?zhí)行一次optimize就可以獲得最終簡(jiǎn)化后的ONNX模型了。最終簡(jiǎn)化后的ONNX模型如下圖所示:

        簡(jiǎn)化后的ONNX模型

        0x6. 總結(jié)

        介于篇幅原因,介紹ONNX的第一篇文章就介紹到這里了,后續(xù)可能會(huì)結(jié)合更多實(shí)踐的經(jīng)驗(yàn)來(lái)談?wù)凮NNX了,例如OneFlow模型導(dǎo)出ONNX進(jìn)行部署???傊?,文章很長(zhǎng),謝謝你的觀看,希望這篇文章有幫助到你。最后歡迎star大老師的onnx-simplifier。

        0x7. 參考資料

        • 【1】https://zhuanlan.zhihu.com/p/86867138
        • 【2】https://oldpan.me/archives/talk-about-onnx
        • 【3】https://blog.csdn.net/chengzi_comm/article/details/53199278
        • 【4】https://www.jianshu.com/p/a24c88c0526a
        • 【5】https://bindog.github.io/blog/2020/03/13/deep-learning-model-convert-and-depoly/
        • 【6】 https://github.com/daquexian/onnx-simplifier

        歡迎關(guān)注GiantPandaCV, 在這里你將看到獨(dú)家的深度學(xué)習(xí)分享,堅(jiān)持原創(chuàng),每天分享我們學(xué)習(xí)到的新鮮知識(shí)。( ? ?ω?? )?

        有對(duì)文章相關(guān)的問(wèn)題,或者想要加入交流群,歡迎添加BBuf微信:

        二維碼

        為了方便讀者獲取資料以及我們公眾號(hào)的作者發(fā)布一些Github工程的更新,我們成立了一個(gè)QQ群,二維碼如下,感興趣可以加入。

        公眾號(hào)QQ交流群


        瀏覽 63
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            午夜色色福利| 2025AV在线| 午夜福利大香蕉| 影音先锋国产精品| 亚洲AV免费在线观看| 巨乳国产一区| 欧美成人免费精品| 91蜜桃视频在线观看| 9797色色| 欧美激情综合色综合啪啪五月| 青青在线| 人人操人人网站| 青青草大香蕉伊人| 午夜成人无码| 一区二区高清无码| 十八禁网站在线观看| 亚洲精品女人| 欧美在线免费观看| 偷拍三区| 人人看人人摸人人插| 成人伊人电影| www.俺来也| 一区无码| 亚洲图片在线| 91国产在线播放| 日韩一级片视频| 激情一一区二区三区| 中文字幕在线无码视频| 九九国产| 日本色综合| 中文字幕亚洲观看| 国产av资源网| 日本黄色大片| 国产成人精品a视频| 99久久婷婷国产综合精品| 欧美精品人妻| 人妻在线你懂的| 国产精品美女久久久| 中文在线字幕免费观看| 国产三级无码| 日韩无码一区二区三| 成人在线免费电影| 国产一级AAAAA片免费| 日狠狠| 国产精品久久久久久精| www.狠狠撸| 操日视频| 蜜臀久久久| 先锋资源av| 国产色自拍| 亚洲中文字幕人妻| 国产伦精品一区二区三区妓女| 亚洲三级国产| 欧美色插| 99国产精品| 日本黄色片在线播放| 午夜成人视频在线观看| 国产海角视频| 91中文字幕网| 成人自拍网| 欧美日韩三级在线| 日韩激情网站| 女人特级毛片18| 亚洲成人AAAAA| 成人免费看AA片| 91精品国产综合久久久蜜臀粉嫩| 在线免费看黄色视频| 日韩中文字幕无码| 中文字幕免费在线观看视频| 亚洲精品无码久久| 无码人妻丰满熟妇区毛片蜜桃麻豆| 日韩五码在线| 国产伦精品一区二区三区妓女| 亚洲无码另类| 无码人妻精品一区二区三区蜜桃91| 操逼日韩| 91蝌蚪视频在线播放| xxxx国产| 伊人综合干| 亚洲专区在线播放| 女侠吕四娘第二部| 激情免费网站| 亚洲AV成人无码久久精品麻豆| 成人色视| 无码狠狠躁久久久久久久91| 亚洲欧美激情视频| 欧美色噜噜| 三级丁香在线| 蜜臀久久久99久久久久久久| 91麻豆精品国产91久久久熟女| 一级一级a免一级a做免费线看内裤| 91亚洲高清| 五月丁香六月久久| 影音先锋av资源在线| 2025精品精品视频| 成人激情免费视频| 西西444www| 一区二区三区高清不卡| 插菊花综合网3| 亚洲成人a片| 豆花视频成人版www满18 | 91视频18| 精品人人人人| 依人成人| 人妻丰满熟妇av无码| 免费三级网站| 伊人偷拍视频| 黄网在线免费观看| 国产白嫩精品久久久久久| 亚洲操操| 性爱视频亚洲| 亚洲无码黄色| 人人射人人摸| 99精品在线免费观看| 翔田千里av在线| 四虎黄色网址| 日韩成人无码精品| 无码h| 一级二级三级毛片| 欧美成人视频在线观看| 久草电影在线观看| 男女拍拍视频| 日本中文字幕不卡| 免费性爱视频| 国产操逼免费视频| 中文字幕视频一区日日骚| 男女啪啪免费视频| 懂色一区二区二区在线播放视频| 精品久久久久久久久久久| 天天日综合网| 欧美日韩国产成人| 四川少BBB搡BBB爽爽爽| 在线无码视频| 无码一区二区三区在线观看| 操B视频在线免费观看| 草比视频| eeuss久久| 欧美成人精品欧美一级乱黄| 日韩啊啊啊| 一级黄色毛片| 91视频国产精品| 日韩一区二区三区在线视频| 高清av在线| 日本A片在线免费观看| 亚洲无码免费| 免费手机av| 鲁鲁鲁鲁鲁鲁鲁777777| 人人看人人摸人人| 91视频你懂的| 成人伊人AV| 亚洲日本欧美| 青春草在线免费视频| 成人在线观看AV| 69色综合| 色播视频在线观看| 亚洲五月婷婷| 亚欧洲精品在线视频免费观看| 国产又粗又大又爽| 国产成人视频| 日逼视频免费| 久久久久久少妇| 国产熟妇码视频户外直播| 男人天堂视频在线观看| 午夜xxx| 国产麻豆剧传媒精品国产AV| 99热在线观看免费| 一级片三级片| 免费无码国产在线53| 国产熟女| 999这里只有精品| 黄工厂精品视频在线播| 欧美国产激情| 在线天堂19| 久久影院av| 欧美丝袜脚交xxxxBH| 成人久久精品| 国产毛片777777| 黄色不卡视频| 婷婷五月天青草| 天天爽天天爽| 九九在线观看视频| 日本免费版网站nba| 国产A片精品| 国产在线秘麻豆精品观看| 一本久久精品一区二区| 欧美在线亚洲| 欧美视频A| 伊人网在线播放| 五月天狠狠干| 肏网站| av一卡二卡| 91人人操| 人妻少妇无码| 成年人黄色电影| 国产又爽又黄A片| 最美人妖系列国产Ts涵涵| 北条麻妃无码在线观看| 亚洲无码中文字幕在线播放| 97人人精品| 九九热在线精品视频| 成人毛片18毛片女人| 嫩BBB槡BBBB槡BBBB撒尿-百度| 中文字幕人妻互换av久久| 人人操超碰在线| 久久久久久久久久久久高清毛片一级| 成人在线观看网| 国产精品大香蕉| 精品国产91| 青娱乐AV在线| 中文在线免费看视频| 看一级黄色视频| 人人艹人人艹| 久久精品水多多www| 中文字幕三区| 国产激情在线播放| 91AV免费在线观看| 激情五月天在线视频| 竹菊影视一区二区三区| 91人人操| 无码网| 久久悠悠| 亚洲成人网在线观看| 69er小视频| 色婷婷久综合久久一本国产AV| 亚洲福利在线免费观看| 狠狠色噜噜狠狠狠7777米奇网| 撸撸操在线视频观看只有精品| 黑人一级片| 黄片入口| 亚洲黄色免费网站| 亚洲成人日韩| 中文字幕亚洲一区| 91蝌蚪视频在线观看| 亚洲日韩视频在线播放| 97国产在线观看| 丰满人妻| 91免费福利视频| 日韩午夜在线观看| 西西www444无码免费视频| 亚洲视频一区| 成人A毛片| 日本草逼视频| 亚洲激情网站| 成人无码区免费AV毛片| av天堂亚洲| 亚洲无码视频网站| 四虎精品一区二区| 黄色毛片电影| 亚洲无码高清视频在线| 美日韩免费视频| wwwa片| 亚洲人天堂| 你懂的网站在线观看| 国产乱伦中文字幕| 亚洲人操逼视频| 欧美久久免费| 先锋影音av资源站| 激情伊人| 欧美丰满美乳XXⅩ高潮www| 国产精品大全| 国产精品婷婷午夜在线观看| 激情丁香六月| 国产精品香蕉| 一级无码高清| 求欧美精品网址| 精品国产成人a在线观看| 中文字幕五码| AV无码人妻| 999精品视频在线| 亚洲无码免费在线观看| 青青草手机视频| 夜夜骚av一区二区三区| 亚洲狠狠干| 一本大道东京热av无码| 最近中文字幕免费mv第一季歌词強上 | 成人影片在线观看18| 亚洲精品久久久久毛片A级牛奶| 自拍偷拍一区二区三区| 国产色自拍| 国产一区视频18| 久久六六| 九九久久精品视频| 欧美在线视频a| 国产成人V在线精品一区| 日韩无码高清免费| 97人人操人人| 艹逼视频| 噜噜噜久久久| 国产操逼小视频| 中文字幕35页| 国产多人搡BBBB槡BBBB| 福利国产在线| 日本无码在线视频| 国产日韩欧美在线播放| 风流少妇一区二区三区91| 欧美成人精品在线| 日本亚洲黄色视频| 91精品久久香蕉国产线看观看 | 最全av在线| 北条麻妃视频在线播放| 久久久久久久AV| 青青草逼视频| 国产99久久九九精品无码免费| 日韩性爱视频在线观看| 欧美视频在线观看免费| 国产高清视频| 国产小视频免费在线观看| 十八禁福利网站| 丁香六月激情婷婷| 综合激情网站| 苍井空一区二区三区| 婷婷色小说| 亚洲一级在线| 国产色天使| 中文字幕一区三区人妻视频| av三级网站| 99成人网站| 肏逼视频网站| 波多野结衣无码AV在线| 人妻一区二区三区| 天天色小说| 99久久亚洲精品日本无码| 人人操人人摸人人爽| 中国无码视频| 久久婷婷国产| 免费中文资源在线观看| 91人妻无码精品| 丰滿人妻一区二区三| 久久久精品午夜人成欧洲亚洲韩国 | 超碰少妇| 无码欧美| 影音先锋婷婷| 久久中文字幕视频| 欧美一道本| 天天日夜夜爽| 伊人久久大香线蕉| 91精品婷婷国产综合久久蝌蚪 | 国产www视频| 成人A片免费观看| 麻豆A∨在线| h片在线观看| 成人动漫一区| 成人无码日韩精品| 亚洲欧美成人网| 婷婷五月天激情俺来也| 成人毛片视频网站| 国产人妻在线| 欧美成人性爱网| 黑人又粗又大XXXXOO| 99久久久精品久久久久久| 中文字幕区| 免费看黃色AAAAAA片| 精品91美女| 日韩无码高清免费| 国产操美女| 国产在线小视频| 久久依人大香蕉| 欧美激情视频一区二区| 亚洲激情五月天| 国产免费激情视频| 亚洲色热| 欧美综合色| 久久久少妇| 亚洲自拍中文字幕| 又紧又嫩又爽无遮挡免费| 嫩草99| 国产成人无码一区二区在线观看| 国产在线无码视频| 日韩女人性爱| 亚洲三级无码在线| 欧美丰满老熟妇XXXXX性| 日韩无码高清视频| 国产中文字字幕乱码无限| 久久婷婷六月综合| 中文字幕观看| 黄色永久免费| 91无码精品国产| 91国产视频在线播放| 亚洲视频五区| 天天撸天天操| 丰满人妻一区二区三区精品高清| 日韩精品一区二区三区黄冈站长| 99久久精品国产色欲| 欧美日韩黄色极品| 天天操夜| 国精产品秘一区二区| 色黄网站在线观看| 伊人成色| 人人操日本| 久久国产黄色视频| 欧美自拍性爱视频| 黃色一級片黃色一級片尖叫声-百度-百| 啊啊啊国产| AA精品| 黄色视频免费播放| 国产中文字幕亚洲综合欧美| 影音先锋成人AV资源| 乱伦三级| 人妻北条麻妃在线| 亚洲秘av无码一区二区| 自拍偷拍国产| 亚洲影院第一页在线观看| 国产卡一卡二| 男女日皮视频| 丁香五月天天| 青青草操逼视频| 精品国产免费无码久久噜噜噜AV| 久操视频免费| 先锋影音一区| 日韩aaaaaa| 天天操天天干欧美精品| 久久久久久伊人| 国产传媒在线观看| 成人动漫一区| 亚洲无码一级片| 大香蕉网站在线观看| 日韩欧美国产精品综合嫩V| 黄色福利| 熟女熟妇人妻一区二区三区| 国产午夜成人福利在线| 噜噜色小说| 欧美色交| 中文字幕在线免费观看电影| 麻豆一级片| 91视频在| 中国免费看片| 国产精品无码av| 亚洲中文视频免费| 农村少妇久久久久久久| 国产婬片一级A片AAA毛片AⅤ | 俺也来最新色视频| 亚洲电影在线观看| 9l视频自拍九色9l视频成人| 亚洲午夜成人| 国内超碰| 丁香五月在线| 亚洲欧美日韩高清| 国产成人精品a区在线观看| 色婷婷在线观看视频| 成人性爱自拍| 五月开心婷婷| 丰满熟妇人妻无码视频| 五月天黄色电影| 欧美成人在线免费视频| 欧美视频综合网| 国产色情视频| 中文在线A∨在线| 免费在线成人网| 国产AV小电影| 91人妻无码精品| 91最新网址| 天天操比| 在线观看av中文字幕| 日韩无码免费播放| 91无码精品国产AⅤ| 波多野结衣高清无码| 国产女主播在线观看| 天天插综合| 日韩高清无码中文字幕| 十八女人高潮A片免费| 黄色视频在线免费观| 亚洲成人天堂| 亚欧在线| 久久黄色视频免费看| 久久国产劲爆∧v内射| 中文字幕av久久爽爽| 色色色成人视频| 黄色激情视频网站| 天天色粽合合合合合合合| 无码人妻日本| 亚洲av在线免费观看| 人人妻天天干| 亚洲性爱手机版| 99热免费在线| 五月天精品| 做爱视频91| 婷婷性爱| 亚洲精品资源在线| 黄色视频网站在线播放| 亚洲色图狠狠撸| 免费a片视频| 亚洲无码激情视频| 91要爱爱| 亚洲中文无码在线| 亚洲涩情91日韩一区二区| 精品国精品自拍自在线| 秋霞精品一区二区三区| 中文在线字幕电视剧免费平台| 久久久久久久久久久国产| 毛片学生妹| 无码中文字幕在线观看| 久久精品视频99| 国产精品综合| 思思热在线视频播放| 日韩天堂| 久草免费电影| 男女无套在线观看免费| 久久性爱免费视频| 超碰91在线| 亚洲69视频| 国产操b视频| 成年人视频在线观看免费| 亚洲高清视频在线观看| 91丝袜| 国产成人无码精品一区秘二区| 日韩精品91| 国产成人精品电影| 可以看的黄色视频| 人人操人人爱人人拍| 91精品人妻一区二| NP玩烂了公用爽灌满视频播放 | 国产黄片在线播放| 韩国三级HD中文字幕2019年| 成人午夜福利电影| 国产精品久久久久久久久久久久久久久 | 夜夜骚AV一二三区无码| 尹人成人| 国产乱伦免费视频| 亚州操B| 亚洲成人黄色电影| 成人AV中文解说水果派| 日本内射在线播放| 国产婬片一级A片AAA毛片AⅤ | 在线看毛片网站| 蜜桃传媒一区二区| 日韩一级电影在线观看| 九九综合网| 免费看A片视频| 大香蕉一级红色片青青河边草| 99在线播放| 影音先锋av无码| 4388亚洲最大| 俺来也俺去也www色| 牛牛Av| 综合中文字幕| 99re国产视频| 色婷婷欧美在线播放内射| 中文字幕无码视频| 日本中文字幕电影| 黄色电影中文字幕| 亚洲制服中文字幕| 国产成人精品国内自产拍免费看| 日韩精品在线观看视频| 久久亚洲国产| 日日干日日干| 中文字幕在线码| 免费观看日韩无码视频| 国产一区二区三区18| 草逼的视频| 欧美成人在线视频网站| 午夜福利电影AV| 国产精品AV一区| 九九草影院| 国产成人99久久亚洲综合精品 | 91操操| 99爱在线观看| 91毛片在线观看| 免费电影日本黄色| 欧美性爱动态| 亚洲福利视频电影精| 欧美精品综合| 中文乱伦视频| 黄色电影一区二区| 欧美级黑寡妇毛片app| 日韩人妻无码网站| 日本精品视频| 欧美一页| 92丨九色丨偷拍老熟女| 日皮视频在线免费观看| 国产成人777777精品综合| 国产欧美精品AAAAAA片| 男女操逼免费观看| 51成人网站免费| 草比视频| 操欧美美女| 久久婷香| 无码六区| 精品中文字幕视频| 六月天av| 四虎2025在线51| 青草福利| 69黄色视频| 日韩无码人妻一区二区| 六月丁香婷| 精品无码蜜桃| 亚洲熟妇在线观看| 免费欧美三级片| 国产男女性爱视频播放| 亚洲播播| 无码123| 91精品国产麻豆国产自产在线| 刘玥一区二区三区| 日本中文无码视频| 夜夜爽夜夜| YOUjiZZ欧美大全| 韩国三级AV| 日韩A片一级无码免费蜜桃| 亚洲日韩国产AV无码无码精品| 人人操人人干人人爽| 国产AA片| ww毛片| 国产精品久久久久久久牛牛| 色婷婷7777| 人妻无码精品久久人妻成人| 操操小骚逼| 丁香婷婷五月| 麻豆国产91在线播放| 午夜激情AV| 91精品久久久久久粉嫩| 久草国产精品| 午夜福利小视频| 亚洲高清视频免费| 激情白浆| 天天看高清无码| 国产成人综合亚洲| 欧美草比| 黄色视频在线观看亚洲一区二区三区免费 | 久草视频福利在线| 在桌下含她的花蒂和舌头H视频| 午夜成人无码视频| 97桃色| 91探花精品偷拍在线播放| 色就是色欧美成人网| 欧美一级a| 3级毛片| 无码人妻一区二区三区| 婷婷久久综合久色综| 欧美性69| 免费看成人片| 五月涩| 无码人妻精品一区二区三区蜜桃91| 亚洲中文字幕人妻| 大香蕉在8线| 99国产精品久久久久久久成人| 人人摸人人看人人草| 亚洲无码免费网站| 国产精品香蕉国产| 欧美熟妇擦BBBB擦BBBB| 五月婷婷俺也去| 九九天堂网| 久久爱91| 在线观看视频免费无码| 麻豆福利在线| 97人妻碰碰中文无码久热丝袜 | 操B网站| 9久热| 一级日韩| 大香蕉国产精品| 五月婷婷影院| 欧美熟女18| 18禁在线| 99在线免费观看| 日韩无码一级| 日本五十路| 欧美成人视频网站| 97人妻精品一区二区三区| www.狠狠| 久久99免费视频| 亚洲成人网站在线| 91亚洲精品视频| 51妺嘿嘿午夜福利| 无码人妻丰满熟妇区毛片视频| 加勒比无码高清| 无码AV一区二区| 欧美福利| 久久婷五月| 黄色一级免费| 黄色在线免费| 黄片久久| 亚洲免费在线观看视频| 婷婷日韩一区二区三区| 日韩视频一区二区三区| 熟妇导航| 亚洲精品影院| 69无码| 日韩A| 亚洲无码A片在线观看APP| 亚洲品久久久蜜| 操逼逼一区二区三区| 色图在线观看| 久久久久久久毛片| 黄网| 猫咪亚洲AV成人无码电影| 超碰91免费在线观看| 精品吃奶一区二区三区视频| 少妇搡BBBB搡BBB搡造水多,| 欧洲亚洲无码| 免费观看亚洲视频| 欧美高潮| 黄色A片免费观看| 麻豆91精品91久久久| 国产精品国产三级国产专区53| 色视频在线观看免费| 一区二区无码区| 操逼视频观看| 免费黄色视频观看| 午夜精品18视频国产17c| 波多野结衣AV在线播放| 免费a网站| 北条麻妃无码在线观看| 小日本91在线观看| 欧美屄视频| 中文亚洲精品字幕电影| 国内精品人妻无码久久久影院蜜桃 | 亚洲成人无码精品| 成人AV中文字幕| 玖玖99视频| 中文字幕一区二区三区四区五区六区| 伊人久久免费视频| 影音先锋成人资源站| 中文字幕毛片| 亚洲字幕| 亚洲无码黄色电影| 人人艹在线观看| 操逼视频91| 91精品丝袜久久久久久| 狠狠狠狠狠狠狠狠| 四虎成人无码| 国产一区二区三区在线视频| 亚洲无码99| 亚洲色五月| 91丨露脸丨熟女| 欧美18禁黄免费网站| h在线观看h| 欧美日韩一级黄色片| 国产老女人农村HD| 性爱视频久久| 91久久免费视频| 欧美成人三级在线| 欧美性爱免费网站| 91蜜桃视频| 无码免费视频| 又粗又硬又爽18级A片| 乱伦AV网| a免费在线| 国产在线观看91| 狠狠操在线观看| 人人妻人人操人人| 全国最大成人网站| 久久天堂| 午夜三级视频| 亚洲AV永久无码国产精品久久 | 无码视频在线| 久久亚洲Aⅴ成人无码国产丝袜| 日本一区二区三区视频在线观看 | 欧一美一色一伦一A片| 92丨九色丨偷拍老熟女| 特级西西WWW888| 成人黄色在线观看| 亚洲国产成人精品综合99| 国产精品一区一区三区| 日韩欧美亚洲一区二区三区| 色色色色五月| 久久成人小电影| 青青草操逼视频| 国产又爽又黄免费视频网站| 99九九99九九九99九他書對| 欧美成人性爱影院| 污网站18禁| 黄色免费在线观看| 亚洲精品97久久中文字幕| 最近中文字幕免费mv第一季歌词強上 | 丁香激情综合| 中文字幕第一页av| 欧美成人在线免费视频| 日韩黄频| 操人妻视频| 性爱精品视频| 骚BBBB槡BBB槡BBB| 91九色TS另类国产人妖| 又黄又爽无遮挡| 欧美性猛交XXXX乱大交蜜桃 | 91精品久久久久久久久久| 黄色成人网站在线观看免费| 青娱乐超碰在线| 亚洲一区二区黄色电影视频网站 | 亚洲爱爱视频| 亚洲综合激情五月久久| 欧美黄色a片| 国产精品视频色| 欧美a片在线| 日韩精品视频在线免费观看| 91无码人妻| AAA三级视频| 一级a一级a免费观看免免黄‘/| 国产无码AV在线| 免费毛片网| 91精东传媒果冻传媒| 成人无码高清在线观看| 男女福利视频| 国产在线毛片| 欧美性爱免费网站| 欧美三级在线| 久久久久久久久成人| 国产无码性爱| 大香蕉精品在线视频| 成人日韩| 18禁二区| 亚洲免费小电影| 中文字幕av第一页| 久草中文视频| 日皮做爱视频网站| 国产成人三级在线播放| 久久黄色精品视频| 日本高潮视频| 黄片无码| 色五月婷婷五月天激情| 免费91| 亚洲综合在线网| 天堂中文在线观看| 最新中文字幕在线播放| 熟女少妇一区二区| 国产麻豆三级片| 偷拍一区| 中文字幕在线欧美| 一区免费在线| 日韩黄色无码视频| 丁香五月激情婷婷| 亚洲色成人网站www永久四虎| 日韩免费a| 久久666| a在线观看| 国内自拍网站| 国产午夜视频在线| 亚洲天堂无码在线观看| 开心激情网站| 老熟女搡BBBB搡BBBB视频| 91色秘乱码一区二区| 亚洲AV高清无码| 日韩性爱一区二区| 成人视频A片| 色色色色五月天| 一级黄色片免费看| 日韩无码123区| 成人小视频在线| 国产一区二区视频在线观看| 亚洲视频中文字幕| 国产成人久久777777| 麻豆精品在线观看| 亚洲视频在线看| 四川搡BBBBB搡BBB| 国产无码性爱| 午夜无码精品一区二区三区99午 | 欧美成人在线视频网站| 日本无码中文字幕| 女人一区二区| 91久久人澡人妻人人做人人爽97 | 国产黄色精品视频| 国产黄色视频在线观看| 在线观看中文字幕无码| 国产无码操逼| 水果派AV解说| 2017天天射| 日本精品人妻| 一区二区三区四区五区在线| 一级无码A片| 污视频网站在线观看| 自拍偷拍在线视频| 国产精品伦理| 麻豆AV免费看| 图片区小说区区亚洲五月| 日本高清视频九区| 免费A级黄片| 免费看18禁| 日韩欧美在线观看| 男人天堂无码视频| 亚洲AV秘无码苍井空| 你懂的在线视频| 午夜福利在线播放| 99热电影| 欧美日韩狠狠操在线观看视频 | 欧美激情一区二区A片成人牛牛| 一本久久精品一区二区| 黄色一级大片| 日韩av综合| 色网站在线观看| 国产口爆| 无码人妻一区二区三一区免费n狂飙| 精品国产黄色| 亚洲视频一区| 亚洲黄色在线观看视频| 福利在线播放| 91视频爱爱| yw尤物视频| 大香蕉日逼| 国产又黄又大又粗| 大香蕉免费在线观看| 日本精品视频在线观看| 综合激情av| 国产精品久久久久精| 人妖黄片| 91成人区| 99热免费观看| 久久久久人妻| 免费操逼电影| 亚洲资源在线观看| 国产福利免费视频| 亚洲va欧洲va国产va不卡| 91香蕉视频| 91亚洲国产精品|