Accelerating PyTorch Transformers with Intel Sapphire Rapids – part 1
TL;DR
Hugging Face demonstrates that training PyTorch Transformers on a four‑node cluster of Intel Sapphire Rapids CPUs with the Intel Extension for PyTorch (IPEX) and oneCCL yields an 8× speed‑up over comparable Ice Lake instances and scales almost linearly, making CPU‑based training a cost‑effective alternative to GPUs.
Why Train on CPUs?
Training on Intel Xeon CPUs can be cheaper and more scalable than GPU‑based training, especially for small‑ to medium‑sized models and datasets. Xeon CPUs provide AVX‑512, Hyper‑Threading, and now Advanced Matrix Extensions (AMX), which accelerate matrix multiplication. CPUs are widely available, can be repurposed for other workloads, and cloud spot instances can reduce costs by up to 90% compared to on‑demand instances.
Advanced Matrix Extensions (AMX)
Sapphire Rapids introduces AMX, a set of new instructions that speed up matrix multiplication—the core operation in deep‑learning training. AMX supports BF16 and INT8 data types and adds 2‑dimensional tile registers. To use AMX, the Linux kernel must be version 5.16 or newer; however, Intel and AWS have back‑ported the required support to kernel 5.15 on the bare‑metal r7iz.metal-16xl instances used in this guide.
Building a Sapphire Rapids Cluster on AWS
The simplest way to access Sapphire Rapids hardware is via the Amazon EC2 R7iz bare‑metal instances (e.g., r7iz.metal-16xl). Because the preview does not yet support AMX in virtual machines, the guide uses bare‑metal instances with 64 vCPUs and 512 GB RAM.
Network Setup
- Open SSH (port 22) on all nodes.
- Configure password‑less SSH from the master node to every node, including the master itself.
- Create a security group that allows unrestricted intra‑cluster traffic and attach it to all instances.
Setting Up the Master Node
- Launch an
r7iz.metal-16xlinstance with Ubuntu 20.04 AMIami-07cd3e6c4915b2d18. - Verify AMX support with
lscpu(flagsamx_bf16 amx_tile amx_int8). - Install dependencies:
sudo apt-get update sudo apt install libgoogle-perftools-dev -y sudo apt-get install python3-pip -y pip install --upgrade pip pip install virtualenv virtualenv cluster_env source cluster_env/bin/activate pip install torch==1.13.0 -f https://download.pytorch.org/whl/cpu pip install intel_extension_for_pytorch==1.13.0 -f https://developer.intel.com/ipex-whl-stable-cpu pip install -f https://developer.intel.com/ipex-whl-stable-cpu pip install transformers==4.24.0 git clone https://github.com/huggingface/transformers.git cd transformers && git checkout v4.24.0 - Generate an SSH key pair (
ssh-keygen) and store it as~/.ssh/cluster. - Create an AMI from this configured instance for reuse.
Setting Up the Remaining Nodes
- Launch three additional
r7iz.metal-16xlinstances using the AMI created above. - On the master, edit
~/.ssh/configto define hostsnode1,node2, andnode3with their private IPs and theclusterkey. - Verify password‑less access with
ssh node[1-3]. - Create a
~/hostsfile listing all nodes, includinglocalhostfor the master:localhost node1 node2 node3
Launching Distributed Training
The example fine‑tunes DistilBERT on the SQuAD dataset.
Single‑Node Baseline
source ~/cluster_env/bin/activate
cd ~/transformers/examples/pytorch/question-answering
pip install -r requirements.txt
export LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc.so"
python run_qa.py \
--model_name_or_path distilbert-base-uncased \
--dataset_name squad \
--do_train --do_eval \
--per_device_train_batch_size 32 \
--num_train_epochs 1 \
--output_dir /tmp/debug_squad/ \
--use_ipex --bf16 --no_cuda
A single epoch completed in ≈26 minutes, compared with ≈3 h 30 min on an Ice Lake c6i.16xlarge instance—a 8× speed‑up.
Distributed Run on Four Nodes
Environment variables for oneCCL and thread placement:
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
export MASTER_ADDR=172.31.3.190
export NUM_PROCESSES=8 # 2 processes per node × 4 nodes
export NUM_PROCESSES_PER_NODE=2
export CCL_WORKER_COUNT=2
export CCL_WORKER_AFFINITY=auto
export KMP_HW_SUBSET=1T
export OMP_NUM_THREADS=24 # training threads per process
Launch with mpirun:
mpirun -f ~/hosts \
-n $NUM_PROCESSES -ppn $NUM_PROCESSES_PER_NODE \
-genv OMP_NUM_THREADS=24 \
-genv LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc.so" \
python3 run_qa.py \
--model_name_or_path distilbert-base-uncased \
--dataset_name squad \
--do_train --do_eval \
--per_device_train_batch_size 32 \
--num_train_epochs 1 \
--output_dir /tmp/debug_squad/ \
--overwrite_output_dir \
--no_cuda \
--xpu_backend ccl \
--bf16
The epoch time dropped to 7 min 30 s, only 1 minute above the ideal linear scaling target of 6 min 30 s (26 min / 4). The screenshot in the original post shows two training processes per node and the master process orchestrating the run.
Implications and Takeaways
- Cost Efficiency – CPU spot instances can be dramatically cheaper than GPU instances while delivering comparable training speed for many workloads.
- Scalability – Near‑linear scaling across four Sapphire Rapids nodes demonstrates that the combination of IPEX and oneCCL effectively distributes both compute and communication.
- Ease of Use – No code changes are required; enabling
--use_ipexand--bf16activates the new AMX instructions automatically. - Future Work – The authors plan a follow‑up post covering inference performance on Sapphire Rapids, which will complete the picture of end‑to‑end CPU acceleration.
Further Resources
- Intel Extension for PyTorch (IPEX): https://github.com/intel/intel-extension-for-pytorch
- Hugging Face CPU training guides:
- Efficient training on CPU – https://huggingface.co/docs/transformers/perf_train_cpu
- Efficient training on many CPUs – https://huggingface.co/docs/transformers/perf_train_cpu_many
- Discussion forum: https://discuss.huggingface.co/