google-kubernetes-engine - 在 Python 中使用 joblib Parallel 时,Google Kubernetes 容器 CPU 使用率不会增加

标签 google-kubernetes-engine python-multiprocessing

我正在 Google Kubernetes 集群中运行一个容器,该容器在具有 64 个 vCPU 和 57 GB 内存的节点上运行。我为容器分配了 16 个 vCPU 和 24 GB 内存。当我在使用 joblib 并行处理且 n_jobs=12 的容器中运行 Python 函数时,CPU 使用率永远不会超过 1 个核心。我尝试在容器内运行一个简单的并行处理脚本,CPU 使用率保持在 1。我不知道发生了什么。任何帮助将不胜感激!

这是 Pod 的 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

最佳答案

并行计算最重要的是实现。

如果没有算法,就很难查明影响性能的瓶颈。

我认为问题在于实现而不是 GKE 本身。


先决条件

我尝试使用新创建的 GKE 集群重新创建并行计算场景,结果如下:

  • GKE 版本:1.15.9
  • 节点数量:1
  • 节点规范:
    • 22 核
    • 64GB 内存。

以下是用于测试的 pod 的 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

请具体查看请求限制部分

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

它将请求 16 个 CPU,这在以后会很重要。

测试

我尝试使用以下方式模拟 pod 中的工作负载:

  • 名为stress的应用程序(apt installstress)
  • 具有 joblibParallel 的 python 程序:

应用压力

我在 Pod 内运行此应用程序 3 次,使用不同的 CPU 量 (4,16,32):

  • $ 压力 -c 4
  • $ 压力 -c 16
  • $ 压力 -c 32

4 核

HTOP1

正如您在上面的输出中看到的,该应用程序完全占用了 4 个核心。

命令的输出:$ kubectl top node显示CPU使用率约为18%:

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

22 个核心中的 1 个核心应约为 4.5%,乘以 4 后约为 18%,与上述输出相同。

查看 GCP 监控,您可以看到利用率约为 0.25(这是分配的 16 个核心中的 4 个):

GCP1

16 核

HTOP2

正如您在上面的输出中看到的,该应用程序完全占用了 16 个内核。

命令的输出:$ kubectl top node显示CPU使用率约为73%:

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

22 个核心中的 1 个核心应约为 4.5%,乘以 16 后约为 72%,与上述输出几乎相同。

查看 GCP 监控,您可以看到利用率约为 1.0(这是分配的 16 个核心中的 16 个):

GCP2

32 核

如果不划分每个进程的时间,就无法在 16 核计算机上运行 32 核工作负载。看看 Kubernetes 是如何管理的:

HTOP3

如您所见,所有核心均已使用,但每个核心仅占 73% 左右。这将在 100% 使用率下增加大约 16 个核心。

$ kubectl 顶级节点GCP 监控 将具有与 16 核情况相同的输出。

Python程序

我尝试使用带有 joblibParallel 的基本 Python 程序,如下所示:

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 核之间的计算所需时间存在差异。

下图显示了运行此测试的 Pod 的 CPU 使用情况。正如您所看到的,使用量逐渐增加。请记住,所使用的算法将对 CPU 使用率产生巨大影响。

GCP Monitoring

如果程序有:

  • n_jobs=4 它将在 4 个核心上以 100% 的速度运行,这将需要 pod 占用约 25% 的 CPU 利用率。
  • n_jobs=16 它将在所有核心上以约 100% 的使用率运行,这意味着 pod 的 CPU 利用率约为 100%。

如果您对此有任何疑问,请告诉我。

关于google-kubernetes-engine - 在 Python 中使用 joblib Parallel 时,Google Kubernetes 容器 CPU 使用率不会增加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60939428/

相关文章:

google-cloud-platform - VPC 原生 GKE 集群生产准备好了吗?

dockerfile - Concourse 尝试使用错误的 sha256 摘要提取 docker 镜像并失败

python 对象组合和多处理

python - 使用多处理模块填充复杂的 numpy 数组

kubernetes - 重新创建 GCP Kubernetes 集群

kubernetes - 使用 Google IAM 进行 GKE 服务 Web 访问

terraform - 为节点池指定 "dotted"k8s 标签?

python - 用于加密多个文件的多线程或多处理

python - 双重或更多多重处理?

python - 检查 Python multiprocessing.Connection 的实例?