บทความนี้อธิบายความหมายและการทำงานเบื้องต้นของ NCCL (NVIDIA Collective Communications Library) เพื่อเพิ่มประสิทธิภาพการสื่อสารระหว่าง GPU พร้อมทั้งนำเสนอผลการทดลองของการตั้งค่า parameter เพื่อให้เข้าใจและเป็นแนวทางในการนำไปใช้งาน
...
ในการทดสอบ เราได้ทำการทดสอบ parameter 2 ตัวได้แก่ NCCL_SOCKET_NTHREADS
และ NCCL_NSOCKS_PERTHREAD
NCCL_SOCKET_NTHREADS
NCCL_SOCKET_NTHREADS
คือจำนวนการใช้งาน thread ของ CPU ที่จะใช้สำหรับเปิดการเชื่อมต่อระหว่าง node ผ่าน network socket
NCCL_NSOCKS_PERTHREAD
NCCL_NSOCKS_PERTHREAD
คือจำนวน network socket ที่ถูกใช้สำหรับแต่ละ thread ของ CPU
Info |
---|
ตัวอย่างการตั้งค่า ตัวอย่างเช่น หากกำหนด และตั้งค่า ดังนั้นจะใช้ทั้งสิ้น 16 network socket Network Socket [1] สำหรับเครื่อง LANTA ที่ปิด Hyper-threading ไว้ การระบุจำนวน thread จะเทียบเท่ากับการใช้งาน CPU core |
Panel | ||||||
---|---|---|---|---|---|---|
| ||||||
ผลคูณของ โดยที่ผลคูณของ |
โดย parameter 2 ตัวนี้ จะใช้ทรัพยากรส่วนหนึ่งของ CPU ในการสื่อสารกันระหว่าง GPU/node ซึ่งในการประมวลผล main task จะต้องใช้ทรัพยากรของ CPU เช่นกันจึงต้อง balance เพื่อหาค่า parameter ที่เหมาะสม
ผลลัพธ์ของการทดสอบ
...
ผลลัพธ์จากการทดสอบ
เราได้ทดลอง Train Model Llama2-13b ทดสอบโดยใช้ dataset โดยใช้ Dataset alpaca (52k)ที่ เป็นชุดข้อมูล
ใช้ 32 node เทรนจำนวน 1 epoch และจำนวน 32 node และใช้ และ Deepspeed - ZeRO stage Stage 3 ได้ผลลัพธ์ดังนี้
NCCL_SOCKET_NTHREADS | NCCL_NSOCKS_PERTHREAD | Testing Rounds | Average time (sec) | Standard Deviation |
8 | 2 | 4 | 307.91 | 3.21 |
16 | 2 | 4 | 309.88 | 7.19 |
8 | 4 | 4 | 311.61 | 2.29 |
16 | 4 | 4 | 313.36 | 0.98 |
4 | 4 | 4 | 316.64 | 3.39 |
8 | 8 | 4 | 321.70 | 3.98 |
4 | 8 | 1 | 321.78 | N/A |
2 | 2 | 4 | 323.78 | 2.90 |
2 | 8 | 1 | 326.43 | N/A |
2 | 16 | 1 | 348.85 | N/A |
1 | 1 | 4 | 373.15 | 6.39 |
หมายเหตุ: ในการทดสอบโดยใช้ model หรือ dataset อื่นอาจได้ผลลัพธ์ที่แตกต่างไป
ตัวอย่างการตั้งค่า NCCL
...
Parameters
ในตัวอย่างนี้ เป็นการตั้งค่า NCCL parameters โดยใช้ NCCL_SOCKET_NTHREADS=8
และ NCCL_NSOCKS_PERTHREAD=2
โดยสามารถดูรายละเอียดได้จากไฟล์ต่อไปนี้
...
Code Block | ||
---|---|---|
| ||
#!/bin/bash #SBATCH -p gpu # Specify partition [Compute/Memory/GPU] #SBATCH -c 64 # Specify number of processors per task #SBATCH --ntasks-per-node=1 # Specify number of tasks per node #SBATCH --gpus-per-node=4 # Specify total number of GPUs #SBATCH -t 1:00:00 # Specify maximum time limit (hour: minute: second) #SBATCH -A xxyyyyyy # Specify project name #SBATCH -J nccl-test # Specify job name #SBATCH -o ./logs/finetune-%j.out # Specify output file module restore module load Mamba module load PrgEnv-gnu module load cpe-cuda/23.03 module load cudatoolkit/23.3_11.8 : "${NTHREADS:=8}" : "${PTHREADS:=2}" : "${BATCH_SIZE:=4}" : "${DEEPSPEED_STAGE:=23}" : "${MODEL_SIZE:=7b}" : "${TASK:=finetune}" : "${RUN_WITH:=conda}" : "${ENV_PATH:=}" : "${SCALING_TYPE:=}" : "${WO_LORA:=NO}" if [ "$PROJ_PATH" == "" ]; then echo "PROJ_PATH is not set, please export the path to the project directory" exit 1 fi if [ "$SHARED_PATH" == "" ]; then echo "SHARED_PATH is not set, please export the path to the shared directory" exit 1 fi if [ "$CACHE_PATH" == "" ]; then echo "CACHE_PATH is not set, please export the path to the cache directory" exit 1 fi if [ "$ENV_PATH" == "" ]; then echo "ENV_PATH is not set, please export the path to the environment" exit 1 fi conda deactivate conda activate $ENV_PATH export WANDB_MODE="offline" export HOSTNAMES=$(scontrol show hostnames "$SLURM_JOB_NODELIST") export MASTER_ADDR=$(scontrol show hostnames "$SLURM_JOB_NODELIST" | head -n 1) export MASTER_PORT=12802 export COUNT_NODE=$(scontrol show hostnames "$SLURM_JOB_NODELIST" | wc -l) LOG_DIR="./logs/${NTHREADS}nth-${PTHREADS}pth-${SLURM_JOB_ID}" mkdir -p $LOG_DIR/node_log export LOG_DIR=$LOG_DIR export NCCL_TIMEOUT=3600000 export NCCL_DEBUG=DEBUG export NCCL_SOCKET_IFNAME=hsn export NCCL_SOCKET_NTHREADS=$NTHREADS export NCCL_NSOCKS_PERTHREAD=$PTHREADS export NCCL_DEBUG_FILE=${LOG_DIR}/nccl-${SLURM_JOB_ID}.log export NCCL_TOPO_DUMP_FILE=${LOG_DIR}/nccl-topo-${SLURM_JOB_ID}.log export BATCH_SIZE=$BATCH_SIZE export DEEPSPEED_STAGE=$DEEPSPEED_STAGE export MODEL_SIZE=$MODEL_SIZE export TORCH_NCCL_BLOCKING_WAIT=0 export TORCH_EXTENSIONS_DIR=$CACHE_PATH export HF_HUB_CACHE="$CACHE_PATH/huggingface" export HF_HOME="$CACHE_PATH/huggingface" export HF_DATASETS_CACHE="$CACHE_PATH/huggingface" export TORCH_HOME=$CACHE_PATH export XDG_CACHE_HOME=$CACHE_PATH export HF_DATASETS_OFFLINE=1 export HF_HUB_OFFLINE=1 echo -------ENVIRONMENT------- echo Python Path: $(which python) echo Batch Size: $BATCH_SIZE echo Deepspeed Stage: $DEEPSPEED_STAGE echo Model Size: $MODEL_SIZE echo Train with LoRA: $WO_LORA echo ------------------------- echo NTHREADS: $NTHREADS echo PTHREADS: $PTHREADS echo NODES: $COUNT_NODE echo HOSTNAMES: $HOSTNAMES echo MASTER_ADDR: $MASTER_ADDR echo MASTER_PORT: $MASTER_PORT echo ------------------------- srun --output=${LOG_DIR}/node_log/node-%t.out sh submit-node.sh |
...
Note |
---|
ในการปรับตัวแปร NCCL ควรระวังการตั้งค่าที่สูงเกินไป อาจส่งผลให้ระบบนั้นใช้ทรัพยากร CPU และ RAM มากเกินความจำเป็น และเกิดการแย่งทรัพยากรกับกระบวนการอื่นๆ ใน Task หลัก เช่น
|
...