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

提升GPU利用率:探索NVIDIA的MIG與MPS虛擬化技術

云計算 虛擬化
對于像V100這樣的GPU,有些廠商會讓多個用戶來共用一張GPU,從而降低單個用戶的費用。在共享GPU過程中,一個重要的操作就是虛擬化,但是虛擬化在安全問題、服務質量上面還有較大的進步空間。

1. 背景

目前GPU卡資源緊張且業務需求逐漸遞增,存在整卡不夠分配或GPU利用率低造成資源浪費的情況。

我們也不可否認還有非常多的應用場景對算力的需求不大,比如:

  • AI推理場景,基本都是在線實時計算,要求延時低,batchsize小,計算量不大。
  • AI開發機場景,團隊內部共享GPU,對算力要求低。

這些場景的分布非常廣泛,在這些場景下,AI應用是無法把GPU強大的計算能力全部發揮出來的。所以,長期以來,很多用戶的GPU利用率都不高,基本都只有10%-30%。

GPU的切分(虛擬化)需求基本來自于兩個方面,一個是普通消費者,二個是計算/服務中心。

對于普通消費者(用戶),希望使用到新推出的GPU特性,比如某些高性能的CUDA操作,而這些操作只有高版本的硬件SM才具備;同時,很多情況下消費者并不能用滿一整張顯卡(比如V100或者A100)的所有資源;另外“數據中心”類的GPU產品,價格都比較高(V100、A100都是wRMB為單位)。所以消費者在使用、價格方面有小資源高性能的GPU需求。

某購物平臺上面的GPU價格某購物平臺上面的GPU價格

對于服務廠商(比如云服務),一方面需要提供價格便宜、性能穩定的GPU給用戶使用。由于整卡的成本價格高,所以服務費用(租金)不會太低。另一個方面,大型的計算中心需要管理成千上萬的GPU,服務廠商有提升集群利用率的訴求,小規格的GPU資源能夠提升配置的細粒度,從而能夠更好的提升集群GPU利用率。

目前,對于像V100這樣的GPU,有些廠商會讓多個用戶來共用一張GPU,從而降低單個用戶的費用。在共享GPU過程中,一個重要的操作就是虛擬化,但是虛擬化在安全問題、服務質量上面還有較大的進步空間。

2. GPU Share策略方案

①MIG(MULTI-INSTANCEGPU****)

隨著AMPERE架構的發布,NVIDIA推出了劃時代的產品–A100,性能達到前所未有的高度。從性能壓榨的角度講,普通的一個AI應用要想把全部A100性能發揮出來是很難的。反過來說,大量資源沒用上,閑置就是浪費。

因此,MIG(multi-Instance GPU)就這樣應運而生了。

MIG 打破了原有 GPU 資源的分配方式,能夠基于 A100 從硬件層面把一個GPU切分成最多 7 個 GPU 實例,并且可以使每一個 GPU 實例都能夠擁有各自的 SMs 和內存系統。簡單理解就是現在可以并發的同時跑7個不同的AI應用,最大程度把強大的GPU資源全部用上。

由于是基于硬件切分的方式,MIG可以讓每個GPU實例之間的內存空間訪問互不干擾,保障每一個使用者的工作時延和吞吐量都是可預期的。

imgimg

由于采用的是硬切分的方式,GPU實例之間的隔離度很好,但是靈活度就比較受限了。MIG的切分方式,每個GPU實例的大小只能按照固定的profile來切分:

imgimg

這個表格清晰的展示了各種不同大小的 GPU 實例他們具備的流處理器比例、內存比例、以及可以分配的數量。

各種profile的組合方式也是非常有限的,如下圖所示:

imgimg

②MPS(MULTI-PROCESS SERVICE )

MPS,包含在CUDA工具包中的多進程服務。它是一組可以替換的,二進制兼容的CUDA API實現,包括3個模塊:

  • 守護進程,用于啟動或停止MPS服務進程, 同時也負責為用戶進程和服務進程之間建立連接關系
  • 服務進程, 多個用戶在單個GPU上面的共享連接,為多個用戶之間執行并發的服務
  • 用戶運行時,集成在CUDA driver庫中,對于CUDA應用程序來說,調用過程透明

當用戶希望在多進程條件下發揮GPU的并發能力,就可以使用MPS。MPS允許多個進程共享同一個GPU context。這樣可以避免上下文切換造成的額外的開銷,以及串行化執行帶來的時間線拉長。同時,MPS還允許不同進程的kernel和memcpy操作在同一GPU上并發執行,以實現最大化GPU利用率 。

具體可以用下面2個圖片對比來說明MPS的特點。

首先,在沒有開啟MPS的情況下,有兩個進程A(藍色)和B(紅色),每個進程都有自己的CUDA context。從圖中可以看到,兩個進程雖然同時被發送,但是在實際執行中是被串行執行的,兩個進程會被GPU中的時間片輪轉調度機制輪流調度進GPU進行執行。這就是執行的時間線被拉長的原因。

imgimg

繼續往下看,如果我們開啟了MPS,同樣是啟動兩個進程A(藍色)和B(紅色),MPS服務進程會將它們兩個CUDA context融合到一個CUDA context里面。這就是最大的不同。兩個context融合到一個之后,GPU上不存在context輪轉切換,減少額外開銷;而且從時間片上來看的話,進程A和B的函數是真正的實現了并發執行的。這就是MPS帶來的好處。

imgimg

MPS的好處是顯而易見的,可以提升GPU利用率,減少GPU上下文切換時間、減少GPU上下文存儲空間。總的來說,就是可以充分利用GPU資源。那么,這么好的技術,為什么在業界用得很少呢?

因為MPS的context融合方式會帶來一個嚴重的問題:錯誤會互相影響。一個進程錯誤退出(包括被kill),如果該進程正在執行kernel,那么和該進程共同share IPC和UVM的其他進程也會一同出錯退出。因此無法在生產場景上大規模使用。

一個節點只能指定一種GPU Share策略

GPU Share策略

說明

備注

MPS

多個進程或應用程序共享同一個GPU的資源,適用于需要并行處理大量數據或執行復雜計算任務的應用場景。

單卡均分;可指定一個節點中多少張卡進行拆分;備注:均分份數—》拆分卡數GPU:1/4 * NVIDIA Ampere A100顯存:1/4 * 24GB 或 6GB

MIG

在一個物理GPU上同時運行多個獨立的GPU實例,不會相互干擾。

支持每個卡都可以指定一種MIG策略;單卡:排序固定,最多7切分:7*14+2+14+1+1+1...img NVIDIA Ampere A100(3g.40gb)

GPU卡型

MIG(僅支持A系列、H系列的卡型)

NVIDIA Ampere A800(80G)

7 * (1g.10gb)4 * (1g.20gb)3 * (2g.20gb)2 * (3g.40gb)1 * (4g.40gb)1 * (7g.80gb)1 * (1g.12gb)、1 * (2g.24gb)、1 * (3g.47gb)2 * (1g.10gb)、1 * (2g.20gb)、1 * (3g.40gb)

NVIDIA Ampere 4090(24G)

不支持

NVIDIA Ampere A100(40G)

7 * (1g.5gb)3 * (2g.10gb)2 * (3g.20gb)1* (4g.20gb)1 * (7g.40gb)

NVIDIA Ampere A30(24G)

4 * (1g.6gb)2 * (2g.12gb)1 * (4g.24gb)2 * (1g.6gb)、1 * (2g.12gb)

NVIDIA GeForce 3090

不支持

3. 實踐與測試

方案一(MPS)

源自nvidia官方開源項目 https://github.com/nvidia/k8s-device-plugin

nvidia-device-plugin 支持兩種gpu-share的方式,分別為 “時間片” 和 “mps”,二者不兼容,只能二選其一。

  1. 時間片方案:應用可以完整使用GPU內存,各應用采用時間片的方式共享GPU計算能力,各應用間內存不隔離(直接放棄這個方案)。
  2. MPS方案:GPU卡被MPS DAEMON 托管,按照拆分SHARE的副本數,均分GPU memory,應用使用GPU memory超過均分值后 OOM,各個進程間GPU memory隔離,GPU的計算能力也按照比例拆分(還是基于時間片的)。

相對而言,MPS方案在隔離性和資源分配方面更具優勢,本次驗證主要做MPS的,沒有做時間片的。

支持的粒度:可以支持到單節點級別,只對某個節點開啟MPS或者時間片的SHARE。

啟用MPS操作

安裝nvidia-device-plugin的時候,啟用第二配置,默認配置不開啟mps或者時間片,在第二配置中啟用gpu-share。

nvidia-device-plugin 支持到具體節點開啟mps,如果某個節點需要開啟MPS,需要在節點上打對應標簽開啟。

nvidia.com/mps.capable 決定是否在節點啟用MPS, 例如:true

nvidia.com/device-plugin.config 決定當前節點使用的配置名字。例如:config1

理論上配置個數是沒限制的,單集群下,可以做多個配置,例如 nvidia-share-4,nvidia-share-2,按照不同的業務需求,對不同的節點按照不同比例拆分。

一個完整的部署編排yaml實例如下(yaml中的節點親和性和容忍,按需修改即可):

---
# Source: nvidia-device-plugin/templates/service-account.yml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nvidia-device-plugin-service-account
  namespace: kube-system
  labels:
    helm.sh/chart: nvidia-device-plugin-0.15.0-rc.2
    app.kubernetes.io/name: nvidia-device-plugin
    app.kubernetes.io/version: "0.15.0-rc.2"
    app.kubernetes.io/managed-by: Helm
---
# Source: nvidia-device-plugin/templates/configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nvidia-device-plugin-configs
  namespace: kube-system
  labels:
    helm.sh/chart: nvidia-device-plugin-0.15.0-rc.2
    app.kubernetes.io/name: nvidia-device-plugin

    app.kubernetes.io/version: "0.15.0-rc.2"
    app.kubernetes.io/managed-by: Helm
data:
  config0: |-
    version: v1

  config1: |-
    version: v1
    sharing:
      mps:
        renameByDefault: true
        resources:
        - name: nvidia.com/gpu
          replicas: 2
---
# Source: nvidia-device-plugin/templates/role.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nvidia-device-plugin-role
  namespace: kube-system
  labels:
    helm.sh/chart: nvidia-device-plugin-0.15.0-rc.2
    app.kubernetes.io/name: nvidia-device-plugin

    app.kubernetes.io/version: "0.15.0-rc.2"
    app.kubernetes.io/managed-by: Helm
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list", "watch"]
---
# Source: nvidia-device-plugin/templates/role-binding.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: nvidia-device-plugin-role-binding
  namespace: kube-system
  labels:
    helm.sh/chart: nvidia-device-plugin-0.15.0-rc.2
    app.kubernetes.io/name: nvidia-device-plugin
    app.kubernetes.io/version: "0.15.0-rc.2"
    app.kubernetes.io/managed-by: Helm
subjects:
  - kind: ServiceAccount
    name: nvidia-device-plugin-service-account
    namespace: kube-system
roleRef:
  kind: ClusterRole
  name: nvidia-device-plugin-role
  apiGroup: rbac.authorization.k8s.io
---
# Source: nvidia-device-plugin/templates/daemonset-device-plugin.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-device-plugin
  namespace: kube-system
  labels:
    helm.sh/chart: nvidia-device-plugin-0.15.0-rc.2
    app.kubernetes.io/name: nvidia-device-plugin
    app.kubernetes.io/version: "0.15.0-rc.2"
    app.kubernetes.io/managed-by: Helm
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: nvidia-device-plugin
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app.kubernetes.io/name: nvidia-device-plugin
      annotations:
        checksum/config: 5cae25ed78745124db43b014773455550cf9c60962da45074548790b2acb66f0
    spec:
      priorityClassName: system-node-critical
      securityContext:
        {}
      serviceAccountName: nvidia-device-plugin-service-account
      shareProcessNamespace: true
      initContainers:
      - image: nvcr.io/nvidia/k8s-device-plugin:v0.17.1
        name: nvidia-device-plugin-init
        command: ["config-manager"]
        env:
        - name: ONESHOT
          value: "true"
        - name: KUBECONFIG
          value: ""
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: "spec.nodeName"
        - name: NODE_LABEL
          value: "nvidia.com/device-plugin.config"
        - name: CONFIG_FILE_SRCDIR
          value: "/available-configs"
        - name: CONFIG_FILE_DST
          value: "/config/config.yaml"
        - name: DEFAULT_CONFIG
          value: "config0"
        - name: FALLBACK_STRATEGIES
          value: "named,single"
        - name: SEND_SIGNAL
          value: "false"
        - name: SIGNAL
          value: ""
        - name: PROCESS_TO_SIGNAL
          value: ""
        volumeMounts:
          - name: available-configs
            mountPath: /available-configs
          - name: config
            mountPath: /config
      containers:
      - image: nvcr.io/nvidia/k8s-device-plugin:v0.17.1
        name: nvidia-device-plugin-sidecar
        command: ["config-manager"]
        env:
        - name: ONESHOT
          value: "false"
        - name: KUBECONFIG
          value: ""
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: "spec.nodeName"
        - name: NODE_LABEL
          value: "nvidia.com/device-plugin.config"
        - name: CONFIG_FILE_SRCDIR
          value: "/available-configs"
        - name: CONFIG_FILE_DST
          value: "/config/config.yaml"
        - name: DEFAULT_CONFIG
          value: "config0"
        - name: FALLBACK_STRATEGIES
          value: "named,single"
        - name: SEND_SIGNAL
          value: "true"
        - name: SIGNAL
          value: "1" # SIGHUP
        - name: PROCESS_TO_SIGNAL
          value: "nvidia-device-plugin"
        volumeMounts:
          - name: available-configs
            mountPath: /available-configs
          - name: config
            mountPath: /config
        securityContext:
          capabilities:
            add:
              - SYS_ADMIN
      - image: nvcr.io/nvidia/k8s-device-plugin:v0.17.1
        imagePullPolicy: IfNotPresent
        name: nvidia-device-plugin-ctr
        command: ["nvidia-device-plugin"]
        env:
          - name: MPS_ROOT
            value: "/run/nvidia/mps"
          - name: CONFIG_FILE
            value: /config/config.yaml
          - name: NVIDIA_MIG_MONITOR_DEVICES
            value: all
          - name: NVIDIA_VISIBLE_DEVICES
            value: all
          - name: NVIDIA_DRIVER_CAPABILITIES
            value: compute,utility
        securityContext:
          capabilities:
            add:
              - SYS_ADMIN
        volumeMounts:
          - name: device-plugin
            mountPath: /var/lib/kubelet/device-plugins
          # The MPS /dev/shm is needed to allow for MPS daemon health-checking.
          - name: mps-shm
            mountPath: /dev/shm
          - name: mps-root
            mountPath: /mps
          - name: cdi-root
            mountPath: /var/run/cdi
          - name: available-configs
            mountPath: /available-configs
          - name: config
            mountPath: /config
      volumes:
        - name: device-plugin
          hostPath:
            path: /var/lib/kubelet/device-plugins
        - name: mps-root
          hostPath:
            path: /run/nvidia/mps
            type: DirectoryOrCreate
        - name: mps-shm
          hostPath:
            path: /run/nvidia/mps/shm
        - name: cdi-root
          hostPath:
            path: /var/run/cdi
            type: DirectoryOrCreate
        - name: available-configs
          configMap:
            name: "nvidia-device-plugin-configs"
        - name: config
          emptyDir: {}
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: nvidia.com/gpu.present
                operator: In
                values:
                - "true"
      tolerations:
        - key: CriticalAddonsOnly
          operator: Exists
        - effect: NoSchedule
          key: nvidia.com/gpu
          operator: Exists
---
# Source: nvidia-device-plugin/templates/daemonset-mps-control-daemon.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-device-plugin-mps-control-daemon
  namespace: kube-system
  labels:
    helm.sh/chart: nvidia-device-plugin-0.15.0-rc.2
    app.kubernetes.io/name: nvidia-device-plugin
    app.kubernetes.io/version: "0.15.0-rc.2"
    app.kubernetes.io/managed-by: Helm
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: nvidia-device-plugin
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app.kubernetes.io/name: nvidia-device-plugin
      annotations:
        checksum/config: 5cae25ed78745124db43b014773455550cf9c60962da45074548790b2acb66f0
    spec:
      priorityClassName: system-node-critical
      securityContext:
        {}
      serviceAccountName: nvidia-device-plugin-service-account
      shareProcessNamespace: true
      initContainers:
      - image: nvcr.io/nvidia/k8s-device-plugin:v0.17.1
        name: mps-control-daemon-mounts
        command: [mps-control-daemon, mount-shm]
        securityContext:
          privileged: true
        volumeMounts:
        - name: mps-root
          mountPath: /mps
          mountPropagation: Bidirectional
      - image: nvcr.io/nvidia/k8s-device-plugin:v0.17.1
        name: mps-control-daemon-init
        command: ["config-manager"]
        env:
        - name: ONESHOT
          value: "true"
        - name: KUBECONFIG
          value: ""
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: "spec.nodeName"
        - name: NODE_LABEL
          value: "nvidia.com/device-plugin.config"
        - name: CONFIG_FILE_SRCDIR
          value: "/available-configs"
        - name: CONFIG_FILE_DST
          value: "/config/config.yaml"
        - name: DEFAULT_CONFIG
          value: "config0"
        - name: FALLBACK_STRATEGIES
          value: "named,single"
        - name: SEND_SIGNAL
          value: "false"
        - name: SIGNAL
          value: ""
        - name: PROCESS_TO_SIGNAL
          value: ""
        volumeMounts:
          - name: available-configs
            mountPath: /available-configs
          - name: config
            mountPath: /config
      containers:
        # TODO: How do we synchronize the plugin and control-daemon on restart.
        - image: nvcr.io/nvidia/k8s-device-plugin:v0.17.1
          name: mps-control-daemon-sidecar
          command: ["config-manager"]
          env:
          - name: ONESHOT
            value: "false"
          - name: KUBECONFIG
            value: ""
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: "spec.nodeName"
          - name: NODE_LABEL
            value: "nvidia.com/device-plugin.config"
          - name: CONFIG_FILE_SRCDIR
            value: "/available-configs"
          - name: CONFIG_FILE_DST
            value: "/config/config.yaml"
          - name: DEFAULT_CONFIG
            value: "config0"
          - name: FALLBACK_STRATEGIES
            value: "named,single"
          - name: SEND_SIGNAL
            value: "true"
          - name: SIGNAL
            value: "1"
          - name: PROCESS_TO_SIGNAL
            value: "/usr/bin/mps-control-daemon"
          volumeMounts:
            - name: available-configs
              mountPath: /available-configs
            - name: config
              mountPath: /config
        - image: nvcr.io/nvidia/k8s-device-plugin:v0.17.1
          imagePullPolicy: IfNotPresent
          name: mps-control-daemon-ctr
          command: [mps-control-daemon]
          env:
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                apiVersion: v1
                fieldPath: spec.nodeName
          - name: CONFIG_FILE
            value: /config/config.yaml
          - name: NVIDIA_MIG_MONITOR_DEVICES
            value: all
          - name: NVIDIA_VISIBLE_DEVICES
            value: all
          - name: NVIDIA_DRIVER_CAPABILITIES
            value: compute,utility
          securityContext:
            privileged: true
          volumeMounts:
          - name: mps-shm
            mountPath: /dev/shm
          - name: mps-root
            mountPath: /mps
          - name: available-configs
            mountPath: /available-configs
          - name: config
            mountPath: /config
      volumes:
      - name: mps-root
        hostPath:
          path: /run/nvidia/mps
          type: DirectoryOrCreate
      - name: mps-shm
        hostPath:
          path: /run/nvidia/mps/shm
      - name: available-configs
        configMap:
          name: "nvidia-device-plugin-configs"
      - name: config
        emptyDir: {}
      nodeSelector:
        # We only deploy this pod if the following sharing label is applied.
        nvidia.com/mps.capable: "true"
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: nvidia.com/gpu.present
                operator: In
                values:
                - "true"
      tolerations:
        - key: CriticalAddonsOnly
          operator: Exists
        - effect: NoSchedule
          key: nvidia.com/gpu
          operator: Exists

驗證

我們的測試集群只有一個節點,有8張4090卡,單卡GPU Memory為 24G。我們采用MPS方案,將卡副本SHARE為兩份,理論上集群節點上看到的 nvidia.com/gpu.shared 資源為16個,單個資源的可用GPU Memory為12G左右。

  • 部署yaml到集群

imgimg

img

部署成功,節點資源如預期,GPU卡的兩倍(因為我們之SHARE了2)。

  • 部署一個使用shared資源的容器(它只能使用一個shared設備)

imgimg

img

部署成功。

  • 驗證GPU MEMORY

初始狀態

imgimg

由于理論上線為12G,我們這兒創建 (1024, 1024, 1024) 類型為fp32的tensor的size為 4G

為了不超過12G,測試 (1024, 1024, 1024) * 2 + (1024,1024,512)理論上不會OOM;

為了達到12G,測試(1024, 1024, 1024) * 3 就應該OOM。

  • (1024,1024,1024) * 2 + (1024,1024,1024)結果,如預期。

imgimg

  • (1024, 1024, 1024) * 3,結果如預期。

imgimg

性能

測試腳本

import torch
import time

# size of tensor
w = 10000000

def compute_pi(n):
    count = 0
    total =  n // w
    print(f"total is {total}")
    for idx in range(total):
        print(f"{idx}/{total}")
        x = torch.rand(w, device='cuda') * 2 - 1
        y = torch.rand(w, device='cuda') * 2 - 1
        distance = x**2 + y **2
        count += (distance <= 1).sum().item()
    return 4 * count / n

n = w * 100000
s = time.time()
pi = compute_pi(n)
e = time.time()

print(f"total {e - s}")
print(f"pi is {pi}")

測試方案: 直接在主機上,在沒有開啟MPS的卡上先后進行多進程并行計算和多進程串行計算,得到計算時間。

再在mps的卡上,進行同樣的計算,對比兩種方案的計算耗時。

在測試機器上(4090顯卡)開啟mps后,同時在一個卡上執行測試腳本,分別看兩個實例同時執行腳本的耗時和單獨執行的耗時,進行對比結果。

  • 在開啟MPS的卡上,兩個進程并行計算。

實例1,計算用時 193 秒

imgimg

實例2,計算用時 193秒

img

GPU使用率,可以看到GPU開啟MPS之后是 Exclusive 模式,GPU利用率 100%

imgimg

  • 在開啟MPS的卡上,串行運行計算任務(就是兩個任務先后計算)

實例1,計算耗時74秒

imgimg

實例2, 計算耗時74秒

imgimg

GPU使用率截圖

imgimg

  • 在沒開啟MPS的卡上,進行并行計算

實例1,用時188秒

imgimg

實例2,用時188秒

imgimg

  • 串行計算,耗時71秒

img

結論:開啟MPS的性能影響不大,開啟后193 ,未開啟188, 性能損失 = 2%

適用場景
  1. 小模型
  2. 計算量不是很大,QPS不是很高的情況下。
卡級別的MPS開啟

目前官方nvidia-device-plugin沒有支持單機上指定卡開啟mps,(場景,單機8卡,四卡開MPS,四卡獨占),源代碼中,可以看到有多種resource的支持,但是參數被屏蔽了,另外就是單配置多資源的情況下,會開啟多個mps daemon,導致nvidia-device-plugin容器不能正常運行。

針對這個問題,進行了單獨的適配,目前已經支持了卡級別MPS的開啟。需要更多大規模的測試后,再投入生產。

方案二(VGPU)

來自第四范式的vgpu方案,目前volcano(要求版本>=1.8.0)集成的也是它。 https://github.com/Project-HAMi/HAMi

其目的是為了統一算力卡的虛擬化調度,正在集成華為vNPU(這個ISSUE),值得調研和投入。

方案三(MIG)

如何管理MIG,參考了知乎(https://zhuanlan.zhihu.com/p/558046644),其中如果關注資源利用率,可以看看 vgpu 和 mig-vgpu部分的吞吐量,性能對比部分。 MIG由gi和ci組成,gi表示gpu實例,ci表示算力單元。

拆分MIG操作流程

MIG的shell操作主要包括:查看命令、創建命令和刪除命令。MIG的操作都要用root權限,所以如果是非root用戶,操作命令要加上sudo字符,下面操作示例中默認用戶是root。 首先將這些操作例出來,然后對一些創建與刪除操作進行講解。

功能

命令

說明

【開】指定某卡 開啟MIG

nvidia-smi -i 0 -mig 1

-i 指定的GPU編號 可以是0,1,3

【關】指定某卡 關閉MIG

nvidia-smi -i 0 -mig 0


【開】全部卡的MIG使能

nvidia-smi -mig 1

1 打開; 0 關閉;

【查看】子GPU實例的profile

nvidia-smi mig -lgip

獲得子GPU可創建的情況

【查看】子GPU實例的placement

nvidia-smi mig -lgipp

獲得子GPU可以創建的位置

【查看】子GPU上CI的profile

nvidia-smi mig -lcip

添加 -gi指定特定的子GPU,如指定子GPU 2查看上面的CI實例: nvidia-smi mig -lci -gi 2

【查看】已創建的子GPU的情況

nvidia-smi mig -lgi


【創建】子GPU + 對應的CI

nvidia-smi mig -i 0 -cgi 9 -C

-i: 指定父GPU -cgi:列出需要創建的子GPU的類型 格式:9 或者 3g.20gb 或者 MIG 3g.20gb -C :連同一起創建CI

【創建】子GPU

nvidia-smi mig -i 0 -cgi 9

創建一個profile為9的GI實例: 3個計算單元 + 20gb顯存。

【創建】子GPU上面的CI

nvidia-smi mig -cci 0,1 -gi 1

-cci:創建的CI實例的編號 -gi:指定子GPU

【刪除】子GPU

nvidia-smi mig -dgi -i 0 -gi 1

-i:指定父GPU -gi:待刪除的子GPU

【刪除】子GPU上面的CI 實例

nvidia-smi mig -dci -i 0 -gi 1 -ci 0

-i:指定父GPU -gi:待操作的子GPU -ci: 待刪除的CI實例

【查看】 整個MIG實例情況

nvidia-smi -L


MIG的操作順序概況為:

使能MIG -> 創建GI實例 -> 創建CI實例 -> 刪除CI實例 -> 刪除GI實例 -> 關閉MIG

imgimg

  • 檢查卡類型 nvidia-smi,卡要求A系列以后
  • 針對單卡開啟MIG,nvidia-smi -i 0 -mig 1,如果出現pending的情況可能需要重啟機器。

imgimg

  • 查看支持的mig profile,nvidia-smi mig -i 0 -lgip

img

  • 這兒我們將0號卡拆成兩個3g.40gb單元 nvidia-smi mig -i 0 -cgi 9,執行兩次,創建了兩。

img

  • 查看創建結果 nvidia-smi mig -i 0 -lgi

imgimg

  • 查看每個GI實例支持的CI規格 nvidia-smi mig -i 0 -lcip

imgimg

  • 給mig實例創建 CI nvidia-smi mig -gi 0 -cci 2

imgimg

  • 查看最終結果 nvidia-smi

imgimg

apiVersion: v1
kind: Pod
metadata:
  name: test1
spec:
  containers:
  - image: harbor.maip.io/base/pytorch-alpaca:v3
    imagePullPolicy: IfNotPresent
    name: test
    command:
    - /bin/bash
    - -c
    - "sleep infinity"
    resources:
      requests:
        nvidia.com/mig-3g.40gb:  1
      limits:
        nvidia.com/mig-3g.40gb:  1
---
apiVersion: v1
kind: Pod
metadata:
  name: test2
spec:
  containers:
  - image: harbor.maip.io/base/pytorch-alpaca:v3
    imagePullPolicy: IfNotPresent
    name: test
    command:
    - /bin/bash
    - -c
    - "sleep infinity"
    resources:
      requests:
        nvidia.com/mig-3g.40gb:  1
      limits:
        nvidia.com/mig-3g.40gb:  1
---
apiVersion: v1
kind: Pod
metadata:
  name: test3
spec:
  containers:
  - image: harbor.maip.io/base/pytorch-alpaca:v3
    imagePullPolicy: IfNotPresent
    name: test
    command:
    - /bin/bash
    - -c
    - "sleep infinity"
    resources:
      requests:
        nvidia.com/gpu:  1
      limits:
        nvidia.com/gpu:  1
  • 看結果

imgimg

imgimgimgimgimgimg

刪除mig 需要先刪除 ci 刪除ci

nvidia-smi mig -dci -i 0 -gi 1 -ci 0 刪除gi nvidia-smi mig -dgi -i 0 -gi 1

4. gpu-operator一鍵部署

GPU Operator 是 NVIDIA 提供的一個 Kubernetes Operator,它簡化了在 Kubernetes 集群中使用 GPU 的過程,通過自動化的方式處理 GPU 驅動程序安裝、NVIDIA Device Plugin、DCGM Exporter 等組件。

helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
helm install --wait --generate-name \
     -n gpu-operator --create-namespace \
     nvidia/gpu-operator \
     # 如果已經安裝了 NVIDIA 驅動程序,可以在 GPU Operator 中禁用驅動安裝,修改values.yaml
     --set driver.enabled=false
  • 其中mps和mig的配置,需要在values.yaml中devicePlugin和migManager新增,然后創建configmap
devicePlugin:
  enabled: true
  repository: nvcr.io/nvidia
  image: k8s-device-plugin
  version: v0.17.1
  imagePullPolicy: IfNotPresent
  env:
    - name: PASS_DEVICE_SPECS
      value: "true"
    - name: FAIL_ON_INIT_ERROR
      value: "true"
    - name: DEVICE_LIST_STRATEGY
      value: envvar
    - name: DEVICE_ID_STRATEGY
      value: uuid
    - name: NVIDIA_VISIBLE_DEVICES
      value: all
    - name: NVIDIA_DRIVER_CAPABILITIES
      value: all
    - name: NODE_LABEL
      value: nvidia.com/device-plugin.config
  config:
    name: device-plugin-config
    default: default
migManager:
  enabled: true
  repository: nvcr.io/nvidia/cloud-native
  image: k8s-mig-manager
  version: v0.12.1-ubuntu20.04
  imagePullPolicy: IfNotPresent
  env:
    - name: WITH_REBOOT
      value: "false"
  config:
    default: all-disabled
    name: custom-mig-parted-config
  gpuClientsConfig:
    name: ""
  • 測試用的device-plugin配置文件。
---
# Source: gpu-operator/templates/plugin_config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: device-plugin-config
  namespace: gpu-operator
  labels:
    app.kubernetes.io/name: gpu-operator
    helm.sh/chart: gpu-operator-v24.3.0
    app.kubernetes.io/instance: stable
    app.kubernetes.io/version: "v24.3.0"
    app.kubernetes.io/managed-by: Helm
data:
  default: |-
    version: v1
    flags:
      migStrategy: none
  mig-mixed: |-
    version: v1
    flags:
      migStrategy: mixed
  mig-single: |-
    version: v1
    flags:
      migStrategy: single
  config1: |-
    flags:
      migStrategy: none
    sharing:
      mps:
        renameByDefault: true
        resources:
        - devices:
          - "0"
          - "1"
          name: nvidia.com/gpu
          replicas: 2
    version: v1

測試用的mig策略配置文件

apiVersion: v1
kind: ConfigMap
metadata:
  name: custom-mig-parted-config
  namespace: gpu-operator
data:
  config.yaml: |
    version: v1
    # 針對第一個卡開啟的MIG
    mig-configs:
      custom-1:
        - devices: [0]
          mig-enabled: true
          mig-devices:
            "1g.10gb": 2
            "2g.20gb": 1
            "3g.40gb": 1

      all-disabled:
        - devices: all
          mig-enabled: false

      all-enabled:
        - devices: all
          mig-enabled: true
          mig-devices: {}

      # A100-40GB, A800-40GB
      all-1g.5gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.5gb": 7

      all-1g.5gb.me:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.5gb+me": 1

      all-2g.10gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "2g.10gb": 3

      all-3g.20gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "3g.20gb": 2

      all-4g.20gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "4g.20gb": 1

      all-7g.40gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "7g.40gb": 1

      # H100-80GB, H800-80GB, A100-80GB, A800-80GB, A100-40GB, A800-40GB
      all-1g.10gb:
        # H100-80GB, H800-80GB, A100-80GB, A800-80GB
        - device-filter: ["0x233010DE", "0x233110DE", "0x232210DE", "0x20B210DE", "0x20B510DE", "0x20F310DE", "0x20F510DE"]
          devices: all
          mig-enabled: true
          mig-devices:
            "1g.10gb": 7

        # A100-40GB, A800-40GB
        - device-filter: ["0x20B010DE", "0x20B110DE", "0x20F110DE", "0x20F610DE"]
          devices: all
          mig-enabled: true
          mig-devices:
            "1g.10gb": 4

      # H100-80GB, H800-80GB, A100-80GB, A800-80GB
      all-1g.10gb.me:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.10gb+me": 1

      # H100-80GB, H800-80GB, A100-80GB, A800-80GB
      all-1g.20gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.20gb": 4

      all-2g.20gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "2g.20gb": 3

      all-3g.40gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "3g.40gb": 2

      all-4g.40gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "4g.40gb": 1

      all-7g.80gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "7g.80gb": 1

      # A30-24GB
      all-1g.6gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.6gb": 4

      all-1g.6gb.me:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.6gb+me": 1

      all-2g.12gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "2g.12gb": 2

      all-2g.12gb.me:
        - devices: all
          mig-enabled: true
          mig-devices:
            "2g.12gb+me": 1

      all-4g.24gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "4g.24gb": 1

      # H100 NVL, H800 NVL, GH200
      all-1g.12gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.12gb": 7

      all-1g.12gb.me:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.12gb+me": 1

      all-1g.24gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.24gb": 4

      all-2g.24gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "2g.24gb": 3

      # H100 NVL, H800 NVL
      all-3g.47gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "3g.47gb": 2

      all-4g.47gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "4g.47gb": 1

      all-7g.94gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "7g.94gb": 1

      # H100-96GB, PG506-96GB, GH200
      all-3g.48gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "3g.48gb": 2

      all-4g.48gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "4g.48gb": 1

      all-7g.96gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "7g.96gb": 1


      # H100-96GB, GH200, H100 NVL, H800 NVL, H100-80GB, H800-80GB, A800-40GB, A800-80GB, A100-40GB, A100-80GB, A30-24GB, PG506-96GB
      all-balanced:
        # H100 NVL, H800 NVL
        - device-filter: ["0x232110DE", "0x233A10DE"]
          devices: all
          mig-enabled: true
          mig-devices:
            "1g.12gb": 1
            "2g.24gb": 1
            "3g.47gb": 1

        # H100-80GB, H800-80GB, A100-80GB, A800-80GB
        - device-filter: ["0x233010DE", "0x233110DE", "0x232210DE", "0x20B210DE", "0x20B510DE", "0x20F310DE", "0x20F510DE"]
          devices: all
          mig-enabled: true
          mig-devices:
            "1g.10gb": 2
            "2g.20gb": 1
            "3g.40gb": 1

        # A100-40GB, A800-40GB
        - device-filter: ["0x20B010DE", "0x20B110DE", "0x20F110DE", "0x20F610DE"]
          devices: all
          mig-enabled: true
          mig-devices:
            "1g.5gb": 2
            "2g.10gb": 1
            "3g.20gb": 1

        # A30-24GB
        - device-filter: "0x20B710DE"
          devices: all
          mig-enabled: true
          mig-devices:
            "1g.6gb": 2
            "2g.12gb": 1

        # H100-96GB, PG506-96GB, GH200
        - device-filter: ["0x234210DE", "0x233D10DE", "0x20B610DE"]
          devices: all
          mig-enabled: true
          mig-devices:
            "1g.12gb": 2
            "2g.24gb": 1
            "3g.48gb": 1
  • 部署完成之后查看服務狀態
kubectl get pod -n gpu-operator
  • 使用打對gpu節點打標簽的方式開啟對應的share策略

操作方法:

  • 開啟MPS策略:將節點標簽 nvidia.com/device-plugin.config 的值修改成具體的MPS策略,具體策略值必須存在配置的ConfigMap中,例如上面配置中的 config1,它表示針對兩個卡開啟的MPS。
  • 開啟MIG策略:將節點標簽 nvidia.com/device-plugin.config 的值修改成mig-mixed策略,它表示可以允許不同規格的MIG出現在一臺機器上。然后還需要將節點標簽 nvidia.com/mig.config 的值修改成具體的mig策略配置名字。例如上面的 custom-1,它表示針對第一個卡開啟的MIG策略。
  • 開啟之后的驗證方式參考實踐與測試


責任編輯:武曉燕 來源: 運維開發故事
相關推薦

2013-04-02 09:15:40

服務器虛擬化

2013-01-04 10:44:31

IBMdW

2012-11-07 15:07:30

VMware虛擬化

2011-04-12 09:07:47

磁盤空間利用率虛擬化的隱藏成本

2025-11-03 02:45:00

2025-09-15 08:34:01

2012-05-08 13:24:45

負載均衡帶寬銳捷網絡

2025-09-03 01:45:00

2022-08-12 11:37:16

優化實踐

2009-05-26 17:34:14

VMware虛擬化服務器

2015-10-15 09:09:38

Oracle數據庫華為

2013-08-21 14:20:50

飛魚星流控王飛魚星

2013-09-03 18:07:49

GPU虛擬化華為NVIDIA

2013-11-15 09:51:21

云端渲染NVIDIA

2011-07-13 09:16:08

服務器虛擬化數據中心

2015-06-04 13:44:34

5G

2018-07-11 15:21:25

GPU虛擬化技術

2020-06-23 07:56:57

虛擬桌面AMDNvidia

2024-08-09 15:50:15

2011-03-17 13:54:42

查詢參數SQL語句利用率
點贊
收藏

51CTO技術棧公眾號

日韩精品专区在线影院重磅| 成人欧美一区二区三区白人| 91精品国产乱码久久久久久蜜臀 | 丁香花电影在线观看完整版| 国产成人av自拍| 欧美一区深夜视频| 精品国产国产综合精品| 国产精品视频3p| 欧美性xxxxx极品少妇| 国产成人三级视频| 爽爽视频在线观看| 韩国午夜理伦三级不卡影院| 久久久中文字幕| 人妻互换一区二区激情偷拍| 91麻豆精品激情在线观看最新| 色欧美日韩亚洲| 国产精品波多野结衣| 亚洲色图狠狠干| 国产成人啪免费观看软件| 国产91在线高潮白浆在线观看| 九九精品视频免费| 欧美日韩播放| 亚洲电影第1页| 99中文字幕在线| 日韩不卡免费高清视频| 亚洲国产精品一区二区www在线| 日本一区二区三区四区在线观看| 亚洲免费视频网| 狠狠狠色丁香婷婷综合久久五月| 青青久久aⅴ北条麻妃| 九九热国产精品视频| 日韩毛片视频| 亚洲人成电影网站色…| 91传媒理伦片在线观看| 91视频亚洲| 欧美日韩一区二区三区在线| 日韩中字在线观看| 色婷婷在线播放| 国产精品激情偷乱一区二区∴| 国产九区一区在线| www.污视频| 国产精品一区二区91| 国产精品专区第二| 中文在线观看av| 久色成人在线| 久久久久一本一区二区青青蜜月| 内射一区二区三区| 成人在线免费小视频| 精品一区二区三区四区| 黄色av网址在线观看| 亚洲国产中文在线| 4438x亚洲最大成人网| 五月婷婷丁香色| 国产精品黄色片| 欧美日韩在线精品一区二区三区激情| 亚洲高清在线免费观看| 最新日韩三级| 在线一区二区观看| 蜜臀视频一区二区三区| 亚洲一区二区三区四区| 在线观看亚洲一区| 亚洲成人天堂网| 99视频有精品高清视频| 欧美一区二区大片| 日本中文字幕精品| 久久电影在线| 亚洲色图五月天| 日本视频在线免费| 最新欧美人z0oozo0| 欧美xxxx做受欧美| 免费在线一区二区三区| 亚洲黄色天堂| 日韩**中文字幕毛片| 亚洲视屏在线观看| 激情六月婷婷久久| 成人欧美视频在线| 男女网站在线观看| 国产精品伦理一区二区| 国产奶头好大揉着好爽视频| 成人av黄色| 亚洲成人自拍一区| 欧美日韩亚洲一二三| 久久99国产精品二区高清软件| 6080日韩午夜伦伦午夜伦| 一区二区三区人妻| 亚洲成在人线免费观看| 中文字幕精品国产| 久草视频手机在线观看| 免费日韩av片| 成人写真视频福利网| 亚洲av无码国产综合专区| 99久久久无码国产精品| 亚洲第一导航| heyzo高清中文字幕在线| 色综合久久88色综合天天6| 岛国av免费在线| 国产伦精品一区二区三区在线播放| 日韩成人免费视频| 麻豆明星ai换脸视频| 日韩午夜黄色| 91亚洲永久免费精品| 亚洲AV第二区国产精品| 亚洲欧洲在线观看av| 欧美精品久久久久久久自慰| 国产一区二区三区朝在线观看| 日韩一区二区三区四区| 9.1成人看片免费版| 亚洲精品一区二区在线看| 4438全国成人免费| 国内精品国产成人国产三级| 久久久噜噜噜久久人人看| 中文字幕精品在线播放| 欧美大电影免费观看| 日韩免费高清av| 免费看的黄色录像| 噜噜噜91成人网| 成人免费视频网站入口| 日本最新在线视频| 日本精品一区二区三区高清| 亚洲精品乱码久久久久久蜜桃欧美| 精品国产精品久久一区免费式| 欧美精品成人在线| 91丨porny丨在线中文 | www.日本精品| 国产精品资源在线| 亚洲v日韩v欧美v综合| av影院在线免费观看| 这里只有精品电影| 99久久精品久久亚洲精品| 欧美在线综合| 狠狠干一区二区| 欧美6一10sex性hd| 欧美一级一区二区| 在线观看美女av| 精品一区二区三区视频在线观看| 欧美一区二区三区电影在线观看| 大桥未久在线播放| 日韩一级完整毛片| 成人在线观看高清| 韩国理伦片一区二区三区在线播放| 欧美福利精品| 亚洲最大成人| 国产午夜精品久久久| 国产 欧美 日韩 在线| 成人综合婷婷国产精品久久蜜臀 | 欧美手机在线观看| 久久精品国产精品亚洲精品| 日韩在线三区| 成人在线高清| www.亚洲免费视频| 91尤物国产福利在线观看| 国产精品久久久久久久岛一牛影视 | 国产另类自拍| 51精品视频| 日韩h在线观看| xxxx.国产| 91捆绑美女网站| 男人的天堂日韩| 日韩中文欧美| 99re在线视频观看| √天堂8资源中文在线| 亚洲第一区第一页| 中文字幕精品三级久久久| 久久青草国产手机看片福利盒子| jizzjizz国产精品喷水| 免费av一区| 国产精品一区二区女厕厕| 亚洲麻豆精品| 日韩欧美黄色影院| 久久狠狠高潮亚洲精品| 2017欧美狠狠色| 天堂中文视频在线| 91精品国产视频| 国产精品亚洲不卡a| 亚洲欧美电影| xvideos成人免费中文版| 精品国产亚洲av麻豆| 亚洲国产裸拍裸体视频在线观看乱了| 欧美成人三级伦在线观看| 视频在线观看一区| 日韩第一页在线观看| 久久久久久久久久久久久久久久久久久久| 午夜剧场成人观在线视频免费观看| 欧美亚洲日本| 欧美人妖巨大在线| 国产性70yerg老太| 国产午夜久久久久| 特黄特黄一级片| 久久久久国产一区二区| 中文一区一区三区免费| 国产精品视屏| 成人久久一区二区| 日本不卡1234视频| 久久久精品在线| 欧美巨乳在线| 日韩一区二区三区四区| av黄色在线播放| 亚洲欧美日韩综合aⅴ视频| 狠狠人妻久久久久久综合蜜桃| 奇米精品一区二区三区在线观看一 | 日韩欧美在线播放| 免费在线观看一级片| 久久一区二区视频| 日韩大尺度视频| 免费成人在线影院| 好吊妞无缓冲视频观看| 99久久99久久精品国产片桃花 | 日本黄视频在线观看| 欧美视频在线一区二区三区| 五月天综合在线| 1000部国产精品成人观看| 国产精品无码永久免费不卡| 国产在线精品一区二区三区不卡| 免费在线激情视频| 国模吧视频一区| 国产精品无码乱伦| 欧美色婷婷久久99精品红桃| 狠狠色综合一区二区| 久久伊人久久| 成人天堂噜噜噜| 日韩一区二区三区免费| 91国内免费在线视频| 五月花成人网| 久久久www成人免费精品| yiren22亚洲综合伊人22| 亚洲国产精品yw在线观看| 国产白浆在线观看| 日韩一区和二区| 一级片免费网站| 欧美色手机在线观看| 日日骚av一区二区| 富二代精品短视频| 日本三级小视频| 偷窥少妇高潮呻吟av久久免费| 免费在线一级片| 亚洲一区二区精品3399| 欧美黑人猛猛猛| 亚洲天堂久久久久久久| 亚洲国产精品一区二区久久hs| 国产亚洲一区二区三区在线观看| 精品一区二区视频在线观看| 大尺度一区二区| 欧美双性人妖o0| 99在线热播精品免费| 亚洲av无码一区东京热久久| 国产成人精品午夜视频免费| 欧美一级小视频| 国产揄拍国内精品对白| 一二三av在线| 国产成人aaaa| 91人人澡人人爽| 北条麻妃一区二区三区| 少妇伦子伦精品无吗| av不卡一区二区三区| 国产精品无码电影| 91麻豆精品秘密| 偷拍夫妻性生活| 国产欧美日韩不卡| 日本黄色录像视频| 一区二区三区中文字幕在线观看| 欧美日韩人妻精品一区二区三区| 一区二区三区美女视频| 麻豆changesxxx国产| 亚洲福利一区二区三区| 五月婷婷中文字幕| 在线亚洲免费视频| 91成品人影院| 精品国产亚洲在线| 欧美偷拍视频| zzijzzij亚洲日本成熟少妇| 操你啦在线视频| 午夜免费久久久久| yy6080久久伦理一区二区| 成人欧美在线观看| 精品国内亚洲2022精品成人| 欧美高清性xxxxhd| 色中色综合网| 国产一区二区片| 玖玖玖国产精品| 樱花草www在线| 99精品桃花视频在线观看| 西西444www无码大胆| 最新热久久免费视频| 国产一级免费观看| 在线看国产一区二区| 精品久久久免费视频| 精品视频在线播放色网色视频| 97视频精彩视频在线观看| 欧美另类99xxxxx| 欧美电影免费观看高清完整| 成人女保姆的销魂服务| 欧美日韩一区二区三区在线电影| 色一情一乱一伦一区二区三区丨 | 97久久精品在线| 丁香婷婷久久| 国产中文一区二区| 国产精品久久久久久麻豆一区软件 | 精品欧美不卡一区二区在线观看| xvideos亚洲| 国产免费不卡| 成人自拍爱视频| 久久一区91| 欧美性大战久久久久xxx| 国内精品久久久久影院色 | 亚洲欧美激情另类| 在线中文字幕日韩| 国产在线精彩视频| 亚洲一区二区三区在线免费观看 | 中文字幕免费高| 日韩精品五月天| av av在线| 亚洲另类在线一区| 中国女人一级一次看片| 亚洲国产精品人久久电影| 久操视频在线| 国产精品久久久久久久久久尿| 国产成人一二| 日本三日本三级少妇三级66| 视频一区在线视频| 黄色国产在线观看| 亚洲一级电影视频| 国产偷人妻精品一区二区在线| 亚洲视频专区在线| 色综合桃花网| 精品久久久久久一区二区里番| 欧美一区二区| 中文字幕一区久久| 国产精品青草综合久久久久99| 九九九在线观看| 亚洲精品国产精品自产a区红杏吧| 成人在线播放| 91免费看国产| 久久久9色精品国产一区二区三区| 少妇黄色一级片| 国产视频亚洲色图| 91黑人精品一区二区三区| 亚洲欧美日韩第一区| 秋霞伦理一区| 鲁片一区二区三区| 久久精品卡一| 蜜桃无码一区二区三区| 日韩欧美国产高清91| 亚洲欧洲综合在线| 欧美整片在线观看| 一区二区三区视频免费观看| 欧美老熟妇喷水| 91浏览器在线视频| 亚洲精品久久久久久久蜜桃| 亚洲人成电影网| 久久精品国产精品亚洲毛片| 欧洲久久久久久| 日韩av一区二区在线影视| 日本成人免费视频| 欧美群妇大交群的观看方式| 一本一道波多野毛片中文在线| 国产精品久久一区| 91亚洲国产高清| 91福利视频免费观看| 亚洲高清免费视频| 亚洲色图 校园春色| 国产精品久久久久久久app| 四季av一区二区凹凸精品| 亚洲精品在线视频播放| 一区二区三区欧美激情| 国产 日韩 欧美 综合| 68精品久久久久久欧美| 国内黄色精品| 一级黄色在线播放| 亚洲成人精品一区| 黄色国产在线| 亚洲jizzjizz日本少妇| 亚洲美女色禁图| 国产精品无码无卡无需播放器| 在线播放欧美女士性生活| 精精国产xxxx视频在线中文版 | 欧美一区激情| 精品中文字幕在线播放| 欧美在线小视频| 最近中文字幕免费mv2018在线| 国产精品免费视频一区二区| 国产精品美女久久久| 丰满的亚洲女人毛茸茸| 日韩视频免费观看高清在线视频| 蜜桃视频在线观看免费视频| 日韩精品一线二线三线| 国产经典欧美精品| 天天综合天天干| 久久精品视频在线| 外国成人在线视频| 天堂在线一区二区三区| 亚洲v日本v欧美v久久精品| 电影av在线| 国产主播一区二区三区四区| 青娱乐精品视频在线| 欧美一级高潮片| 日韩在线小视频| 香蕉视频一区二区三区| 国产在线视频三区| 一本大道综合伊人精品热热| 2024短剧网剧在线观看|