国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

繞開算力限制,如何用單GPU微調 LLM?這是一份「梯度累積」算法教程

人工智能 新聞
讓算力資源用到極致,是每一位開發者的必修課。

自從大模型變成熱門趨勢之后,GPU 就成了緊俏的物資。很多企業的儲備都不一定充足,更不用說個人開發者了。有沒有什么方法可以更高效的利用算力訓練模型?

在最近的一篇博客,Sebastian Raschka 介紹了「梯度累積」的方法,能夠在 GPU 內存受限時使用更大 batch size 訓練模型,繞開硬件限制。

圖片

在此之前,Sebastian Raschka 也分享過一篇運用多 GPU 訓練策略加速大型語言模型微調的文章,包括模型或 tensor sharding 等機制,這些機制將模型權重和計算分布在不同的設備上,以解決 GPU 的內存限制。

微調 BLOOM 模型進行分類

假設我們有興趣采用近期預訓練的大型語言模型來處理文本分類等下游任務。那么,我們可能會選擇使用 GPT-3 的開源替代品 BLOOM 模型,特別是「僅有」 5.6 億個參數的 BLOOM 版本 —— 它應該可以毫無問題地融入至傳統 GPU 的 RAM 中(Google Colab 免費版本擁有 15 Gb RAM 的 GPU)。

一旦開始,就很可能遇到問題:內存會在訓練或微調期間迅速增加。訓練這個模型的唯一方法是使批大小為 1(batch size=1)。

圖片

使用批大小為 1(batch size=1)為目標分類任務微調 BLOOM 的代碼如下所示。你也可以在 GitHub 項目頁面下載完整代碼:

https://github.com/rasbt/gradient-accumulation-blog/blob/main/src/1_batchsize-1.py

你可以將此代碼直接復制并粘貼到 Google Colab 中,但還必須將隨附的 local_dataset_utilities.py 文件拖放到從該文件導入了一些數據集實用程序的同一文件夾中。

# pip install torch lightning matplotlib pandas torchmetrics watermark transformers datasets -U

import os
import os.path as op
import time

from datasets import load_dataset
from lightning import Fabric
import torch
from torch.utils.data import DataLoader
import torchmetrics
from transformers import AutoTokenizer
from transformers import AutoModelForSequenceClassification
from watermark import watermark

from local_dataset_utilities import download_dataset, load_dataset_into_to_dataframe, partition_dataset
from local_dataset_utilities import IMDBDataset

def tokenize_text (batch):
    return tokenizer (batch ["text"], truncatinotallow=True, padding=True, max_length=1024)

def train (num_epochs, model, optimizer, train_loader, val_loader, fabric):

    for epoch in range (num_epochs):
        train_acc = torchmetrics.Accuracy (
            task="multiclass", num_classes=2).to (fabric.device)

        for batch_idx, batch in enumerate (train_loader):
            model.train ()

            ### FORWARD AND BACK PROP
            outputs = model (
                batch ["input_ids"],
                attention_mask=batch ["attention_mask"],
                labels=batch ["label"]
            ) 

            fabric.backward (outputs ["loss"])

            ### UPDATE MODEL PARAMETERS
            optimizer.step ()
            optimizer.zero_grad ()

            ### LOGGING
            if not batch_idx % 300:
                print (f"Epoch: {epoch+1:04d}/{num_epochs:04d}"
                      f"| Batch {batch_idx:04d}/{len (train_loader):04d}"
                      f"| Loss: {outputs ['loss']:.4f}")

            model.eval ()
            with torch.no_grad ():
                predicted_labels = torch.argmax (outputs ["logits"], 1)
                train_acc.update (predicted_labels, batch ["label"])

        ### MORE LOGGING
        model.eval ()
        with torch.no_grad ():
            val_acc = torchmetrics.Accuracy (task="multiclass", num_classes=2).to (fabric.device)
            for batch in val_loader:
                outputs = model (
                    batch ["input_ids"],
                    attention_mask=batch ["attention_mask"],
                    labels=batch ["label"]
                )
                predicted_labels = torch.argmax (outputs ["logits"], 1)
                val_acc.update (predicted_labels, batch ["label"])

            print (f"Epoch: {epoch+1:04d}/{num_epochs:04d}"
                  f"| Train acc.: {train_acc.compute ()*100:.2f}%"
                  f"| Val acc.: {val_acc.compute ()*100:.2f}%"
                  )
            train_acc.reset (), val_acc.reset ()

if __name__ == "__main__":

    print (watermark (packages="torch,lightning,transformers", pythnotallow=True))
    print ("Torch CUDA available?", torch.cuda.is_available ())
    device = "cuda" if torch.cuda.is_available () else "cpu"

    torch.manual_seed (123)
    # torch.use_deterministic_algorithms (True)

    ##########################
    ### 1 Loading the Dataset
    ##########################
    download_dataset ()
    df = load_dataset_into_to_dataframe ()
    if not (op.exists ("train.csv") and op.exists ("val.csv") and op.exists ("test.csv")):
        partition_dataset (df)

    imdb_dataset = load_dataset (
        "csv",
        data_files={
            "train": "train.csv",
            "validation": "val.csv",
            "test": "test.csv",
        },
    )

    #########################################
    ### 2 Tokenization and Numericalization
    #########################################

    tokenizer = AutoTokenizer.from_pretrained ("bigscience/bloom-560m", max_length=1024)
    print ("Tokenizer input max length:", tokenizer.model_max_length, flush=True)
    print ("Tokenizer vocabulary size:", tokenizer.vocab_size, flush=True)

    print ("Tokenizing ...", flush=True)
    imdb_tokenized = imdb_dataset.map (tokenize_text, batched=True, batch_size=None)
    del imdb_dataset
    imdb_tokenized.set_format ("torch", columns=["input_ids", "attention_mask", "label"])
    os.environ ["TOKENIZERS_PARALLELISM"] = "false"

    #########################################
    ### 3 Set Up DataLoaders
    #########################################

    train_dataset = IMDBDataset (imdb_tokenized, partition_key="train")
    val_dataset = IMDBDataset (imdb_tokenized, partition_key="validation")
    test_dataset = IMDBDataset (imdb_tokenized, partition_key="test")

    train_loader = DataLoader (
        dataset=train_dataset,
        batch_size=1,
        shuffle=True,
        num_workers=4,
        drop_last=True,
    )

    val_loader = DataLoader (
        dataset=val_dataset,
        batch_size=1,
        num_workers=4,
        drop_last=True,
    )

    test_loader = DataLoader (
        dataset=test_dataset,
        batch_size=1,
        num_workers=2,
        drop_last=True,
    )

    #########################################
    ### 4 Initializing the Model
    #########################################

    fabric = Fabric (accelerator="cuda", devices=1, precisinotallow="16-mixed")
    fabric.launch ()

    model = AutoModelForSequenceClassification.from_pretrained (
        "bigscience/bloom-560m", num_labels=2)

    optimizer = torch.optim.Adam (model.parameters (), lr=5e-5)


    model, optimizer = fabric.setup (model, optimizer)
    train_loader, val_loader, test_loader = fabric.setup_dataloaders (
        train_loader, val_loader, test_loader)

    #########################################
    ### 5 Finetuning
    #########################################

    start = time.time ()
    train (
        num_epochs=1,
        model=model,
        optimizer=optimizer,
        train_loader=train_loader,
        val_loader=val_loader,
        fabric=fabric,
    )

    end = time.time ()
    elapsed = end-start
    print (f"Time elapsed {elapsed/60:.2f} min")

    with torch.no_grad ():
        model.eval ()
        test_acc = torchmetrics.Accuracy (task="multiclass", num_classes=2).to (fabric.device)
        for batch in test_loader:
            outputs = model (
                batch ["input_ids"],
                attention_mask=batch ["attention_mask"],
                labels=batch ["label"]
            )
            predicted_labels = torch.argmax (outputs ["logits"], 1)
            test_acc.update (predicted_labels, batch ["label"])

    print (f"Test accuracy {test_acc.compute ()*100:.2f}%")

作者使用了 Lightning Fabric,因為它可以讓開發者在不同硬件上運行此代碼時靈活地改變 GPU 數量和多 GPU 訓練策略。它還允許僅通過調整查準率 flag 來啟用混合精度訓練(mixed-precision training)。在這種情況下,混合精度訓練可以將訓練速度提高三倍,并將內存需求降低約 25%。

上面展示的主要代碼都是在主函數(if __name__ == "__main__" 的 context)中執行的,即使只使用單個 GPU,也推薦使用 PyTorch 運行環境執行多 GPU 訓練。而后,包含在 if __name__ == "__main__" 中的以下三個代碼部分負責數據加載:

# 1 加載數據集

# 2 token 化和數值化

# 3 設置數據加載器

第 4 節是初始化模型(Initializing the Model)中,然后在第 5 節 微調(Finetuning)中,調用 train 函數,這是開始讓事情變得有趣的地方。在 train (...) 函數中,實現了標準的 PyTorch 循環。核心訓練循環的注釋版本如下所示:

批大小為 1(Batch size=1)的問題是梯度更新將會變得非?;靵y和困難,正如下述訓練模型時基于波動的訓練損失和糟糕的測試集性能所看到的:

...
torch : 2.0.0
lightning : 2.0.0
transformers: 4.27.2

Torch CUDA available? True
...
Epoch: 0001/0001 | Batch 23700/35000 | Loss: 0.0969
Epoch: 0001/0001 | Batch 24000/35000 | Loss: 1.9902
Epoch: 0001/0001 | Batch 24300/35000 | Loss: 0.0395
Epoch: 0001/0001 | Batch 24600/35000 | Loss: 0.2546
Epoch: 0001/0001 | Batch 24900/35000 | Loss: 0.1128
Epoch: 0001/0001 | Batch 25200/35000 | Loss: 0.2661
Epoch: 0001/0001 | Batch 25500/35000 | Loss: 0.0044
Epoch: 0001/0001 | Batch 25800/35000 | Loss: 0.0067
Epoch: 0001/0001 | Batch 26100/35000 | Loss: 0.0468
Epoch: 0001/0001 | Batch 26400/35000 | Loss: 1.7139
Epoch: 0001/0001 | Batch 26700/35000 | Loss: 0.9570
Epoch: 0001/0001 | Batch 27000/35000 | Loss: 0.1857
Epoch: 0001/0001 | Batch 27300/35000 | Loss: 0.0090
Epoch: 0001/0001 | Batch 27600/35000 | Loss: 0.9790
Epoch: 0001/0001 | Batch 27900/35000 | Loss: 0.0503
Epoch: 0001/0001 | Batch 28200/35000 | Loss: 0.2625
Epoch: 0001/0001 | Batch 28500/35000 | Loss: 0.1010
Epoch: 0001/0001 | Batch 28800/35000 | Loss: 0.0035
Epoch: 0001/0001 | Batch 29100/35000 | Loss: 0.0009
Epoch: 0001/0001 | Batch 29400/35000 | Loss: 0.0234
Epoch: 0001/0001 | Batch 29700/35000 | Loss: 0.8394
Epoch: 0001/0001 | Batch 30000/35000 | Loss: 0.9497
Epoch: 0001/0001 | Batch 30300/35000 | Loss: 0.1437
Epoch: 0001/0001 | Batch 30600/35000 | Loss: 0.1317
Epoch: 0001/0001 | Batch 30900/35000 | Loss: 0.0112
Epoch: 0001/0001 | Batch 31200/35000 | Loss: 0.0073
Epoch: 0001/0001 | Batch 31500/35000 | Loss: 0.7393
Epoch: 0001/0001 | Batch 31800/35000 | Loss: 0.0512
Epoch: 0001/0001 | Batch 32100/35000 | Loss: 0.1337
Epoch: 0001/0001 | Batch 32400/35000 | Loss: 1.1875
Epoch: 0001/0001 | Batch 32700/35000 | Loss: 0.2727
Epoch: 0001/0001 | Batch 33000/35000 | Loss: 0.1545
Epoch: 0001/0001 | Batch 33300/35000 | Loss: 0.0022
Epoch: 0001/0001 | Batch 33600/35000 | Loss: 0.2681
Epoch: 0001/0001 | Batch 33900/35000 | Loss: 0.2467
Epoch: 0001/0001 | Batch 34200/35000 | Loss: 0.0620
Epoch: 0001/0001 | Batch 34500/35000 | Loss: 2.5039
Epoch: 0001/0001 | Batch 34800/35000 | Loss: 0.0131
Epoch: 0001/0001 | Train acc.: 75.11% | Val acc.: 78.62%
Time elapsed 69.97 min
Test accuracy 78.53%

由于沒有多的 GPU 可用于張量分片(tensor sharding),又能做些什么來訓練具有更大批大小(batch size)的模型呢?

其中一種解決方法就是梯度累積,可以通過它來修改前面提到的訓練循環。

什么是梯度積累?

梯度累積是一種在訓練期間虛擬增加批大?。╞atch size)的方法,當可用的 GPU 內存不足以容納所需的批大小時,這非常有用。在梯度累積中,梯度是針對較小的批次計算的,并在多次迭代中累積(通常是求和或平均),而不是在每一批次之后更新模型權重。一旦累積梯度達到目標「虛擬」批大小,模型權重就會使用累積梯度進行更新。

參考下面更新的 PyTorch 訓練循環:

圖片

如果將 accumulation_steps 設置為 2,那么 zero_grad () 和 optimizer.step () 將只會每隔一秒調用一次。因此,使用 accumulation_steps=2 運行修改后的訓練循環與將批大?。╞atch size)加倍具有相同的效果。

例如,如果想使用 256 的批大小,但只能將 64 的批大小放入 GPU 內存中,就可以對大小為 64 的四個批執行梯度累積。(處理完所有四個批次后,將獲得相當于單個批大小為 256 的累積梯度。)這樣能夠有效地模擬更大的批大小,而無需更大的 GPU 內存或跨不同設備的張量分片。

雖然梯度累積可以幫助我們訓練具有更大批量大小的模型,但它不會減少所需的總計算量。實際上,它有時會導致訓練過程略慢一些,因為權重更新的執行頻率較低。盡管如此,它卻能幫我們解決限制問題,即批大小非常小時導致的更新頻繁且混亂。

例如,現在讓我們運行上面的代碼,批大小為 1,需要 16 個累積步驟(accumulation steps)來模擬批大小等于 16。

輸出如下:

...
torch : 2.0.0
lightning : 2.0.0
transformers: 4.27.2

Torch CUDA available? True
...
Epoch: 0001/0001 | Batch 23700/35000 | Loss: 0.0168
Epoch: 0001/0001 | Batch 24000/35000 | Loss: 0.0006
Epoch: 0001/0001 | Batch 24300/35000 | Loss: 0.0152
Epoch: 0001/0001 | Batch 24600/35000 | Loss: 0.0003
Epoch: 0001/0001 | Batch 24900/35000 | Loss: 0.0623
Epoch: 0001/0001 | Batch 25200/35000 | Loss: 0.0010
Epoch: 0001/0001 | Batch 25500/35000 | Loss: 0.0001
Epoch: 0001/0001 | Batch 25800/35000 | Loss: 0.0047
Epoch: 0001/0001 | Batch 26100/35000 | Loss: 0.0004
Epoch: 0001/0001 | Batch 26400/35000 | Loss: 0.1016
Epoch: 0001/0001 | Batch 26700/35000 | Loss: 0.0021
Epoch: 0001/0001 | Batch 27000/35000 | Loss: 0.0015
Epoch: 0001/0001 | Batch 27300/35000 | Loss: 0.0008
Epoch: 0001/0001 | Batch 27600/35000 | Loss: 0.0060
Epoch: 0001/0001 | Batch 27900/35000 | Loss: 0.0001
Epoch: 0001/0001 | Batch 28200/35000 | Loss: 0.0426
Epoch: 0001/0001 | Batch 28500/35000 | Loss: 0.0012
Epoch: 0001/0001 | Batch 28800/35000 | Loss: 0.0025
Epoch: 0001/0001 | Batch 29100/35000 | Loss: 0.0025
Epoch: 0001/0001 | Batch 29400/35000 | Loss: 0.0000
Epoch: 0001/0001 | Batch 29700/35000 | Loss: 0.0495
Epoch: 0001/0001 | Batch 30000/35000 | Loss: 0.0164
Epoch: 0001/0001 | Batch 30300/35000 | Loss: 0.0067
Epoch: 0001/0001 | Batch 30600/35000 | Loss: 0.0037
Epoch: 0001/0001 | Batch 30900/35000 | Loss: 0.0005
Epoch: 0001/0001 | Batch 31200/35000 | Loss: 0.0013
Epoch: 0001/0001 | Batch 31500/35000 | Loss: 0.0112
Epoch: 0001/0001 | Batch 31800/35000 | Loss: 0.0053
Epoch: 0001/0001 | Batch 32100/35000 | Loss: 0.0012
Epoch: 0001/0001 | Batch 32400/35000 | Loss: 0.1365
Epoch: 0001/0001 | Batch 32700/35000 | Loss: 0.0210
Epoch: 0001/0001 | Batch 33000/35000 | Loss: 0.0374
Epoch: 0001/0001 | Batch 33300/35000 | Loss: 0.0007
Epoch: 0001/0001 | Batch 33600/35000 | Loss: 0.0341
Epoch: 0001/0001 | Batch 33900/35000 | Loss: 0.0259
Epoch: 0001/0001 | Batch 34200/35000 | Loss: 0.0005
Epoch: 0001/0001 | Batch 34500/35000 | Loss: 0.4792
Epoch: 0001/0001 | Batch 34800/35000 | Loss: 0.0003
Epoch: 0001/0001 | Train acc.: 78.67% | Val acc.: 87.28%
Time elapsed 51.37 min
Test accuracy 87.37%

根據上面的結果,損失的波動比以前小了。此外,測試集性能提升了 10%。由于只迭代了訓練集一次,因此每個訓練樣本只會遇到一次。訓練用于 multiple epochs 的模型可以進一步提高預測性能。

你可能還會注意到,這段代碼的執行速度也比之前使用的批大小為 1 的代碼快。如果使用梯度累積將虛擬批大小增加到 8,仍然會有相同數量的前向傳播(forward passes)。然而,由于每八個 epoch 只更新一次模型,因此反向傳播(backward passes)會很少,這樣可更快地在一個 epoch(訓練輪數)內迭代樣本。

結論

梯度累積是一種在執行權重更新之前通過累積多個小的批梯度來模擬更大的批大小的技術。該技術在可用內存有限且內存中可容納批大小較小的情況下提供幫助。

但是,首先請思考一種你可以運行批大小的場景,這意味著可用內存大到足以容納所需的批大小。在那種情況下,梯度累積可能不是必需的。事實上,運行更大的批大小可能更有效,因為它允許更多的并行性且能減少訓練模型所需的權重更新次數。

總之,梯度累積是一種實用的技術,可以用于降低小批大小干擾信息對梯度更新準確性的影響。這是迄今一種簡單而有效的技術,可以讓我們繞過硬件的限制。

PS:可以讓這個運行得更快嗎?

沒問題。可以使用 PyTorch 2.0 中引入的 torch.compile 使其運行得更快。只需要添加一些 model = torch.compile,如下圖所示:

圖片

GitHub 上提供了完整的腳本。

在這種情況下,torch.compile 在不影響建模性能的情況下又減少了十分鐘的訓練時間:

poch: 0001/0001 | Batch 26400/35000 | Loss: 0.0320
Epoch: 0001/0001 | Batch 26700/35000 | Loss: 0.0010
Epoch: 0001/0001 | Batch 27000/35000 | Loss: 0.0006
Epoch: 0001/0001 | Batch 27300/35000 | Loss: 0.0015
Epoch: 0001/0001 | Batch 27600/35000 | Loss: 0.0157
Epoch: 0001/0001 | Batch 27900/35000 | Loss: 0.0015
Epoch: 0001/0001 | Batch 28200/35000 | Loss: 0.0540
Epoch: 0001/0001 | Batch 28500/35000 | Loss: 0.0035
Epoch: 0001/0001 | Batch 28800/35000 | Loss: 0.0016
Epoch: 0001/0001 | Batch 29100/35000 | Loss: 0.0015
Epoch: 0001/0001 | Batch 29400/35000 | Loss: 0.0008
Epoch: 0001/0001 | Batch 29700/35000 | Loss: 0.0877
Epoch: 0001/0001 | Batch 30000/35000 | Loss: 0.0232
Epoch: 0001/0001 | Batch 30300/35000 | Loss: 0.0014
Epoch: 0001/0001 | Batch 30600/35000 | Loss: 0.0032
Epoch: 0001/0001 | Batch 30900/35000 | Loss: 0.0004
Epoch: 0001/0001 | Batch 31200/35000 | Loss: 0.0062
Epoch: 0001/0001 | Batch 31500/35000 | Loss: 0.0032
Epoch: 0001/0001 | Batch 31800/35000 | Loss: 0.0066
Epoch: 0001/0001 | Batch 32100/35000 | Loss: 0.0017
Epoch: 0001/0001 | Batch 32400/35000 | Loss: 0.1485
Epoch: 0001/0001 | Batch 32700/35000 | Loss: 0.0324
Epoch: 0001/0001 | Batch 33000/35000 | Loss: 0.0155
Epoch: 0001/0001 | Batch 33300/35000 | Loss: 0.0007
Epoch: 0001/0001 | Batch 33600/35000 | Loss: 0.0049
Epoch: 0001/0001 | Batch 33900/35000 | Loss: 0.1170
Epoch: 0001/0001 | Batch 34200/35000 | Loss: 0.0002
Epoch: 0001/0001 | Batch 34500/35000 | Loss: 0.4201
Epoch: 0001/0001 | Batch 34800/35000 | Loss: 0.0018
Epoch: 0001/0001 | Train acc.: 78.39% | Val acc.: 86.84%
Time elapsed 43.33 min
Test accuracy 87.91%


請注意,與之前相比準確率略有提高很可能是由于隨機性。

圖片

責任編輯:張燕妮 來源: 機器之心
相關推薦

2019-07-16 07:52:49

NumPyPython機器學習

2023-09-01 14:02:25

用戶分析攻略

2020-06-01 15:04:44

甲骨文自治數據庫

2023-01-18 23:38:32

神經網絡代碼

2020-03-06 15:38:10

編程語言PythonJava

2024-10-24 20:56:36

2023-05-19 06:53:58

GPT分析報告

2018-06-25 15:15:11

編程語言Python爬蟲

2019-03-24 14:14:40

代碼閱讀源代碼

2019-12-03 10:28:53

編程語言PythonJava

2021-10-22 06:04:05

勒索軟件攻擊報告

2024-03-20 12:44:35

AI訓練

2022-04-29 08:48:25

開源

2020-02-05 17:10:54

人工智能機器學習技術

2021-04-13 09:09:29

DevOps流程Docker

2024-04-24 13:21:01

Llama 3視頻AR

2016-06-01 10:25:47

大數據/博科

2015-05-14 19:23:47

思科錢伯斯

2018-05-15 09:15:03

CNN卷積神經網絡函數
點贊
收藏

51CTO技術棧公眾號

gogo大胆日本视频一区| 最近2019中文字幕在线高清| 欧美日韩午夜爽爽| 国内久久视频| 国产精品视频网站| 91精品尤物| 亚洲一二三在线| aa级大片免费在线观看| 在线成人午夜影院| 黄色小视频在线观看| 性久久久久久久久| 免费观看羞羞视频网站| 中文字幕精品综合| 97在线播放视频| av高清不卡在线| 亚洲不卡中文字幕无码| 成人动漫av在线| 播放灌醉水嫩大学生国内精品| 国产毛片精品一区| a天堂资源在线观看| 成人自拍视频在线观看| 狠狠精品干练久久久无码中文字幕 | 精品国产污污免费网站入口| jizz在线观看视频| 欧美人与禽zozo性伦| 草草影院在线观看| 欧美一级日韩免费不卡| 伊人在线视频| 日韩欧美黄色影院| 成人午夜视屏| 久久精品视频在线播放| 欧美大片91| 国产精品久久不能| 黄色日韩精品| 亚洲一二三区精品| 久久人人97超碰com| 羞羞网站在线观看入口免费| 一区二区三区精品久久久| 亚洲日本va中文字幕久久| 色av一区二区| 国产精品电影| 久久国产色av| 精品盗摄女厕tp美女嘘嘘| 亚洲va欧美va国产综合剧情| 日韩视频精品在线观看| 伊人狠狠色丁香综合尤物| 不卡的av电影| 亚洲1024| 亚洲第一精品福利| 亚洲国产视频二区| 亚洲在线一区二区| 免费观看久久久4p| 奇米影音第四色| 在线观看亚洲成人| 激情小说亚洲| 91在线网站视频| 黄一区二区三区| 欧美色老女人| 日韩精品一区二区三区四区视频| 国产aⅴ精品一区二区四区| 国产精品美女呻吟| 日本免费在线视频不卡一不卡二| 日本在线观看a| 欧美亚洲国产bt| 亚洲一区二区av| 成人h在线播放| 国产成人精品一区二区三区网站观看| 日本欧洲一区| 日韩精品欧美国产精品忘忧草 | 精品一区二区三区中文字幕老牛| 精品日韩欧美| 国产欧美在线观看一区| h视频在线播放| 久热爱精品视频线路一| 欧美日韩国产一区精品一区| 农民人伦一区二区三区| 欧美日韩一二三四五区| 裤袜国产欧美精品一区| 国产精品视频xxx| 极品少妇一区二区三区精品视频| 一级黄色av| 亚洲一区二区福利| 精品1区2区3区4区| 中文字幕桃花岛| 亚洲摸下面视频| 欧美视频成人| 色综合97天天综合网| 欧美一区二区三区四区视频| 久久99偷拍| 成人在线视频一区二区三区| 福利一区福利二区微拍刺激| 粉嫩一区二区三区在线观看| 成人av蜜桃| 一区二区成人在线视频| **欧美日韩在线观看| 91亚洲精品一区| 中文字幕日本不卡| 伊人久久精品| 在线观看日韩羞羞视频| 欧美色视频一区| 久久综合国产| 亚欧美在线观看| 综合激情国产一区| 蜜桃av噜噜一区| 91在线不卡| 91精品视频免费观看| 中文字幕一区免费在线观看| 成人一区视频| 黄色一级视频播放| 欧美哺乳videos| 99视频精品| av在线播放网| 成人欧美一区二区三区黑人| 久久久国产精品午夜一区ai换脸| av在线网页| 日韩欧美一区二区视频在线播放 | 日本三级免费观看| 日韩毛片在线看| 噜噜噜躁狠狠躁狠狠精品视频| 青青草超碰在线| 国产精品久久久久久久久久久久久久 | 国精品**一区二区三区在线蜜桃| 日本亚洲精品| 国产亚洲欧美一区二区三区| 午夜成人在线视频| 999久久久免费精品国产| 成人在线小说| 国产成人亚洲综合91精品| 中文字幕一区在线观看| 91成人福利| 成人eeuss影院在线观看| 久久91亚洲精品中文字幕奶水| 国产**成人网毛片九色 | 国产美女无遮挡网站| 一区二区三区四区精品| 日韩黄色小视频| 色婷婷av在线| 四虎影院一区二区| 国产视频久久久久| 成人av在线看| 国产成年精品| 羞羞在线观看网站| 成人亚洲激情网| 欧美日韩一区二区在线观看| 亚洲国内精品| 国产又色又爽又黄刺激在线视频| 亚洲砖区区免费| 深夜福利一区二区| 国产精品美女一区二区三区 | 三级久久三级久久| 国产无遮挡裸体视频在线观看| 三年中文高清在线观看第6集| 亚洲国模精品一区| 东方欧美亚洲色图在线| 蜜桃在线一区| 天海翼一区二区三区免费| 91在线免费网站| 91精品免费观看| 国产成人综合在线| 97久久综合精品久久久综合| 成人在色线视频在线观看免费大全 | 四虎影视2018在线播放alocalhost| 亚洲最大激情中文字幕| 欧美日韩一区不卡| 国产精品一区二区果冻传媒| 日本少妇精品亚洲第一区| 一级毛片免费观看| 欧美国产视频在线观看| 国产一区二区三区欧美| 国产精品电影院| 亚洲天堂久久| 日本精品另类| 91麻豆福利| 欧美性bbwbbwbbwhd| 久久九九国产精品怡红院 | 天天色综合社区| 国产精品久久网| 制服丝袜亚洲精品中文字幕| 成人综合婷婷国产精品久久蜜臀 | 成人在线看片网站| 国内精品久久国产| 一区二区三区动漫| 欧美日韩国产一区二区三区| 天堂成人免费av电影一区| 狂野欧美xxxx韩国少妇| 国产区视频在线| 欧美大片在线播放| 91久久精品一区| 日韩一区二区久久久| 精品国产91久久久| 成人免费高清在线| 极品日韩av| 免费看成人人体视频| 男人添女人下部高潮视频在线观看| 日本 片 成人 在线| 日本一区视频在线播放| 热re99久久精品国产66热| 亚洲国产精品电影在线观看| 亚洲一区在线观看免费观看电影高清| 国产综合色视频|