Versions Compared

Key

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

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

Table of Contents
minLevel1
maxLevel63
include
outlinefalse
indent
styledefault
exclude
typelist
class
printabletrue

ภาพรวมของ NCCL

...

Panel
panelIconIdatlassian-warning
panelIcon:warning:
bgColor#FFFAE6

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

โดย parameter 2 ตัวนี้ จะใช้ทรัพยากรส่วนหนึ่งของ CPU ในการสื่อสารกันระหว่าง GPU/node ซึ่งในการประมวลผล main task จะต้องใช้ทรัพยากรของ CPU เช่นกันจึงต้อง balance เพื่อหาค่า parameter ที่เหมาะสม

...

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:=2}"
: "${MODEL_SIZE:=7b}"
: "${TASK:=finetune}"
: "${RUN_WITH:=conda}"
: "${ENV_PATH:=}"
: "${SCALING_TYPE:=}"
: "${WO_LORA:=NO}"

whileif [[ "$#$PROJ_PATH" -gt 0 ]== "" ]; dothen
    case $1 in
    --nthreads)
    echo "PROJ_PATH is not set, please export the path to the project directory"
   NTHREADS="$2" exit 1
fi
if [ "$SHARED_PATH" == "" shift]; 2then
    echo "SHARED_PATH is not ;;set, please export the path --pthreads)to the shared directory"
    exit PTHREADS="$2"1
fi
if [      shift 2"$CACHE_PATH" == "" ]; then
    echo "CACHE_PATH is not set, please export the ;;path to the cache  --batch_size)directory"
    exit 1
fi
if [ BATCH_SIZE="$2"
 "$ENV_PATH" == "" ]; then
    echo "ENV_PATH shiftis 2not set, please export the path to the environment"
 ;;   exit  --deepspeed_stage)1
fi

conda deactivate
conda activate $ENV_PATH

export DEEPSPEEDWANDB_STAGEMODE="$2offline"
export HOSTNAMES=$(scontrol show      shift 2
        ;;
    --model_size)
        MODEL_SIZE="$2"
        shift 2
        ;;
    --task)
        TASK="$2"
        shift 2
        ;;
    --run_with)
        RUN_WITH="$2"
        shift 2
        ;;
    --env_path)
        ENV_PATH="$2"
        shift 2
        ;;
    --scaling_type)
        SCALING_TYPE="$2"
        shift 2
        ;;
    --wo_lora)
        WO_LORA="$2"
        shift 2
        ;;
    *)
        echo "Unknown parameter passed: $1"
        exit 1
        ;;
    esac
done

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)

if [ "$TASK" == "nccl" ]; then
    LOG_DIR="./logs/${NTHREADS}nth-${PTHREADS}pth-${SLURM_JOB_ID}" # for nccl testing
elif [ "$TASK" == "scaling" ]; then
    folstru=""
    if [ "$WO_LORA" == "YES" ]; then
        folstru="/wo-lora"
    fi
    if [ "$SCALING_TYPE" != "" ]; then
        LOG_DIR="../scaling$folstru/${SCALING_TYPE}/stage-${DEEPSPEED_STAGE}/llama-${MODEL_SIZE}/${COUNT_NODE}n-${BATCH_SIZE}b-${SLURM_JOB_ID}"
    else 
        LOG_DIR="../scaling/stage-${DEEPSPEED_STAGE}/llama-${MODEL_SIZE}/${COUNT_NODE}n-${BATCH_SIZE}b-${SLURM_JOB_ID}" 
    fi
else 
    LOG_DIR="./logs/${COUNT_NODE}n-${BATCH_SIZE}b-${SLURM_JOB_ID}"
fi

if [ "$WO_LORA" == "YES" ]; then
    export filename="train_wo_lora.py"
else
    export filename="train.py"
fi

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-${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

...

Code Block
languagebash
#!/bin/bash

echo "------INFO--------"
echo node_number: $SLURM_PROCID
echo hostname: $(hostname)
echo "------------------"
echo ""

echo "----LAUNCHING TRAINING----"

accelerate launch \
    --num_processes $((4 * $COUNT_NODE)) \
    --num_machines $COUNT_NODE \
    --multi_gpu \
    --mixed_precision bf16 \
    --machine_rank $SLURM_PROCID \
    --main_process_ip $MASTER_ADDR \
    --main_process_port $MASTER_PORT \
    --dynamo_backend inductor \
    $PROJ_PATH/scripts/$filenametrain_wo_lora.py \
        --pretrained_model_name_or_path "meta-llama/Llama-2-$MODEL_SIZE-chat-hf" \
        --train_file $SHARED_PATH/datasets/alpaca_json/alpaca_all.json \
        --validation_file $SHARED_PATH/datasets/alpaca_json/alpaca_validation.json \
        --seed 42 \
        --max_seq_length 1300 \
        --output_dir $PROJ_PATH/checkpoint \
        --num_train_epochs 1 \
        --per_device_train_batch_size $BATCH_SIZE \
        --per_device_eval_batch_size $BATCH_SIZE \
        --save_steps 700 \
        --save_total_limit 5 \
        --learning_rate 8e-5 \
        --weight_decay 0.01 \
        --warmup_ratio 0.05 \
        --lr_scheduler_type cosine \
        --gradient_accumulation_steps 1 \
        --deepspeed "$PROJ_PATH/deepspeed_config/deepspeed_$DEEPSPEED_STAGE.json" \
        --gradient_checkpointing True \
        --tf32 True \
        --bf16 True \
        --max_grad_norm 1.0 \
        --logging_steps 10 \
        --dataloader_num_workers 16 \
        --ddp_find_unused_parameters False \
        --log_dir $LOG_DIR \
        --node_number $SLURM_PROCID

...

ข้อควรระวังในการปรับค่า Parameters

Note

ในการปรับ ในการปรับตัวแปร NCCL parameters ควรระวังการตั้งค่าที่สูงเกินไปอาจทำให้ระบบใช้ทรัพยากร ควรระวังการตั้งค่าที่สูงเกินไป อาจส่งผลให้ระบบนั้นใช้ทรัพยากร CPU และ RAM มากเกินความจำเป็น อาจส่งผลให้เกิดการแย่งทรัพยากรกับกระบวนการอื่นๆ และเกิดการแย่งทรัพยากรกับกระบวนการอื่นๆ ใน main task Task หลัก เช่น

  • การ load data

, การปรับ weight, การ evaluate รวมถึงอาจเกิด overhead ในการจัดการ threads และ sockets ที่มากเกินไป

แหล่งอ้างอิง

...

  • การปรับ weight

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

แหล่งอ้างอิง