我正在 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
) - 具有
joblib
和Parallel
的 python 程序:
应用压力
我在 Pod 内运行此应用程序 3 次,使用不同的 CPU 量 (4,16,32):
$ 压力 -c 4
$ 压力 -c 16
$ 压力 -c 32
4 核
正如您在上面的输出中看到的,该应用程序完全占用了 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 个):
16 核
正如您在上面的输出中看到的,该应用程序完全占用了 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 个):
32 核
如果不划分每个进程的时间,就无法在 16 核计算机上运行 32 核工作负载。看看 Kubernetes 是如何管理的:
如您所见,所有核心均已使用,但每个核心仅占 73% 左右。这将在 100% 使用率下增加大约 16 个核心。
$ kubectl 顶级节点
和 GCP 监控
将具有与 16 核情况相同的输出。
Python程序
我尝试使用带有 joblib
和 Parallel
的基本 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 使用率产生巨大影响。
如果程序有:
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/