181 lines
5.8 KiB
Bash
181 lines
5.8 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Build a text-only Parquet dataset from a one-prompt-per-line file. The script
|
|
# shards prompts across GPU_NUM single-GPU torchrun workers, runs
|
|
# v1_preprocess.py with --preprocess_task text_only, and writes prompt
|
|
# embeddings/captions under OUTPUT_DIR for DMD2/DiffusionNFT text-only runs.
|
|
|
|
INPUT_FILE="${1:-train.txt}"
|
|
OUTPUT_DIR="${OUTPUT_DIR:-data/train_text_only_dmd_preprocessed}"
|
|
MODEL_PATH="${MODEL_PATH:-Wan-AI/Wan2.1-T2V-1.3B-Diffusers}"
|
|
GPU_NUM="${GPU_NUM:-2}"
|
|
BATCH_SIZE="${BATCH_SIZE:-1}"
|
|
SAMPLES_PER_FILE="${SAMPLES_PER_FILE:-8}"
|
|
FLUSH_FREQUENCY="${FLUSH_FREQUENCY:-8}"
|
|
TEXT_MAX_LENGTH="${TEXT_MAX_LENGTH:-512}"
|
|
CONDA_ROOT="${CONDA_ROOT:-/root/miniconda3}"
|
|
CONDA_ENV="${CONDA_ENV:-fastvideo}"
|
|
MIN_FREE_GPU_MB="${MIN_FREE_GPU_MB:-22000}"
|
|
|
|
if [[ ! -f "$INPUT_FILE" ]]; then
|
|
echo "Input text file not found: $INPUT_FILE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "$CONDA_ROOT/etc/profile.d/conda.sh" ]]; then
|
|
echo "Conda activation script not found under $CONDA_ROOT" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# shellcheck source=/dev/null
|
|
source "$CONDA_ROOT/etc/profile.d/conda.sh"
|
|
conda activate "$CONDA_ENV"
|
|
|
|
if [[ "${HF_HUB_ENABLE_HF_TRANSFER:-0}" == "1" ]]; then
|
|
if ! python -c "import hf_transfer" >/dev/null 2>&1; then
|
|
echo "HF_HUB_ENABLE_HF_TRANSFER=1 but hf_transfer is not installed; disabling fast transfer."
|
|
export HF_HUB_ENABLE_HF_TRANSFER=0
|
|
fi
|
|
else
|
|
export HF_HUB_ENABLE_HF_TRANSFER=0
|
|
fi
|
|
|
|
visible_gpus=$(nvidia-smi --query-gpu=index --format=csv,noheader 2>/dev/null | wc -l | tr -d ' ')
|
|
if [[ "$visible_gpus" -lt "$GPU_NUM" ]]; then
|
|
echo "Expected at least $GPU_NUM GPUs, found $visible_gpus" >&2
|
|
exit 1
|
|
fi
|
|
|
|
for gpu_id in $(seq 0 $((GPU_NUM - 1))); do
|
|
free_mb=$(nvidia-smi --id="$gpu_id" --query-gpu=memory.free --format=csv,noheader,nounits | tr -d ' ')
|
|
if [[ "$free_mb" -lt "$MIN_FREE_GPU_MB" ]]; then
|
|
echo "GPU $gpu_id has only ${free_mb} MiB free; text-only Wan preprocessing needs" \
|
|
"about ${MIN_FREE_GPU_MB} MiB." >&2
|
|
echo "Free the GPU or lower MIN_FREE_GPU_MB if you know this run will fit." >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
MARKER="$OUTPUT_DIR/.fastvideo_text_only_dmd_output"
|
|
if [[ -d "$OUTPUT_DIR" && ! -f "$MARKER" ]]; then
|
|
echo "Refusing to overwrite existing non-script output directory: $OUTPUT_DIR" >&2
|
|
echo "Set OUTPUT_DIR to a new path or remove the directory manually." >&2
|
|
exit 1
|
|
fi
|
|
|
|
rm -rf "$OUTPUT_DIR"
|
|
mkdir -p "$OUTPUT_DIR"
|
|
touch "$MARKER"
|
|
|
|
echo "Text-only DMD preprocessing config:"
|
|
echo " input: $INPUT_FILE"
|
|
echo " output: $OUTPUT_DIR"
|
|
echo " model: $MODEL_PATH"
|
|
echo " gpus: $GPU_NUM"
|
|
echo " batch size per GPU: $BATCH_SIZE"
|
|
echo " text max length: $TEXT_MAX_LENGTH"
|
|
echo " samples per parquet file: $SAMPLES_PER_FILE"
|
|
echo " flush frequency: $FLUSH_FREQUENCY"
|
|
|
|
SHARD_DIR="$OUTPUT_DIR/_text_shards"
|
|
mkdir -p "$SHARD_DIR"
|
|
|
|
python - "$INPUT_FILE" "$SHARD_DIR" "$GPU_NUM" <<'PY'
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
input_path = Path(sys.argv[1])
|
|
shard_dir = Path(sys.argv[2])
|
|
num_shards = int(sys.argv[3])
|
|
|
|
prompts = [line.rstrip("\n") for line in input_path.read_text(encoding="utf-8").splitlines() if line.strip()]
|
|
if not prompts:
|
|
raise SystemExit(f"No non-empty prompts found in {input_path}")
|
|
|
|
for shard_idx in range(num_shards):
|
|
shard_prompts = prompts[shard_idx::num_shards]
|
|
shard_path = shard_dir / f"train_text_shard_{shard_idx}.txt"
|
|
shard_path.write_text("\n".join(shard_prompts) + "\n", encoding="utf-8")
|
|
print(f"Wrote {len(shard_prompts)} prompts to {shard_path}")
|
|
PY
|
|
|
|
run_preprocess_worker() {
|
|
local gpu_id="$1"
|
|
local shard_file="$2"
|
|
local shard_output="$3"
|
|
local log_file="$4"
|
|
local master_port="$5"
|
|
local -a cmd=(
|
|
torchrun
|
|
--nnodes=1
|
|
--nproc_per_node=1
|
|
--master_port "$master_port"
|
|
fastvideo/pipelines/preprocess/v1_preprocess.py
|
|
--model_path "$MODEL_PATH"
|
|
--data_merge_path "$shard_file"
|
|
--preprocess_video_batch_size "$BATCH_SIZE"
|
|
--seed 42
|
|
--max_height 448
|
|
--max_width 832
|
|
--num_frames 77
|
|
--dataloader_num_workers 0
|
|
--output_dir "$shard_output"
|
|
--train_fps 16
|
|
--samples_per_file "$SAMPLES_PER_FILE"
|
|
--flush_frequency "$FLUSH_FREQUENCY"
|
|
--text_max_length "$TEXT_MAX_LENGTH"
|
|
--video_length_tolerance_range 5
|
|
--preprocess_task text_only
|
|
)
|
|
|
|
{
|
|
echo "[gpu${gpu_id}] log file: $log_file"
|
|
echo "[gpu${gpu_id}] command: CUDA_VISIBLE_DEVICES=${gpu_id} ${cmd[*]}"
|
|
} | tee "$log_file"
|
|
|
|
CUDA_VISIBLE_DEVICES="$gpu_id" "${cmd[@]}" 2>&1 \
|
|
| sed -u "s/^/[gpu${gpu_id}] /" \
|
|
| tee -a "$log_file"
|
|
local status=${PIPESTATUS[0]}
|
|
if [[ "$status" -ne 0 ]]; then
|
|
echo "[gpu${gpu_id}] preprocessing failed with exit code $status" | tee -a "$log_file"
|
|
fi
|
|
return "$status"
|
|
}
|
|
|
|
pids=()
|
|
for gpu_id in $(seq 0 $((GPU_NUM - 1))); do
|
|
shard_file="$SHARD_DIR/train_text_shard_${gpu_id}.txt"
|
|
shard_output="$OUTPUT_DIR/shard_${gpu_id}"
|
|
mkdir -p "$shard_output"
|
|
log_file="$OUTPUT_DIR/preprocess_gpu_${gpu_id}.log"
|
|
|
|
echo "Launching text-only preprocessing on GPU ${gpu_id}: ${shard_file}"
|
|
run_preprocess_worker "$gpu_id" "$shard_file" "$shard_output" "$log_file" "$((29610 + gpu_id))" &
|
|
pids+=("$!")
|
|
done
|
|
|
|
failed=0
|
|
for pid in "${pids[@]}"; do
|
|
if ! wait "$pid"; then
|
|
failed=1
|
|
fi
|
|
done
|
|
|
|
if [[ "$failed" -ne 0 ]]; then
|
|
echo "One or more preprocessing workers failed. Check logs under $OUTPUT_DIR." >&2
|
|
exit 1
|
|
fi
|
|
|
|
num_parquet=$(find "$OUTPUT_DIR" -name '*.parquet' | wc -l | tr -d ' ')
|
|
if [[ "$num_parquet" -eq 0 ]]; then
|
|
echo "No parquet files were produced under $OUTPUT_DIR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Text-only preprocessing complete."
|
|
echo "Parquet files: $num_parquet"
|
|
echo "Use this training data_path:"
|
|
echo "$OUTPUT_DIR"
|