Transformers 文档
分布式 CPU
并获得增强的文档体验
开始使用
分布式 CPU
CPU 很常见,并且在 GPU 不可用时,可以成为一种经济高效的训练选择。当训练大型模型或单个 CPU 太慢时,使用分布式 CPU 训练可以帮助加速训练。
本指南演示了如何使用 Trainer 和 Kubernetes 集群,在裸机上使用 DistributedDataParallel (DDP) 策略,通过多个 CPU 执行分布式训练。本指南中显示的所有示例都依赖于 Intel oneAPI HPC Toolkit。
您将需要 Intel oneAPI 中的两个工具包。
- oneCCL 包含深度学习中常用集合通信的高效实现,例如 all-gather、all-reduce 和 reduce-scatter。要从预构建的 wheel 安装,请确保始终使用最新版本。请参阅此处的表格,以检查 Python 和 PyTorch 版本是否支持 oneCCL 版本。
# installs oneCCL for PyTorch 2.4.0
pip install oneccl_bind_pt==2.4.0 -f https://developer.intel.com/ipex-whl-stable-cpu
有关更多详细信息,请参阅 oneCCL 安装。
- MPI 是一个消息传递接口,用于硬件和网络之间的通信。 oneCCL 工具包与 MPI 一起安装,但您需要在使用前 source 环境,如下所示。
oneccl_bindings_for_pytorch_path=$(python -c "from oneccl_bindings_for_pytorch import cwd; print(cwd)")
source $oneccl_bindings_for_pytorch_path/env/setvars.sh
最后,安装 Intex Extension for PyTorch (IPEX),它可以为 Intel 硬件实现额外的性能优化,例如权重共享和更好的线程运行时控制。
pip install intel_extension_for_pytorch==<version_name> -f https://developer.intel.com/ipex-whl-stable-cpu
有关更多详细信息,请参阅 IPEX 安装。
Trainer
Trainer 支持使用 oneCCL 后端通过 CPU 进行分布式训练。在命令参数中添加 --ddp_backend ccl
参数即可启用它。
下面的示例演示了 run_qa.py 脚本。它允许在一个 Xeon CPU 上使用两个进程进行训练,每个 socket 运行一个进程。
调整变量 OMP_NUM_THREADS/CCL_WORKER_COUNT
以获得最佳性能。
export CCL_WORKER_COUNT=1
export MASTER_ADDR=127.0.0.1
mpirun -n 2 -genv OMP_NUM_THREADS=23 \
python3 run_qa.py \
--model_name_or_path google-bert/bert-large-uncased \
--dataset_name squad \
--do_train \
--do_eval \
--per_device_train_batch_size 12 \
--learning_rate 3e-5 \
--num_train_epochs 2 \
--max_seq_length 384 \
--doc_stride 128 \
--output_dir /tmp/debug_squad/ \
--no_cuda \
--ddp_backend ccl \
--use_ipex
Kubernetes
使用 CPU 的分布式训练也可以使用 PyTorchJob 部署到 Kubernetes 集群。在开始之前,您应该执行以下设置步骤。
- 确保您可以访问已安装 Kubeflow 的 Kubernetes 集群。
- 安装和配置 kubectl 以与集群交互。
- 设置 PersistentVolumeClaim (PVC) 以存储数据集和模型文件。有多种选项可供选择,包括 StorageClass 或云存储桶。
- 为训练脚本和所有必需的依赖项(例如 PyTorch、Transformers、IPEX、oneCCL 和 OpenSSH)设置 Docker 容器,以方便容器之间的通信。
下面的 Dockerfile 示例使用支持使用 CPU 进行分布式训练的基础镜像,并将 Transformers 提取到 /workspace
目录中,以将训练脚本包含在镜像中。镜像需要构建并复制到集群节点或推送到容器注册表,然后再进行部署。
FROM intel/intel-optimized-pytorch:2.4.0-pip-multinode
RUN apt-get update -y && \
apt-get install -y --no-install-recommends --fix-missing \
google-perftools \
libomp-dev
WORKDIR /workspace
# Download and extract the transformers code
ARG HF_TRANSFORMERS_VER="4.46.0"
RUN pip install --no-cache-dir \
transformers==${HF_TRANSFORMERS_VER} && \
mkdir transformers && \
curl -sSL --retry 5 https://github.com/huggingface/transformers/archive/refs/tags/v${HF_TRANSFORMERS_VER}.tar.gz | tar -C transformers --strip-components=1 -xzf -
PyTorchJob
PyTorchJob 是 Kubernetes API 的扩展,用于在 Kubernetes 上运行 PyTorch 训练作业。它包含一个 yaml 文件,用于定义训练作业的参数,例如 PyTorchJob 的名称、worker 的数量、每个 worker 的资源类型等等。
volumeMount 参数是 PVC 在每个 worker pod 的容器中挂载的路径。 PVC 通常用于在训练完成后保存数据集、检查点文件和模型。
下面的 yaml 文件示例在 run_qa.py 脚本上设置了四个 worker。根据您的训练脚本和集群中的节点数调整 yaml 文件。
CPU 资源限制和请求在 CPU 单位中定义。一个 CPU 单位相当于一个物理 CPU 核心或虚拟核心。yaml 文件中定义的 CPU 单位应小于单台机器的可用 CPU 和内存容量,以便为 kubelet 和系统留出一些资源。对于 Guaranteed
服务质量,请为资源限制和请求设置相同的 CPU 和内存量。
apiVersion: "kubeflow.org/v1"
kind: PyTorchJob
metadata:
name: transformers-pytorchjob
spec:
elasticPolicy:
rdzvBackend: c10d
minReplicas: 1
maxReplicas: 4
maxRestarts: 10
pytorchReplicaSpecs:
Worker:
replicas: 4 # The number of worker pods
restartPolicy: OnFailure
template:
spec:
containers:
- name: pytorch
image: <image name>:<tag> # Specify the docker image to use for the worker pods
imagePullPolicy: IfNotPresent
command: ["/bin/bash", "-c"]
args:
- >-
cd /workspace/transformers;
pip install -r /workspace/transformers/examples/pytorch/question-answering/requirements.txt;
source /usr/local/lib/python3.10/dist-packages/oneccl_bindings_for_pytorch/env/setvars.sh;
torchrun /workspace/transformers/examples/pytorch/question-answering/run_qa.py \
--model_name_or_path distilbert/distilbert-base-uncased \
--dataset_name squad \
--do_train \
--do_eval \
--per_device_train_batch_size 12 \
--learning_rate 3e-5 \
--num_train_epochs 2 \
--max_seq_length 384 \
--doc_stride 128 \
--output_dir /tmp/pvc-mount/output_$(date +%Y%m%d_%H%M%S) \
--no_cuda \
--ddp_backend ccl \
--bf16 \
--use_ipex;
env:
- name: LD_PRELOAD
value: "/usr/lib/x86_64-linux-gnu/libtcmalloc.so.4.5.9:/usr/local/lib/libiomp5.so"
- name: TRANSFORMERS_CACHE
value: "/tmp/pvc-mount/transformers_cache"
- name: HF_DATASETS_CACHE
value: "/tmp/pvc-mount/hf_datasets_cache"
- name: LOGLEVEL
value: "INFO"
- name: CCL_WORKER_COUNT
value: "1"
- name: OMP_NUM_THREADS # Can be tuned for optimal performance
value: "240"
resources:
limits:
cpu: 240 # Update the CPU and memory limit values based on your nodes
memory: 128Gi
requests:
cpu: 240 # Update the CPU and memory request values based on your nodes
memory: 128Gi
volumeMounts:
- name: pvc-volume
mountPath: /tmp/pvc-mount
- mountPath: /dev/shm
name: dshm
restartPolicy: Never
nodeSelector: # Optionally use nodeSelector to match a certain node label for the worker pods
node-type: gnr
volumes:
- name: pvc-volume
persistentVolumeClaim:
claimName: transformers-pvc
- name: dshm
emptyDir:
medium: Memory
部署
在您使用适合您的集群和训练作业的设置设置 PyTorchJob yaml 文件后,使用以下命令将其部署到集群。
export NAMESPACE=<specify your namespace>
kubectl create -f pytorchjob.yaml -n ${NAMESPACE}
使用 kubectl get pods -n ${NAMESPACE}
列出命名空间中的 pod。最初,状态可能是“Pending”,但一旦容器被拉取和创建,它应该会变为“Running”。
kubectl get pods -n ${NAMESPACE}
NAME READY STATUS RESTARTS AGE
...
transformers-pytorchjob-worker-0 1/1 Running 0 7m37s
transformers-pytorchjob-worker-1 1/1 Running 0 7m37s
transformers-pytorchjob-worker-2 1/1 Running 0 7m37s
transformers-pytorchjob-worker-3 1/1 Running 0 7m37s
...
使用以下命令检查每个 worker 的日志。添加 -f
以流式传输日志。
kubectl logs transformers-pytorchjob-worker-0 -n ${NAMESPACE} -f
训练完成后,可以从 PVC 或存储位置复制训练好的模型。使用以下命令从集群中删除 PyTorchJob 资源。
kubectl delete -f pytorchjob.yaml -n ${NAMESPACE}