精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

【TVM 教程】向 Relay 中添加算子 原創

發布于 2025-8-6 10:32
瀏覽
0收藏

Apache TVM 是一個深度的深度學習編譯框架,適用于 CPU、GPU 和各種機器學習加速芯片。更多 TVM 中文文檔可訪問 →https://tvm.hyper.ai/

本文檔將以添加?cumulative product?算子的 PR(基于?cumulative sum?算子 PR)為例,介紹在 Relay 中注冊一個新的 TVM 算子所需的步驟。

注冊一個新的算子需要如下幾個步驟:

  1. 添加一個屬性節點,聲明在編譯時已知的固定參數
  2. 為算子編寫一個類型關系,以整合到 Relay 的類型系統中
  3. 使用 C++ 中的?RELAY_REGISTER_OP?宏,為編譯器注冊算子的數量、類型和其他提示
  4. 編寫算子的計算方式
  5. 用 Relay 注冊算子和 schedule
  6. 定義一個為算子產生調用節點的 C++ 函數,并為該函數注冊一個 Python API hook
  7. 將上述 Python API hook 放在一個更簡潔的接口中
  8. 為新的 Relay 算子編寫測試

1. 定義屬性節點

屬性是在編譯時已知的固定參數。卷積算子的步長和擴張可能屬于卷積算子屬性節點字段的恰當示例。

屬性應在文件夾?include/tvm/relay/attrs/?內的文件中定義。

最終我們要創建一個算子,它的接口可以在最終的 Python 接口中清晰可見:

def cumprod(data, axis=None, dtype=None, exclusive=None):
    """Numpy style cumprod op. Return the cumulative inclusive product of the elements along a given axis.
    參數
    ----------
    data : relay.Expr 類型
        算子的輸入數據。
    axis : int 類型,可選
        Axis along which the cumulative product is computed. The default (None) is to compute the cumprod over the flattened array.
    dtype : string 類型,可選
        Type of the returned array and of the accumulator in which the elements are multiplied.
        如果 dtype 沒有被指定, 那么它默認為 data 的 dtype。
    exclusive : bool 類型,可選
        If true will return exclusive product in which the first element is not included. In other terms, if true, the j-th output element would be the product of the first (j-1) elements. Otherwise, it would be the product of the first j elements. The product of zero elements will be 1.
    返回
    -------
    result : relay.Expr 類型
        如果 axis 不為空的話,結果的大小和形狀和 data 一樣。
        如果 axis 為空的話, 結果是一個一維數組。
    """

cumsum()?存在類似的接口。

因此,在?include/tvm/relay/attrs/transform.h?中定義屬性時,可以選擇算子的 axis、accumulation dtype 及 exclusivity 作為結構體的合適字段。

/*! 用在 cumsum 和 cumprod 算子中的簡單屬性 */
struct ScanopAttrs : public tvm::AttrsNode<ScanopAttrs> {
  Integer axis;
  DataType dtype;
  Bool exclusive = Bool(false);
  TVM_DECLARE_ATTRS(ScanopAttrs, "relay.attrs.ScanopAttrs") {
    TVM_ATTR_FIELD(axis).describe("The axis to operate over").set_default(NullValue<Integer>());
    TVM_ATTR_FIELD(dtype).describe("Output data type").set_default(NullValue<DataType>());
    TVM_ATTR_FIELD(exclusive)
        .describe("The first element is not included")
        .set_default(Bool(false));
  }
};

2. 編寫類型關系

為了提高注冊算子的靈活性,在 Relay 中表示類型時更突出,算子使用輸入和輸出類型之間的關系進行類型化。這些關系被表示為函數,它接收一個輸入類型和輸出類型的列表(這些類型中的任何一個都可能是不完整的),然后返回一個滿足關系的輸入和輸出類型的列表,包括可以在編譯時靜態確定的形狀信息?;旧?,一個算子的關系除了計算輸出類型外,還可以執行所有必要的類型化規則(即通過檢查輸入類型)。

在?src/relay/op/tensor/transform.cc?中可以找到 cumulative product 與 cumulative product 算子的類型關系。

TVM_REGISTER_NODE_TYPE(ScanopAttrs);
bool ScanopRel(const Array<Type>& types, int num_inputs, const Attrs& attrs, const TypeReporter& reporter) {
    // types: [data, output]
    ICHECK_EQ(types.size(), 2) << "Expects two types, one for the input and another for the output";
    const auto* data = types[0].as<TensorTypeNode>();
    if (data == nullptr) {
        ICHECK(types[0].as<IncompleteTypeNode>())
        << "Scanop: expect input type to be TensorType but get " << types[0];
        return false;
    }

    const auto* param = attrs.as<ScanopAttrs>();

    auto dtype = param->dtype;
    if (dtype.is_void()) {
        dtype = data->dtype;
    }

    if (param->axis.defined()) {
        reporter->Assign(types[1], TensorType(data->shape, dtype));
    } else {
        auto prod = data->shape[0];
        for (size_t i = 1; i < data->shape.size(); ++i) {
            prod = prod * data->shape[i];
        }
        reporter->Assign(types[1], TensorType({prod}, dtype));
    }

    return true;
}

3. 將參數數量和屬性與算子關聯起來

注冊新算子的名稱,并為其添加調用接口的注解。C++ 中的?RELAY_REGISTER_OP?宏允許開發者在 Relay 中指定一個算子的以下信息:

  • 參數數量
  • 位置參數的名稱和描述
  • 支持級別(1 表示內部固有的;更高的數字表示集成度低或外部支持的算子)
  • 算子的類型關系
  • 其他在優化算子時有用的注解

再次將其添加到?src/relay/op/tensor/transform.cc?中:

RELAY_REGISTER_OP("cumsum")
    .describe(
        R"doc(Return the cumulative sum of the elements along a given axis.)doc" TVM_ADD_FILELINE)
    .set_num_inputs(1)
    .add_argument("data", "Tensor", "The input tensor.")
    .set_support_level(3)
    .add_type_rel("Cumsum", ScanopRel)
    .set_attr<TOpPattern>("TOpPattern", kOpaque);

RELAY_REGISTER_OP("cumprod")
    .describe(
        R"doc(Return the cumulative product of the elements along a given axis.)doc" TVM_ADD_FILELINE)
    .set_num_inputs(1)
    .add_argument("data", "Tensor", "The input tensor.")
    .set_support_level(3)
    .add_type_rel("Cumprod", ScanopRel)
    .set_attr<TOpPattern>("TOpPattern", kOpaque);

在這種情況下,TOpPattern?是對編譯器關于算子執行的計算模式的提示,這對于融合算子可能很有用。kOpaque?提示 TVM 無需融合這個算子。

4. 定義算子的計算

為算子定義接口后,仍需定義如何執行 cumulative sum 和 cumulative product 的實際計算。

假設算子計算的實現方式,經過了多輪測試且表現良好。推薦查看?張量表達式教程、TVM 算子清單(topi)、python/tvm/topi/scan.py?中 cumulative sum 及 cumulative product 相關實現案例,以及?python/tvm/topi/cuda/scan.py?中的 GPU 版本。在 cumulative sum 及 cumulative product 算子中,可以直接用?TIR,張量表達式及 topi 降級后表示為 TIR。

5. 將計算(compute)和策略(strategy)與 Relay 關聯起來

實現計算函數后,需要將其與 Relay 算子粘合在一起。在 TVM 中,這意味著不僅要定義 computation,還要定義算子的 schedule。策略決定使用哪種 computation 及 schedule。例如,對于二維卷積,識別出這屬于一種深度卷積后,最終將其分配給一個更有效的 computation 和 schedule。

實際上除了在 CPU 和 GPU 的實現之間進行調度外,基本沒有類似需求。在?python/tvm/relay/op/strategy/generic.py?和?python/tvm/relay/op/strategy/cuda.py?中,我們添加了如下策略:

def wrap_compute_scanop(topi_compute):
    """Wrap scanop style topi compute"""

    def _compute_scanop(attrs, inputs, _):
        return [topi_compute(inputs[0], attrs.axis, attrs.dtype, attrs.exclusive)]

    return _compute_scanop

@override_native_generic_func("cumsum_strategy")
def cumsum_strategy(attrs, inputs, out_type, target):
    """cumsum 基本策略"""
    strategy = _op.OpStrategy()
    strategy.add_implementation(
        wrap_compute_scanop(topi.cumsum),
        wrap_topi_schedule(topi.generic.schedule_extern),
        name="cumsum.generic",
    )
    return strategy

@override_native_generic_func("cumprod_strategy")
def cumprod_strategy(attrs, inputs, out_type, target):
    """cumprod 基本策略"""
    strategy = _op.OpStrategy()
    strategy.add_implementation(
        wrap_compute_scanop(topi.cumprod),
        wrap_topi_schedule(topi.generic.schedule_extern),
        name="cumprod.generic",
    )
    return strategy

@cumsum_strategy.register(["cuda", "gpu"])
def cumsum_strategy_cuda(attrs, inputs, out_type, target):
    """cumsum cuda 策略"""
    strategy = _op.OpStrategy()
    strategy.add_implementation(
        wrap_compute_scanop(topi.cuda.cumsum),
        wrap_topi_schedule(topi.cuda.schedule_scan),
        name="cumsum.cuda",
    )
    return strategy

@cumprod_strategy.register(["cuda", "gpu"])
def cumprod_strategy_cuda(attrs, inputs, out_type, target):
    """cumprod cuda 策略"""
    strategy = _op.OpStrategy()
    strategy.add_implementation(
        wrap_compute_scanop(topi.cuda.cumprod),
        wrap_topi_schedule(topi.cuda.schedule_scan),
        name="cumprod.cuda",
    )
    return strategy

每個策略都定義了寫入的 compute 以及在?add_implementation()?中使用的 schedule。最后,將 strategy 和 compute 與python/tvm/relay/op/_transform.py?中定義的 Relay 算子關聯起來。

# cumsum
@_reg.register_compute("cumsum")
def compute_cumsum(attrs, inputs, output_type):
    """cumsum 的計算定義"""
    return [topi.cumsum(inputs[0], attrs.axis, attrs.dtype, attrs.exclusive)]

_reg.register_strategy("cumsum", strategy.cumsum_strategy)
_reg.register_shape_func("cumsum", False, elemwise_shape_func)

# cumprod
@_reg.register_compute("cumprod")
def compute_cumprod(attrs, inputs, output_type):
    """cumprod 的計算定義"""
    return [topi.cumprod(inputs[0], attrs.axis, attrs.dtype, attrs.exclusive)]

_reg.register_strategy("cumprod", strategy.cumprod_strategy)
_reg.register_shape_func("cumprod", False, elemwise_shape_func)

shape 函數用于確定 output shape,給定一個動態 shaped tensor。在這種情況下,TVM 的 output shape 與 input shape 保持一致。

6. 創建 Relay 調用節點并提供 Python Hook

現在已經有了一個可以運行的算子,接下來只需通過一個 Relay 調用節點(Relay Call Node)正確地調用即可。這一步需要簡單地編寫一個函數,接收算子的參數(作為 Relay 表達式),并向算子返回一個的調用節點(即應該被放在調用算子的 Relay AST 中的節點)。

目前不支持調用屬性和類型參數(最后兩個字段),所以只需使用?Op::Get?從算子注冊表中獲取算子信息,并將參數傳遞給調用節點(如下所示)。在?src/relay/op/tensor/transform.cc

Expr MakeCumsum(Expr data, Integer axis, DataType dtype, Bool exclusive) {
    auto attrs = make_object<ScanopAttrs>();
    attrs->dtype = dtype;
    attrs->axis = axis;
    attrs->exclusive = exclusive;
    static const Op& op = Op::Get("cumsum");
    return Call(op, {data}, Attrs(attrs), {});
}

TVM_REGISTER_GLOBAL("relay.op._make.cumsum").set_body_typed(MakeCumsum);

Expr MakeCumprod(Expr data, Integer axis, DataType dtype, Bool exclusive) {
    auto attrs = make_object<ScanopAttrs>();
    attrs->dtype = dtype;
    attrs->axis = axis;
    attrs->exclusive = exclusive;
    static const Op& op = Op::Get("cumprod");
    return Call(op, {data}, Attrs(attrs), {});
}

TVM_REGISTER_GLOBAL("relay.op._make.cumsum").set_body_typed(MakeCumprod);

其中?TVM_REGISTER_GLOBAL?通過?relay.op._make.cumsum(...)?和?relay.op._make.cumsum(...)?分別暴露(expose)Python 中的?MakeCumsum?和?MakeCumprod?函數。

7. 包含一個更簡潔的 Python API hook

通常 Relay 中約定俗成的是,通過?TVM_REGISTER_GLOBAL?導出的函數應該包裝在單獨的 Python 函數中,而不是直接在 Python 中調用。對于算子,我們在?python/tvm/relay/op/transform.py?中提供了更簡潔的接口:

def cumsum(data, axis=None, dtype=None, exclusive=None):
    return _make.cumsum(data, axis, dtype, exclusive)

def cumprod(data, axis=None, dtype=None, exclusive=None):
    return _make.cumprod(data, axis, dtype, exclusive)

注意,這些 Python wrapper 也可能為算子提供更簡潔的接口。例如?concat?算子被注冊為只接受一個算子(即一個帶有要連接的張量的元組),但是 Python wrapper 將張量作為參數,并在產生調用節點之前將它們組合成一個元組。

def concat(*args):
    """圍繞零軸連接輸入張量。

    參數
    ----------
    args: Tensor 列表

    返回
    -------
    tensor: 連接的張量。
    """
    tup = Tuple(list(args))
    return _make.concat(tup)

8. 編寫單元測試

更多用于 cumulative sum 和 cumulative product 算子的單元測試示例,請查看?tests/python/relay/test_op_level3.py。

其他主題

梯度算子

梯度算子對于在 Relay 中編寫可微分程序很重要。雖然 Relay 的 autodiff 算法可以得到優秀的語言結構的微分,但算子是不透明的。因為 Relay 無法查看它的實現,所以必須提供明確的微分規則。

Python 和 C++ 都可用于編寫梯度算子,這里重點介紹更為常用的 Python 實例。

在 Python 中添加梯度算子

Python 梯度算子集合可以在?python/tvm/relay/op/_tensor_grad.py?中找到 。本部分內容將詳細介紹兩個有代表性的例子:sigmoid?和?multiply。

@register_gradient("sigmoid")
def sigmoid_grad(orig, grad):
    """返回 [grad * sigmoid(x) * (1 - sigmoid(x))]."""
    return [grad * orig * (ones_like(orig) - orig)]

這里的輸入是原始算子?orig?以及梯度算子?grad,返回是一個列表,其中第 i 個索引的元素,是算子相對于算子第 i 個輸入的導數。通常,梯度算子將返回一個列表,其元素的個數和基礎算子(base operator)的輸入一樣多。

進一步分析這個定義之前,先回憶一下 sigmoid 函數的導數:?σ/?x=σ(x)(1?σ(x))。上面的定義看起來類似于數學定義,但有一個重要的補充:

術語?orig * (ones_like(orig) - orig)?直接匹配導數,因為這里的?orig?是 sigmoid 函數。除了要了解如何計算該函數的梯度之外,還要掌握該梯度與其他梯度組合的方法,即在整個程序中累積梯度。這就是?grad?的作用。在表達式?grad * orig * (ones_like(orig) - orig)中,乘以?grad?指定了到目前為止如何用梯度組合導數。

接下來請看?multiply的示例:

@register_gradient("multiply")
def multiply_grad(orig, grad):
    """返回 [grad * y, grad * x]"""
    x, y = orig.args
    return [collapse_sum_like(grad * y, x),
            collapse_sum_like(grad * x, y)]

在此示例中,返回列表中有兩個元素,因為?multiply?是二元運算符(binary operator)。如果 f(x,y) = xy,偏導數是 ?f / ?x = y 和 ?f / ?y = x。

與?sigmoid?相比,multiply?需要一個額外的步驟,因為?multiply?具有廣播語義(broadcasting semantics)。由于?grad?的 shape 可能與輸入 shape 不匹配,所以我們使用?collapse_sum_like?來獲取?grad * <var>?項的內容,并使其 shape 與做微分的輸入 shape 相匹配。

在 C++ 中添加梯度算子

在 C++ 中添加梯度算子的方法,與在 Python 中添加梯度算子類似,但注冊的接口略有不同。

首先,確保?src/relay/transforms/pattern_utils.h?被包含在內。它提供了用于在 Relay AST 中創建節點的輔助函數。定義梯度算子的方式與 Python 類似:

tvm::Array<Expr> MultiplyGrad(const Expr& orig_call, const Expr& output_grad) {
    const Call& call = orig_call.Downcast<Call>();
    return { CollapseSumLike(Multiply(output_grad, call.args[1]), call.args[0]),
             CollapseSumLike(Multiply(output_grad, call.args[0]), call.args[1]) };
}

注意,在 C++ 中不能使用與 Python 相同的運算符重載(operator overloading),而是需要向下轉換,因此實現更加冗長。即便如此,我們仍然可以輕易地驗證這個定義反映了 Python 中先前的例子。

要注冊梯度算子,這里無需使用 Python 修飾器,只需要在基礎算子注冊的末尾添加?set_attr?調用 “FPrimalGradient” 即可。

RELAY_REGISTER_OP("multiply")
    // ...
    // 設置其他屬性
    // ...
    .set_attr<FPrimalGradient>("FPrimalGradient", MultiplyGrad);

?著作權歸作者所有,如需轉載,請注明出處,否則將追究法律責任
收藏
回復
舉報
回復
相關推薦
av二区在线| 国产免费av一区| a级日韩大片| 欧美视频在线观看免费| 日本精品一区二区三区视频| 一级特黄aaa大片| 在线成人h网| 一本色道久久88亚洲综合88| 日韩不卡的av| 91av亚洲| 亚洲国产美国国产综合一区二区| 欧美日韩亚洲一区二区三区在线观看| 国产尤物在线观看| 亚洲深爱激情| 欧美成在线视频| 国产精品情侣呻吟对白视频| 最新精品在线| 欧美日韩国产a| 黄色影院一级片| а√资源新版在线天堂| 久久久久青草大香线综合精品| 91九色单男在线观看| 日日摸天天添天天添破| 午夜精品视频| 日韩亚洲欧美中文在线| www.久久av| 大陆精大陆国产国语精品| 欧洲在线/亚洲| 热99这里只有精品| 性欧美video高清bbw| 国产精品久久久久久久久搜平片 | 精品国内自产拍在线观看| 久久久久国产精品区片区无码| 日韩视频一二区| 欧美日本韩国一区| 中文字幕欧美人妻精品一区| av中文字幕在线观看第一页| 一区二区久久久久久| 亚洲一区二区在线免费观看| 欧美日韩影视| 91麻豆文化传媒在线观看| 操人视频欧美| www.99视频| 国产一区二区三区四区五区入口 | 黄色片视频在线免费观看| 国产羞羞视频在线播放| 亚洲欧美日韩成人高清在线一区| 亚洲ai欧洲av| 在线观看麻豆| 国产精品久久久久久久久久久免费看| 亚洲草草视频| 在线激情网站| 亚洲男人的天堂在线观看| 色呦呦网站入口| 黄色视屏免费在线观看| 亚洲欧洲一区二区三区| 一本一本久久a久久精品综合妖精| av在线电影观看| 国产精品视频麻豆| 台湾成人av| 久久黄色美女电影| 17c精品麻豆一区二区免费| 亚洲一区二区自拍偷拍| 精品国产99久久久久久| 亚洲免费观看高清在线观看| 久久亚洲国产成人精品无码区| 欧美天天影院| 一区二区三区中文在线观看| 欧美视频在线观看视频| 蜜桃视频在线观看免费视频| 图片区日韩欧美亚洲| 日韩精品视频久久| 欧美一区二区三区婷婷| 日韩欧美一级二级三级| 国产精品成人无码专区| 天堂一区二区三区四区| 在线性视频日韩欧美| 日本黄色免费片| 欧美日韩国产精品一区二区亚洲| 98精品国产高清在线xxxx天堂| 精品国产午夜福利| 久久精品国产网站| 国产日韩一区二区| 国产人成在线观看| 亚洲欧美国产三级| www.中文字幕在线| 四虎影视精品永久在线观看| 精品国产乱码久久久久久1区2区| 三级男人添奶爽爽爽视频| 欧美日韩高清| 久久久久这里只有精品| 日韩久久久久久久久久| 国产成人a级片| 区一区二区三区中文字幕| 欧美jizz18hd性欧美| 亚洲国产视频一区| 999精彩视频| 奇米777国产一区国产二区| 色777狠狠综合秋免鲁丝| 激情综合五月网| 日韩国产精品久久久久久亚洲| 亚洲综合小说区| 极品白浆推特女神在线观看| 一区二区三区av电影| 午夜视频在线瓜伦| 国产精品极品在线观看| www.xxxx欧美| 99久久久无码国产精品免费蜜柚| 国产精品一卡二卡| 亚洲欧美国产精品桃花| 理论片午夜视频在线观看| 欧美精品一二三| xxxx日本黄色| 国产精品亚洲欧美| 99在线视频免费观看| 99免在线观看免费视频高清| 欧美色视频日本高清在线观看| 三区视频在线观看| 精品久久久久久久久久久aⅴ| 久久久视频精品| 国产免费av观看| 欧美高清在线一区二区| 无罩大乳的熟妇正在播放| 日韩成人18| 色噜噜狠狠狠综合曰曰曰| 台湾佬中文在线| 97se狠狠狠综合亚洲狠狠| 草草草视频在线观看| 久久精品 人人爱| 一区三区二区视频| 色老头在线视频| 91网址在线看| 国产在线精品91| 国产精品22p| 欧美高清自拍一区| 国产乱码精品一区二区三区精东| 欧美韩国日本一区| 国产成人av影视| 九九热精品视频在线观看| 91精品国产色综合久久不卡98| 不卡av中文字幕| 一区二区三区久久久| 国产精品二区视频| 午夜精品久久| 国产伦精品一区二区三区高清| 日韩少妇视频| 精品福利一区二区三区| 九九九国产视频| 成人午夜私人影院| xxxx18hd亚洲hd捆绑| 巨人精品**| 欧洲成人在线视频| 丁香婷婷在线| 欧美老女人第四色| 久久国产波多野结衣| 国产麻豆精品在线| av片在线免费| 精品无人区一区二区| 777777777亚洲妇女| 欧美在线一卡| 欧美制服丝袜第一页| 很污很黄的网站| 国产91丝袜在线观看| 97干在线视频| 自拍视频一区| 国产精品一区久久| 超碰最新在线| 亚洲国产福利在线| 草莓视频18免费观看| 中文字幕av免费专区久久| 中文字幕资源在线观看| 欧美日韩国产欧| 久久婷婷人人澡人人喊人人爽| 欧美1级2级| 久久精品91久久久久久再现| 亚洲乱码在线观看| 欧美性猛交xxxx免费看| 黄色激情小视频| 国产999精品久久久久久| 久久精品国产精品亚洲色婷婷| 精品一二三区| dy888夜精品国产专区| 蜜桃视频在线观看播放| 在线播放日韩专区| 亚洲黄色片视频| 在线视频综合导航| 免费中文字幕视频| 国产目拍亚洲精品99久久精品| 国产在线视频三区| 久久国产高清| 青青草综合视频| 国产91一区| 99国产超薄丝袜足j在线观看| 日韩欧美看国产| 欧美日韩第一页| 福利在线午夜| 日韩电影免费观看中文字幕| 96日本xxxxxⅹxxx17| 精品国产精品自拍| 亚洲精品卡一卡二| 久久久亚洲欧洲日产国码αv| 两性午夜免费视频| 天堂成人免费av电影一区| 狠狠干视频网站| 亚洲免费专区| 99在线国产| 日本免费成人| 国产精品99导航| 黄频免费在线观看| 欧美超级乱淫片喷水| 国产小视频在线| 亚洲国产黄色片| 99在线观看免费| 精品视频一区二区三区免费| 好看的av在线| 亚洲成a人在线观看| 午夜爱爱毛片xxxx视频免费看| 久久无码av三级| 动漫av在线免费观看| 久久66热偷产精品| 欧美精品性生活| 丝袜诱惑制服诱惑色一区在线观看 | 午夜欧美2019年伦理| 日韩一区二区三区四区在线| 欧美激情一区二区三区蜜桃视频| 中文人妻一区二区三区| 成人三级伦理片| 精品国产乱码久久久久夜深人妻| 精品亚洲免费视频| 污网站免费在线| 奇米影视在线99精品| 无码人妻丰满熟妇区毛片| 在线亚洲成人| 91好吊色国产欧美日韩在线| 国内自拍视频一区二区三区| 91精品一区二区三区四区| 欧美gayvideo| 亚洲第一精品区| 99久久婷婷国产综合精品电影√| 亚洲国产精品一区二区第一页| 欧美日韩国产免费观看视频| 色一情一区二区三区四区| 精品成av人一区二区三区| 欧美亚洲精品日韩| 免费国产自久久久久三四区久久| 久久天天狠狠| 成人精品亚洲| 亚洲免费久久| 7777久久香蕉成人影院| 免费观看国产视频在线| 欧美人成在线| 欧美又粗又长又爽做受| 在线看片成人| 欧美日韩一区二区在线免费观看| 噜噜噜久久亚洲精品国产品小说| 久久婷婷国产91天堂综合精品| 美洲天堂一区二卡三卡四卡视频| www.日本一区| 国产精品1区2区| 欧美双性人妖o0| 国产亚洲成年网址在线观看| 国产wwwwxxxx| 亚洲夂夂婷婷色拍ww47| 国产黄色片免费看| 在线观看免费亚洲| 国产精品热久久| 日韩美女视频在线| 欧洲伦理片一区 二区 三区| 综合久久五月天| 在线中文字幕电影| 国产91精品视频在线观看| 韩国成人在线| 99久久精品免费看国产一区二区三区 | 亚洲精品免费观看| 国产l精品国产亚洲区久久| 日韩av午夜在线观看| 在线观看网站黄| 久久综合国产精品| 日本一级片免费| 五月激情综合色| 一级黄在线观看| 亚洲成人av片| 中文字幕在线视频区| 国产+人+亚洲| 国产综合色在线观看| 99精品国产一区二区| 久久93精品国产91久久综合| 91免费视频黄| 亚洲欧美不卡| 91性高潮久久久久久久| 91老司机福利 在线| 欧美风情第一页| 欧美性xxxx极品hd欧美风情| 国产男男gay体育生网站| 日韩经典中文字幕在线观看| 欧美被日视频| 国产成人a亚洲精品| 日韩欧美激情电影| 日韩国产精品一区二区三区| 国内自拍一区| 九九九九九国产| 91麻豆国产在线观看| 免费在线观看黄视频| 欧美图片一区二区三区| 天堂av2024| 欧美国产日韩一区二区| 国产69精品久久| 免费久久99精品国产自| 欧美性久久久| 自拍一级黄色片| 中文字幕成人av| 国产情侣自拍av| 欧美mv和日韩mv国产网站| 91在线视频| 日韩美女视频中文字幕| 成午夜精品一区二区三区软件| 一区视频二区视频| 免费高清在线一区| 法国空姐电影在线观看| 婷婷亚洲久悠悠色悠在线播放| 国产高潮在线观看| 色婷婷成人综合| 电影久久久久久| 欧美精品亚洲精品| 国产亚洲永久域名| 免费a在线观看播放| 亚洲高清三级视频| 开心激情综合网| 色综合久久久888| 亚洲大奶少妇| 欧美一级中文字幕| 国产一区二区三区免费在线观看| 国产精品无码无卡无需播放器| 色激情天天射综合网| 日本中文字幕电影在线观看| 97精品伊人久久久大香线蕉| 狠狠一区二区三区| 国内精品视频一区二区三区| 国产**成人网毛片九色 | 91精品国产91久久久久游泳池 | 欧美精品生活片| 国产一区二区三区黄网站| 伊人久久大香线蕉av一区| 捆绑调教美女网站视频一区| 亚洲一级理论片| 在线成人午夜影院| www免费视频观看在线| 147欧美人体大胆444| 欧美三级免费| 老司机免费视频| 高潮白浆女日韩av免费看| 免费在线国产| 国产精品久久在线观看| 国产精品久久久久久久久妇女| 182午夜在线观看| 一区二区三区丝袜| 蜜臀av中文字幕| 欧美一级电影免费在线观看| 国产日产精品一区二区三区四区的观看方式 | 国产在线精品免费| 欧美极品aaaaabbbbb| 日韩av最新在线| 日韩在线观看不卡| 欧美日韩在线免费观看视频| 国产电影一区在线| 精品美女久久久久| 一区二区三区在线播放欧美| 国产激情精品一区二区三区| 蜜臀精品一区二区| 26uuu精品一区二区在线观看| 真实新婚偷拍xxxxx| 久99久在线视频| 亚洲大片精品免费| 久久久久久久久久久久91| 亚洲日本在线看| 午夜性色福利影院| 国产精品在线看| 在线播放日韩| 萌白酱视频在线| 亚洲成人精品av| 成人在线高清| 成品人视频ww入口| 国产精品电影一区二区| 懂色av蜜臀av粉嫩av分享吧| 日韩av观看网址| 欧美1区3d| 91成人破解版| 日韩西西人体444www| 欧美性suv| 欧美日韩中文字幕在线播放| 久久一区二区三区四区| 国产一区二区麻豆| 91超碰中文字幕久久精品| 色综合久久一区二区三区| 国产老熟女伦老熟妇露脸| 欧美高清精品3d| 竹内纱里奈兽皇系列在线观看| 欧美日韩一级在线 | 日韩a级片在线观看| 亚洲欧美激情另类校园|