<strike id="ca4is"><em id="ca4is"></em></strike>
  • <sup id="ca4is"></sup>
    • <s id="ca4is"><em id="ca4is"></em></s>
      <option id="ca4is"><cite id="ca4is"></cite></option>
    • 二維碼
      企資網

      掃一掃關注

      當前位置: 首頁 » 企資快報 » 服務 » 正文

      機器學習編譯器和優化器的通俗介紹

      放大字體  縮小字體 發布日期:2021-09-12 02:09:42    作者:媒體小英    瀏覽次數:21
      導讀

      更多互聯網精彩資訊、工作效率提升關注【飛魚在浪嶼】(日更新)在許多機器學習用例中,尤其是在邊緣節點運行 ML 模型時,模型的成功仍然取決于其運行的硬件,這使得在生產中使用 ML 模型的人員了解他們的模型如何編

      更多互聯網精彩資訊、工作效率提升關注【飛魚在浪嶼】(日更新)


      在許多機器學習用例中,尤其是在邊緣節點運行 ML 模型時,模型的成功仍然取決于其運行的硬件,這使得在生產中使用 ML 模型的人員了解他們的模型如何編譯和優化以運行非常重要在不同的硬件加速器上。

      理想情況下,編譯器是不可見的,一切都會“正常工作”。然而,我們距離這一點還有很多年。隨著越來越多的公司希望將 ML 帶到邊緣,并且越來越多的硬件正在為 ML 模型開發,越來越多的編譯器正在開發以彌合 ML 模型和硬件加速器之間的差距——MLIR、TVM、XLA、 PyTorch Glow、cuDNN 等。 根據 PyTorch 的創建者 Soumith Chintala 的說法,隨著 ML 采用的成熟,公司將擇優選擇誰可以更好地編譯和優化他們的模型。

      了解編譯器的工作原理可以幫助您選擇正確的編譯器,將模型運行在您選擇的硬件上,并診斷性能問題并加速您的模型。

      ML 的下一個競賽是編譯器(Soumith Chintala,Venture Beat 2020)

      這篇文章(希望如此)是對 ML 編譯器的介紹。它始于邊緣計算,編譯器從系統工程師的領域進入了普通 ML 從業者的領域。

      下一部分是關于在邊緣部署 ML 模型的兩個主要問題:兼容性和性能、編譯器如何解決這些問題以及編譯器如何工作。最后提供了一些關于如何使用幾行代碼顯著加快 ML 模型的資源。


      目錄
      …… 1. 云計算與邊緣計算
      …… 2.編譯:兼容性
      .... 3. 優化:性能
      …… 4. 如何優化您的 ML 模型
      …… 5. 手工設計與基于機器學習的編譯器
      …… 6. 不同類型的編譯器
      …… 7. 編譯器的下一步是什么


      1. 云計算與邊緣計算

      想象一下,您已經訓練了一個令人難以置信的 ML 模型,其準確性超出了您的期望。您很高興能夠部署此模型。

      最簡單的方法是將您的模型打包并通過托管云服務(例如 AWS 或 GCP)進行部署,云服務在使公司輕松將 ML 模型投入生產方面做得非常出色。

      但是,云部署有很多缺點。首先是成本。ML 模型可能是計算密集型的,而且計算成本很高。甚至在 2018 年,像 Pinterest、Infor、Intuit 等大公司每年已經在云賬單上花費數億美元 。對于中小型公司來說,這個數字每年可能在5 萬到200 萬美元之間。云服務的錯誤可能導致初創公司破產 。

      隨著 AWS 使用量的激增,公司的云賬單

      隨著云計算費用的攀升,越來越多的公司正在尋找將其計算推向消費設備(邊緣設備)的方法。在邊緣完成的計算越多,對云的需求就越少,他們為服務器支付的費用也就越少。

      除了控制成本外,還有許多特性使邊緣計算具有吸引力。首先是它允許應用程序在云計算無法運行的地方運行。當模型位于公共云上時,它們依賴穩定的 Internet 連接將數據發送到云并返回。邊緣計算允許模型在沒有 Internet 連接或連接不可靠的情況下工作,例如在農村地區或發展中國家。

      其次,當模型已經在消費者的設備上時,可以少擔心網絡延遲。需要通過網絡傳輸數據(將數據發送到云上的模型進行預測,然后將預測發送回用戶)可能會使某些用例變得不可能。在許多情況下,網絡延遲是比推理延遲更大的瓶頸。例如,可能能夠將 ResNet50 的推理延遲從 30 毫秒減少到 20 毫秒,但網絡延遲可能高達數秒,具體取決于所在的位置。下圖顯示了從佛蒙特州到世界上各個服務器中心的網絡延遲。

      Ping 結果從佛蒙特州到世界各地的服務器。ping.psa.fun 的結果

      在處理敏感的用戶數據時,將模型置于邊緣也很有吸引力。云上的機器學習意味著系統可能必須通過網絡發送用戶數據,使其容易被攔截。云計算通常還意味著將多個用戶的數據存儲在同一個地方,這意味著數據泄露會影響到很多人。據《安全》雜志 2020 年報道,近 80% 的公司在過去 18 個月中經歷了云數據泄露。邊緣計算使遵守有關如何傳輸或存儲用戶數據的法規(例如 GDPR)變得更加容易。


      2.編譯:兼容性

      由于邊緣計算相對于云計算具有許多優勢,因此公司正在競相開發針對不同 ML 用例進行優化的邊緣設備。包括谷歌、蘋果、特斯拉在內的老牌公司都宣布了自己制造芯片的計劃。與此同時,機器學習硬件初創公司已經籌集了數十億美元來開發更好的人工智能芯片。

      人工智能硬件初創公司的一個子集(Crunchbase 的融資信息)

      有了這么多用于運行機器學習模型的硬件新產品,一個問題就出現了:我們如何使用任意框架構建的模型在任意硬件上運行?

      對于在硬件上運行的框架,它必須得到硬件供應商的支持。例如,盡管 TPU 于 2018 年 2 月公開發布,但直到 2020 年 9 月,PyTorch才支持 TPU 。在此之前,如果想使用 TPU,則必須使用 TensorFlow 或 JAX。

      在某種類型的硬件(平臺)上為框架提供支持是耗時且工程密集的。從 ML 工作負載映射到硬件需要了解并能夠利用硬件的基礎設施。然而,一個基本的挑戰是不同的硬件類型具有不同的內存布局和計算原語。.

      例如,CPU 的計算原語曾經是一個數字(標量),GPU 的計算原語曾經是一個一維向量,而 TPU 的計算原語是一個二維向量(張量)。然而,如今許多 CPU 具有向量指令,而一些 GPU 具有二維張量核心。與二維向量相比,一維向量對一批 256 張圖像 x 3 通道 x 224 W x 224 H 執行卷積算子將有很大不同。同時需要考慮不同的 L1、L2 和 L3 布局和緩沖區大小以有效地使用它們。

      計算不同硬件后端的原語和內存布局

      框架開發者往往只專注于為少數服務器級硬件(例如 GPU)提供支持,而硬件供應商則傾向于為范圍狹窄的框架提供自己的內核庫(例如 Intel 的 OpenVino 只支持Caffe、TensorFlow、MXNet、Kaldi 和 ONNX。NVIDIA 有 CUDA 和 cuDNN)。將 ML 模型部署到新硬件(例如手機、嵌入式設備、FPGA 和 ASIC)需要大量的手動工作。

      如何在任意硬件后端運行使用任意框架構建的模型。


      中臺

      如果創建一個中臺來橋接框架和平臺,而不是針對每種新的硬件類型和設備都針對新的編譯器和庫呢?框架開發者將不再需要支持每一種類型的硬件,只需要將他們的框架代碼翻譯成這個中臺服務。那么硬件供應商可以支持一個中間框架而不是支持多個嗎?

      這種類型的“中間人”稱為中間表示(IR)。IR 是編譯器工作方式的核心。根據模型的原始代碼,編譯器在生成硬件原生代碼以在特定平臺上運行模型之前生成一系列高級和低級中間表示。

      為了從 IR 生成機器原生代碼,編譯器通常利用代碼生成器,也稱為代碼生成器。ML 編譯器使用的最流行的代碼生成器是LLVM,由 Vikram Adve 和 Chris Lattner開發。TensorFlow XLA、NVIDIA CUDA 編譯器 (NVCC)、MLIR(用于構建其他編譯器的元編譯器)和 TVM 都使用 LLVM。

      此過程也稱為“降低”,因為將高級框架代碼“降低”為低級硬件本機代碼。這不是“翻譯”,因為它們之間沒有一對一的映射。

      高級 IR 通常是 ML 模型的計算圖。對于熟悉 TensorFlow 的人來說,這里的計算圖類似于您在 TensorFlow 1.0 中遇到的計算圖,之前 TensorFlow 切換到 Eager Execution。在 TensorFlow 1.0 中,TensorFlow 在運行模型之前首先構建了模型的計算圖。此計算圖允許 TensorFlow 了解模型以優化其運行時。

      高級 IR 通常與硬件無關(不關心它將在什么硬件上運行),而低級 IR 通常與框架無關(不關心模型是用什么框架構建的)。

      高級 IR 和低級 IR


      3.優化:性能

      在“降低”代碼以將模型運行到您選擇的硬件中后,可能會遇到的一個問題是性能。Codegen 非常擅長將 IR 降低為機器代碼,但根據目標硬件后端,生成的機器代碼可能無法正常執行。生成的代碼可能不會利用數據局部性和硬件緩存,或者可能不會利用可以加速代碼的高級功能,例如向量或并行操作。

      典型的 ML 工作流由許多框架和庫組成。例如,可以使用 pandas/dask/ray 從數據中提取特征。可以使用 NumPy 來執行矢量化。可以使用 LightGBM 之類的樹模型來生成特征,然后使用使用各種框架(如 sklearn、TensorFlow 或 Transformer)構建的模型集合進行預測。

      盡管這些框架中的個別功能可能會被優化,但跨框架幾乎沒有優化。在這些函數之間移動數據以進行計算的幼稚方式可能會導致整個工作流程的速度下降一個數量級。斯坦福 DAWN 實驗室的研究人員進行的一項研究發現,與手動優化代碼相比,使用 NumPy、Pandas 和 TensorFlow 的典型機器學習工作負載在一個線程中的運行速度要慢 23 倍(Palkar 等人,'18)。

      在生產中通常發生的是數據科學家/機器學習工程師 pip 安裝他們工作所需的包。事情似乎在開發環境中運行良好,因此他們將模型部署到生產環境中。當他們在生產中遇到性能問題時,他們的公司通常會聘請優化工程師來為他們運行的硬件優化他們的模型。

      Cruise 優化工程師的工作描述

      Mythic 優化工程師的職位描述

      優化工程師很難找到,而且招聘成本很高,因為他們需要同時具備 ML 和硬件架構方面的專業知識。優化編譯器(也優化代碼的編譯器)是一種替代解決方案,因為它們可以自動化優化模型的過程。在將 ML 模型代碼降級為機器代碼的過程中,編譯器可以查看您的 ML 模型的計算圖及其包含的運算符——卷積、循環、交叉熵——并找到一種方法來加速它。


      總結一下目前為止所涵蓋的內容,編譯器橋接了 ML 模型和它們運行的硬件。優化編譯器由兩個組件組成:降低和優化。這兩個組件不一定是分開的。優化可以發生在從高級 IR 到低級 IR 的所有階段。

    • 降低:編譯器為您的模型生成硬件本機代碼,以便您的模型可以在某些硬件上運行。
    • 優化:編譯器優化您的模型以在該硬件上運行。

      4. 如何優化您的 ML 模型

      有兩種方法可以優化您的 ML 模型:本地和全局。本地是當您優化模型的一個運算符或一組運算符時。全局是端到端地優化整個計算圖時。

      已知有標準的局部優化技術可以加速您的模型,其中大多數技術使事物并行運行或減少芯片上的內存訪問。以下是四種常用技術。

    • 向量化:給定一個循環或嵌套循環,而不是一次執行一項,而是使用硬件原語對內存中連續的多個元素進行操作。
    • 并行化:給定一個輸入數組(或 n 維數組),將其劃分為不同的、獨立的工作塊,并分別對每個塊進行操作。
    • 循環平鋪:更改循環中的數據訪問順序以利用硬件的內存布局和緩存。這種優化依賴于硬件。CPU 上的良好訪問模式不是 GPU 上的良好訪問模式。請參閱下面由Colfax Research 提供的可視化。
    • 運算符融合:將多個運算符融合為一個以避免冗余內存訪問。例如,對同一個數組的兩個操作需要對該數組進行兩次循環。在融合的情況下,它只是一個循環。請參閱下面Matthias Boehm的示例。

      Colfax Research 的循環平鋪可視化。

      Matthias Boehm 的算子融合示例

      根據 Weld(另一個編譯器)的創建者 Shoumik Palkar 的說法,這些標準的局部優化技術有望提高約 3 倍的速度。當然,這個估計是高度依賴于上下文的。

      要獲得更大的加速,需要利用計算圖的更高級別結構。例如,給定一個卷積神經網絡,計算圖可以垂直或水平融合,以減少內存訪問并加速模型。請參閱下面由 NVIDIA 的TensorRT 團隊制作的可視化。

      卷積神經網絡計算圖的縱向和橫向融合


      5. 手工設計與基于機器學習的編譯器

      手工設計的規則

      正如上一節通過卷積神經網絡的垂直和水平融合所暗示的那樣,有許多可能的方法來執行給定的計算圖。例如,給定 3 個運算符 A、B 和 C,可以將 A 與 B 融合,將 B 與 C 融合,或者將 A、B 和 C 融合在一起。

      傳統上,框架和硬件供應商會聘請優化工程師,他們根據自己的經驗提出如何最好地執行模型計算圖的啟發式方法。例如,NVIDIA 可能有一個工程師或一個工程師團隊專門研究如何讓 ResNet-50 在他們的 DGX A100 服務器上真正快速運行。(這也是為什么你不應該過多地閱讀MLPerf 的結果。在某種硬件上運行得非常快的流行模型并不意味著任意模型在該硬件上運行得非常快。可能只是這個模型是過度優化)。

      手工設計的規則有幾個缺點。首先是它們不是最佳的。不能保證工程師提出的啟發式方法是最好的解決方案。

      其次,它們是非自適應的。在新框架或新硬件架構上重復這個過程需要大量的努力。

      由于模型優化取決于構成其計算圖的一組運算符,因此這很復雜。優化卷積神經網絡不同于優化循環神經網絡,也不同于優化transformer。NVIDIA 和 Google 專注于在其硬件上優化 ResNet 和 BERT 等流行模型。但是,作為 ML 研究人員,如果想出一個新的模型架構呢?在被硬件供應商采用和優化之前,您可能需要自己對其進行優化以證明它的速度很快。


      使用機器學習加速機器學習模型

      目標是在所有可能的方法中找到執行計算圖的最快方法。如果嘗試所有可能的方法,記錄他們需要運行的時間,然后選擇最好的方法會怎樣?

      問題是有太多可能的方法(路徑)來探索(組合!),并且嘗試所有方法都被證明是不可行的。如果使用 ML 來:

      縮小搜索空間,因此不必嘗試那么多路徑。預測一條路徑需要多長時間,這樣我們就不必等待整個計算圖完成執行。

      估計通過整個計算圖的路徑運行所需的時間非常困難,因為它需要對該圖進行大量假設。目前的技術可能只關注圖表的一小部分。

      如果您在 GPU 上使用 PyTorch,您可能已經看到torch.backends.cudnn.benchmark=True. 當此設置為 True 時,將啟用cuDNN 自動調諧。cuDNN 自動調諧搜索一組預先確定的選項以執行卷積算子,然后選擇最快的方式。如果每次迭代都運行相同的 convnet 形狀,cuDNN 自動調整會很有幫助。第一次運行卷積算子時會很慢,因為 cuDNN 自動調諧需要時間來運行搜索。但是在后續運行中,cuDNN 將使用自動調整的緩存結果來選擇最快的配置。

      cuDNN autotune盡管有效,但僅適用于卷積算子,而且 AFAIK 僅適用于 PyTorch 和 MXNet。一個更通用的解決方案是autoTVM,它是開源編譯器堆棧 TVM 的一部分。autoTVM使用子圖而不僅僅是運算符,因此它使用的搜索空間要復雜得多。autoTVM 的工作方式非常復雜,但要點如下:

        它首先將計算圖分解為子圖。它預測每個子圖有多大。它分配時間為每個子圖搜索最佳路徑。它縫合了將每個子圖運行在一起以執行整個圖的最佳方式。

      autoTVM 測量運行每條路徑所需的實際時間,這為其提供了地面實況數據以訓練成本模型以預測未來路徑將花費多長時間。這種方法的優點在于,因為模型是使用運行時生成的數據進行訓練的,所以它可以適應它運行的任何類型的硬件。缺點是成本模型需要更多時間才能開始改進。

      與 cuDNN 在 NVIDIA TITAN X 上的 ResNet-50 相比,
      基于 ML 的 TVM 提供的加速。基于 ML 的 TVM 需要約 70 次試驗才能勝過 cuDNN。

      TVM 的成本模型如何運作

      像 TVM 這樣的編譯器是自適應的、靈活的,當您想嘗試新硬件時尤其有用。一個例子是蘋果在 2020 年 11 月發布了他們的 M1 芯片。M1是基于ARM的片上系統,ARM架構或多或少都比較好理解。但是,M1 的 ARM 實現仍然有很多新穎的組件,需要進行大量優化才能使各種 ML 模型在其上快速運行。發布一個月后,OctoML 的人們表明,autoTVM 所做的優化比 Apple 的 Core ML 團隊手工設計的優化快了近 30%. 當然,隨著 M1 的成熟和手工優化變得密集,自動優化將很難擊敗手工優化。但系統工程師可以利用 autoTVM 等工具來加速優化。

      雖然自動調整的結果令人印象深刻,但它們有一個問題:TVM 可能很慢。遍歷所有可能的路徑并找到最優化的路徑。對于復雜的 ML 模型,此過程可能需要數小時甚至數天。但是,這是一次性操作,您的優化搜索結果可以緩存并用于優化現有模型并為未來的調整會話提供一個起點。您為一個硬件后端優化一次模型,然后在同一后端的多個設備上運行它。當您有一個準備好用于生產的模型并且目標硬件可以運行推理時,這種優化是理想的。


      6. 不同類型的編譯器

      最廣泛使用的編譯器類型是由主要框架和硬件供應商開發的針對特定框架和硬件組合的特定領域編譯器。不出所料,最受歡迎的產品是由最大的供應商開發的。

    • NVCC(NVIDIA CUDA 編譯器):僅適用于 CUDA。閉源。
    • XLA(Accelerated Linear Algebra,Google):最初是為了加速 TensorFlow 模型,但已被 JAX 采用。作為 TensorFlow 存儲庫的一部分開源。
    • PyTorch Glow (Facebook):PyTorch 已經采用 XLA 在 TPU 上啟用 PyTorch,但對于其他硬件,它依賴于 PyTorch Glow。作為 PyTorch 存儲庫的一部分開源。

      一般而言,第三方編譯器非常雄心勃勃(例如,您必須非常自信地認為您可以比 NVIDIA 更好地針對 GPU 進行優化)。但是第三方編譯器很重要,因為它們有助于降低新框架、新一代硬件、新模型的性能開銷,讓小玩家有機會與擁有自己的編譯器針對現有產品進行大量調整的老牌玩家競爭。

      最好的第三方編譯器是 Apache TVM,它適用于各種框架(包括 TensorFlow、MXNet、PyTorch、Keras、CNTK)和各種硬件后端(包括 CPU、服務器 GPU、ARM、x86、移動 GPU 和基于 FPGA 的加速器)。

      另一個令人興奮的項目是MLIR,它最初也是由 Chris Lattner(LLVM 的創建者)在 Google發起的。但是,它現在屬于 LLVM 組織。MLIR 并不是一個真正的編譯器,而是一個元編譯器,構建自己的編譯器的基礎設施。MLIR 可以運行多個 IR,包括 TVM 的 IR,以及 LLVM IR 和 TensorFlow 圖。


      WebAssembly (WASM)

      WASM 是過去幾年中最令人興奮的技術趨勢之一。它性能卓越、易于使用,并且擁有一個像野火一樣不斷發展的生態系統。截至 2021 年 9 月,全球 93% 的設備都支持它。

      我們一直在討論編譯器如何為模型生成機器原生代碼以在某些硬件后端上運行。如果我們想生成一些可以在任何硬件后端上運行的代碼怎么辦?

      使用了舊瀏覽器。如果可以在瀏覽器中運行模型,就可以在任何支持瀏覽器的設備上運行您的模型:Macbook、Chromebook、iPhone、Android 手機等。無需關心這些設備使用什么芯片。如果蘋果決定從英特爾芯片轉向 ARM 芯片,那不是你的問題!

      WebAssembly 是一個開放標準,允許瀏覽器中運行可執行程序。在 sklearn、PyTorch、TensorFlow 或您使用的任何框架中構建模型后,您以將模型編譯為 WASM,而不是編譯模型以在特定硬件上運行。你會得到一個可執行文件,你可以只用 Javascript 來使用它。

      WASM 的主要缺點是因為 WASM 在瀏覽器中運行,所以速度很慢。盡管 WASM 已經比 Javascript 快得多,但與在設備(例如 iOS 或 Android 應用程序)上本地運行代碼相比,它仍然很慢。Jangda 等人的一項研究。顯示編譯為 WASM 的應用程序運行速度比原生應用程序平均慢 45%(在 Firefox 上)到 55%(在 Chrome 上)。

      有許多編譯器可以幫助您編譯為 WASM。最流行的可能是 Emscripten(它也使用 LLVM 代碼生成器),但它只能從 C 和 C++ 編譯成 WASM。scailable應該可以從 scikit-learn 模型轉換為 WASM,但它在 GitHub 上只有 13 顆星,而且在過去 3 個月內沒有更新(它甚至還在維護嗎?)。TVM 是我所知道的唯一一個從ML 模型編譯為 WASM 的活動編譯器。

      提示:如果決定試用 TVM,請使用他們的非官方 conda/pip 命令進行快速安裝(https://tlcpack.ai/)。如果需要幫助,他們只有一個 Discord 服務器!

      https://discord.com/invite/8jNs8MkayG


      7. 編譯器的下一步是什么

      考慮模型如何在不同的硬件后端上運行,這樣可以提高它們的性能。Austin Huang在我們的MLOps Discord上發帖稱,他經常通過使用簡單的現成工具(量化工具、Torchscript、ONNX、TVM)而無需太多努力就可以實現 2倍的加速。

      這里有一個很棒的技巧列表,可以在 GPU 上加速 PyTorch 模型,甚至無需使用編譯器。

      當模型準備好部署時,有必要嘗試不同的編譯器,看看哪一個能給您帶來最佳的性能提升。可以并行運行這些實驗。一個推理請求的小幅提升可以累積成數百萬或數十億推理請求的大回報。

      盡管用于機器學習的編譯器已經取得了巨大的進步,但在我們完全從一般 ML 從業者那里抽象出編譯器之前,還有很多工作要做。想想像 GCC 這樣的傳統編譯器。您使用 C 或 C++ 編寫代碼,GCC 會自動將您的代碼降低為機器代碼。大多數 C 程序員甚至不關心 GCC 生成什么中間表示。

      未來,機器學習編譯器可以采用同樣的方式。您使用框架以計算圖的形式創建 ML 模型,您的 ML 編譯器可以為您運行的任何硬件生成機器原生代碼。您甚至無需擔心中間表示。

      TVM 之類的工具是使未來成為可能的步驟。

    •  
      (文/媒體小英)
      免責聲明
      本文僅代表作發布者:媒體小英個人觀點,本站未對其內容進行核實,請讀者僅做參考,如若文中涉及有違公德、觸犯法律的內容,一經發現,立即刪除,需自行承擔相應責任。涉及到版權或其他問題,請及時聯系我們刪除處理郵件:weilaitui@qq.com。
       

      Copyright ? 2016 - 2025 - 企資網 48903.COM All Rights Reserved 粵公網安備 44030702000589號

      粵ICP備16078936號

      微信

      關注
      微信

      微信二維碼

      WAP二維碼

      客服

      聯系
      客服

      聯系客服:

      在線QQ: 303377504

      客服電話: 020-82301567

      E_mail郵箱: weilaitui@qq.com

      微信公眾號: weishitui

      客服001 客服002 客服003

      工作時間:

      周一至周五: 09:00 - 18:00

      反饋

      用戶
      反饋

      午夜久久久久久网站,99久久www免费,欧美日本日韩aⅴ在线视频,东京干手机福利视频
        <strike id="ca4is"><em id="ca4is"></em></strike>
      • <sup id="ca4is"></sup>
        • <s id="ca4is"><em id="ca4is"></em></s>
          <option id="ca4is"><cite id="ca4is"></cite></option>
        • 主站蜘蛛池模板: 无遮挡色视频真人免费| 美女被免费视频网站a国产| 欧美又粗又大又硬又长又爽视频| 国自产拍在线天天更新91| 人人澡人人澡人人看添av| 一个人看的视频www在线| 福利所第一导航| 女欢女爱第一季| 人妻少妇精品视频一区二区三区 | 8888四色奇米在线观看不卡| 波多野结衣在线观看一区 | 一本色道久久综合亚洲精品| 精品少妇人妻AV免费久久洗澡| 成年人网站免费观看| 初尝黑人巨砲波多野结衣| jzzjzz免费观看大片免费| 特级毛片www| 国产精品自在线观看剧情| 亚洲偷自精品三十六区| 国产精品久久自在自线观看| 日本黄色影院在线观看| 国产v亚洲v天堂无码| 一本久久精品一区二区| 特级毛片爽www免费版| 国产精品日韩欧美一区二区三区 | 中文字幕av无码不卡| 精品一区二区三区无卡乱码| 天天av天天翘天天综合网| 亚洲日本黄色片| 91影院在线观看| 成年女人免费播放影院| 俺来也俺去啦久久综合网| 720lu国内自拍视频在线| 日韩视频在线播放| 啦啦啦www播放日本观看| bl道具play珠串震珠强迫| 欧美性bbwbbw| 国产二区在线播放| 一个人hd高清在线观看| 欧美特黄三级在线观看| 国产强伦姧在线观看|