Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

บทความนี้อธิบายความหมายและการทำงานเบื้องต้นของ NCCL (NVIDIA Collective Communications Library) เพื่อเพิ่มประสิทธิภาพการสื่อสารระหว่าง GPU พร้อมทั้งนำเสนอผลการทดลองของการตั้งค่า parameter เพื่อให้เข้าใจและเป็นแนวทางในการนำไปใช้งาน

...

ในการทดสอบ เราได้ทำการทดสอบ parameter 2 ตัวได้แก่ NCCL_SOCKET_NTHREADS และ NCCL_NSOCKS_PERTHREAD

  1. NCCL_SOCKET_NTHREADS

NCCL_SOCKET_NTHREADS คือจำนวนการใช้งาน thread ของ CPU ที่จะใช้สำหรับเปิดการเชื่อมต่อระหว่าง node ผ่าน network socket

  1. NCCL_NSOCKS_PERTHREAD

NCCL_NSOCKS_PERTHREAD คือจำนวน network socket ที่ถูกใช้สำหรับแต่ละ thread ของ CPU

Info

ตัวอย่างการตั้งค่า

ตัวอย่างเช่น หากกำหนด NCCL_SOCKET_NTHREADS เป็น 8 ; CPU จะใช้งาน CPU 8 thread (สำหรับเครื่อง LANTA ที่ปิด Hyper-threading ไว้ การระบุจำนวน thread จะเทียบเท่ากับการใช้งาน CPU core) และเมื่อตั้งค่า 8 Threads[1]

และตั้งค่า NCCL_NSOCKS_PERTHREAD เป็น 2 แต่ละ thread จะ 2 network socket ; แต่ละ Thread จะใช้ Network Socket 2 ตัว ในการสื่อสาร

ดังนั้นจะใช้ทั้งสิ้น 16 network socket Network Socket

[1] สำหรับเครื่อง LANTA ที่ปิด Hyper-threading ไว้ การระบุจำนวน thread จะเทียบเท่ากับการใช้งาน CPU core
Panel
panelIconIdatlassian-warning
panelIcon:warning:
bgColor#FFFAE6

ผลคูณของ โดยที่ผลคูณของ NCCL_SOCKET_NTHREADS และ NCCL_NSOCKS_PERTHREAD จะต้องไม่เกิน 64.

โดย 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
languagebash
#!/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 หลัก เช่น

  • การ load data

  • การปรับ weight

  • การ evaluate อาจเกิด เกิด overhead ในการจัดการ threads และ sockets ที่มากเกินไป

...