Использование ЦПУ Google Kubernetes Container не увеличивается при использовании joblib Parallel в Python - PullRequest
0 голосов
/ 30 марта 2020

Я запускаю контейнер в Google Kubernetes Cluster, и этот контейнер работает на узле с 64 виртуальными ЦП и 57 ГБ памяти. Я выделил контейнеру 16 виртуальных ЦП и 24 ГБ памяти. Когда я запускаю функцию Python в контейнере, который использует параллельную обработку joblib с n_jobs = 12, загрузка ЦП никогда не превышает 1 ядро. Я попытался запустить простой сценарий параллельной обработки в контейнере, и загрузка ЦП осталась равной 1. Я не знаю, что происходит. Любая помощь будет оценена!

Вот YAML стручка:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "9"
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"extensions/v1beta1","kind":"Deployment","metadata":{"annotations":{},"name":"inference","namespace":"default"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"inference"}},"template":{"metadata":{"labels":{"app":"inference"}},"spec":{"containers":[{"args":["workers/infer.py"],"command":["python"],"image":"gcr.io/staging-239917/autoqa:v3","name":"inference","resources":{"limits":{"cpu":"16000m","memory":"16000Mi"},"requests":{"cpu":"16000m","memory":"8000Mi"}}}]}}}}
  creationTimestamp: "2020-03-28T16:49:50Z"
  generation: 9
  labels:
    app: inference
  name: inference
  namespace: default
  resourceVersion: "4878070"
  selfLink: /apis/apps/v1/namespaces/default/deployments/inference
  uid: 23eb391e-7114-11ea-a540-42010aa20052
spec:
  progressDeadlineSeconds: 2147483647
  replicas: 1
  revisionHistoryLimit: 2147483647
  selector:
    matchLabels:
      app: inference
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: inference
    spec:
      containers:
      - args:
        - workers/infer.py
        command:
        - python
        image: gcr.io/staging-239917/autoqa:1.0.9026a5a8-55ba-44b5-8f86-269cea2e201c
        imagePullPolicy: IfNotPresent
        name: inference
        resources:
          limits:
            cpu: 16100m
            memory: 16000Mi
          requests:
            cpu: "16"
            memory: 16000Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 1
  conditions:
  - lastTransitionTime: "2020-03-28T16:49:50Z"
    lastUpdateTime: "2020-03-28T16:49:50Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  observedGeneration: 9
  readyReplicas: 1
  replicas: 1
  updatedReplicas: 1

1 Ответ

0 голосов
/ 06 мая 2020

Самое важное в параллельных вычислениях - это реализация.

Без алгоритма может быть трудно точно определить узкое место, влияющее на производительность.

Я думаю, что проблема заключается в реализации, а не в самой GKE.


Предварительные условия

Я пытался воссоздать параллельные вычисления Сценарий с недавно созданным кластером GKE и вот что я узнал:

  • Версия GKE: 1.15.9
  • Количество узлов: 1
  • Спецификация узла:
    • 22 ядра
    • 64 ГБ оперативной памяти.

Вот определение YAML для контейнера, который использовался для тестирования:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
  namespace: default
spec:
  containers:
  - image: ubuntu
    resources:
      limits:
        cpu: "16"
        memory: "32Gi"
      requests:
        cpu: "16"
        memory: "32Gi" 
    command:
      - sleep
      - "infinity"
    imagePullPolicy: IfNotPresent
    name: ubuntu
  restartPolicy: Always

Пожалуйста, определите c посмотрите на деталь requests и limits

    resources:
      limits:
        cpu: "16"
        memory: "32Gi"
      requests:
        cpu: "16"
        memory: "32Gi" 

Это запросит 16 CPU, что будет важно позже.

Тестирование

Я пытался смоделировать рабочую нагрузку в модуле с помощью:

  • приложения, называемого стрессом (apt install stress)
  • python программы с joblib и Parallel:

Напряжение приложения

Я запускал это приложение в модуле 3 раза с различным используемым количеством процессора (4,16,32):

  • $ stress -c 4
  • $ stress -c 16
  • $ stress -c 32

4 ядра

HTOP1

Как видно из вышеприведенного вывода, это приложение полностью использует 4 ядра.

Вывод команды: $ kubectl top node показывает, что загрузка процессора составляет около 18%:

❯ kubectl top node
NAME                                      CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
gke-gke-high-default-pool-f7a17f78-0696   4090m        18%    948Mi           1%  

1 ядро ​​из 22 должно составлять около 4,5%, а после умножения его на 4 оно будет равно быть около 18%, что соответствует показателю выше.

Изучив GCP Monitoring, вы можете увидеть коэффициент использования примерно в 0,25 (что составляет 4 ядра из 16 выделенных):

GCP1

16 ядра

HTOP2

Как видно из вышеприведенного вывода, этим приложением полностью занято 16 ядер.

Вывод команды: $ kubectl top node показывает, что загрузка ЦП составляет около 73%:

NAME                                      CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
gke-gke-high-default-pool-f7a17f78-0696   16168m       73%    945Mi           1%  

1 ядро ​​из 22 должно составлять около 4,5%, а после умножения его на 16 оно составит около 72%, что примерно столько же, сколько указано выше вывод.

Если посмотреть на GCP Monitoring, вы можете увидеть коэффициент использования примерно в 1,0 (то есть 16 ядер из 16 выделенных):

GCP2

32 ядра

Невозможно запустить 32-ядерную рабочую нагрузку на 16-ядерном компьютере без разделения времени для каждого процесса. Посмотрите, как Kubernetes управляет этим:

HTOP3

Как вы можете видеть все ядра используются, но только примерно на 73% каждый , Это добавило бы около 16 ядер при 100% использования.

$ kubectl top node и GCP Monitoring будут иметь тот же выход, что и 16-ядерный корпус.

Python программа

Я пытался использовать программу basi c Python с joblib и Parallel, как показано ниже:

from joblib import Parallel, delayed
import sys 

my_list = range(20000)
squares = []

# Function to parallelize
def find_square(i):
    return i ** 131072

# With parallel processing
squares = Parallel(n_jobs=int(sys.argv[1]), verbose=1)(delayed(
    find_square)(i)for i in my_list)

Я запустил вышеуказанная программа с количеством ядер от 4 до 16. Ниже приведены результаты:

[Parallel(n_jobs=4)]: Done 20000 out of 20000 | elapsed:  7.0min finished
[Parallel(n_jobs=5)]: Done 20000 out of 20000 | elapsed:  5.6min finished
[Parallel(n_jobs=6)]: Done 20000 out of 20000 | elapsed:  4.7min finished
[Parallel(n_jobs=7)]: Done 20000 out of 20000 | elapsed:  4.0min finished
[Parallel(n_jobs=8)]: Done 20000 out of 20000 | elapsed:  3.5min finished
[Parallel(n_jobs=9)]: Done 20000 out of 20000 | elapsed:  3.1min finished
[Parallel(n_jobs=10)]: Done 20000 out of 20000 | elapsed:  2.8min finished
[Parallel(n_jobs=11)]: Done 20000 out of 20000 | elapsed:  2.6min finished
[Parallel(n_jobs=12)]: Done 20000 out of 20000 | elapsed:  2.6min finished
[Parallel(n_jobs=13)]: Done 20000 out of 20000 | elapsed:  2.6min finished
[Parallel(n_jobs=14)]: Done 20000 out of 20000 | elapsed:  2.5min finished
[Parallel(n_jobs=15)]: Done 20000 out of 20000 | elapsed:  2.5min finished
[Parallel(n_jobs=16)]: Done 20000 out of 20000 | elapsed:  2.5min finished

Как видите, существует разница во времени, необходимая для вычислений между 4 ядрами и 16.

Ниже на графике показано использование процессора для модуля, который выполнял эти тесты. Как вы можете видеть, наблюдается постепенное увеличение использования. Пожалуйста, имейте в виду, что используемый алгоритм будет иметь огромное влияние на использование процессора.

GCP Monitoring

Если бы программа имела:

  • n_jobs=4, она работала бы на 4 ядрах при 100%, что означало бы около 25% загрузки процессора для модуля.
  • n_jobs=16 он будет работать на всех ядрах при примерно 100% использовании, что повлечет за собой около 100% загрузки ЦП для модуля.

Пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы к этому.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...