Files
project_6/verify_submission.sh

236 lines
8.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# verify_submission.sh — 竞赛提交前的完整验证
#
# 在真机上运行:
# cd /home/dylan/project_6
# bash verify_submission.sh
#
# 检查项:
# 1. Dockerfile语法
# 2. patch_ops.sh可执行 + 引用的文件全部存在
# 3. CCCL preload编译链完整(头文件+源文件+build脚本)
# 4. computility-run.yaml路径与build输出匹配
# 5. prebuilt .so文件完整性(SHA256)
# 6. qwen3_5.py imports的corex模块全部有对应.so或build脚本
# 7. Docker context大小(不要超过平台限制)
# 8. 单卡冒烟测试(如果有GPU)
PASS=0
FAIL=0
WARN=0
check() {
local name=$1; shift
if "$@" >/dev/null 2>&1; then
echo "$name"
PASS=$((PASS+1))
else
echo "$name"
FAIL=$((FAIL+1))
fi
}
warn() {
echo "$1"
WARN=$((WARN+1))
}
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$ROOT"
echo "=== 1. 文件结构 ==="
check "Dockerfile存在" test -f Dockerfile
check "computility-run.yaml存在" test -f computility-run.yaml
check "patch_ops.sh存在" test -f qwen3_6_scripts/patch_ops.sh
check "patch_ops.sh可执行" test -x qwen3_6_scripts/patch_ops.sh
check ".dockerignore存在" test -f .dockerignore
echo ""
echo "=== 2. CCCL Preload编译链 ==="
check "build脚本存在" test -f qwen3_6_scripts/cccl_preload/build_cccl_preload.sh
check "源文件存在" test -f qwen3_6_scripts/cccl_preload/cccl_allocator_preload.cu
check "CCCL头文件目录存在" test -d qwen3_6_scripts/cccl_preload/include/cub
check "libcudacxx头文件存在" test -d qwen3_6_scripts/cccl_preload/include/cuda
CCCL_HEADERS=$(find qwen3_6_scripts/cccl_preload/include -type f 2>/dev/null | wc -l)
if [[ "$CCCL_HEADERS" -ge 280 ]]; then
echo " ✓ CCCL头文件数量: $CCCL_HEADERS (≥280)"
PASS=$((PASS+1))
else
echo " ✗ CCCL头文件数量: $CCCL_HEADERS (期望≥280)"
FAIL=$((FAIL+1))
fi
# 检查关键头文件
check "cub/util_allocator.cuh" test -f qwen3_6_scripts/cccl_preload/include/cub/util_allocator.cuh
check "cub/config.cuh" test -f qwen3_6_scripts/cccl_preload/include/cub/config.cuh
check "cuda/__cccl_config" test -f qwen3_6_scripts/cccl_preload/include/cuda/__cccl_config
check "nv/target" test -f qwen3_6_scripts/cccl_preload/include/nv/target
echo ""
echo "=== 3. patch_ops.sh → CCCL preload 调用链 ==="
if grep -q "cccl_preload/build_cccl_preload.sh" qwen3_6_scripts/patch_ops.sh; then
echo " ✓ patch_ops.sh调用新版build脚本"
PASS=$((PASS+1))
else
echo " ✗ patch_ops.sh未调用cccl_preload/build_cccl_preload.sh"
FAIL=$((FAIL+1))
fi
# 检查旧文件是否残留
if [[ -f qwen3_6_scripts/cccl_preload_allocator.cu ]]; then
echo " ✗ 旧mock文件残留: cccl_preload_allocator.cu"
FAIL=$((FAIL+1))
else
echo " ✓ 旧mock文件已清理"
PASS=$((PASS+1))
fi
echo ""
echo "=== 4. computility-run.yaml 路径匹配 ==="
YAML_PRELOAD=$(grep -A1 "LD_PRELOAD" computility-run.yaml | grep "value:" | awk '{print $2}')
if [[ -n "$YAML_PRELOAD" ]]; then
echo " ✓ LD_PRELOAD已配置: $YAML_PRELOAD"
PASS=$((PASS+1))
# 检查路径与build输出一致
BUILD_OUTPUT_DIR=$(grep "build_cccl_preload.sh" qwen3_6_scripts/patch_ops.sh | grep -oP '/workspace/\S+' | head -1 | tr -d ';')
EXPECTED_SO="${BUILD_OUTPUT_DIR}/libcccl_allocator.so"
if [[ "$YAML_PRELOAD" == "$EXPECTED_SO" || "$YAML_PRELOAD" == "/workspace/qwen3_6_scripts/libcccl_allocator.so" ]]; then
echo " ✓ 路径匹配build输出"
PASS=$((PASS+1))
else
echo " ✗ 路径不匹配: yaml=$YAML_PRELOAD expected=$EXPECTED_SO"
FAIL=$((FAIL+1))
fi
else
echo " ✗ computility-run.yaml缺少LD_PRELOAD"
FAIL=$((FAIL+1))
fi
# 检查CCCL_ALLOC_DISABLE
if grep -q "CCCL_ALLOC_DISABLE" computility-run.yaml; then
echo " ✓ CCCL_ALLOC_DISABLE可控"
PASS=$((PASS+1))
fi
echo ""
echo "=== 5. Prebuilt .so 完整性 ==="
PREBUILT_DIR="qwen3_6_scripts/prebuilt/corex-3.2.3-ivcore10"
if [[ -f "${PREBUILT_DIR}/SHA256SUMS" ]]; then
EXPECTED=$(wc -l < "${PREBUILT_DIR}/SHA256SUMS")
ACTUAL=$(ls "${PREBUILT_DIR}"/*.so 2>/dev/null | wc -l)
if [[ "$ACTUAL" -ge "$EXPECTED" ]]; then
echo " ✓ prebuilt .so数量: $ACTUAL (manifest expects $EXPECTED)"
PASS=$((PASS+1))
else
echo " ✗ prebuilt .so数量不足: $ACTUAL < $EXPECTED"
FAIL=$((FAIL+1))
fi
# 如果有sha256sum工具, 验证checksum
if command -v sha256sum &>/dev/null; then
if (cd "$PREBUILT_DIR" && sha256sum --status --check SHA256SUMS 2>/dev/null); then
echo " ✓ SHA256校验通过"
PASS=$((PASS+1))
else
echo " ✗ SHA256校验失败"
FAIL=$((FAIL+1))
fi
fi
else
echo " △ SHA256SUMS不存在, 跳过校验"
WARN=$((WARN+1))
fi
echo ""
echo "=== 6. qwen3_5.py corex imports vs prebuilt ==="
IMPORTS=$(grep "from vllm import corex_" qwen3_6_scripts/qwen3_5.py 2>/dev/null | sed 's/.*import //' | sed 's/ as.*//' | sort -u)
for mod in $IMPORTS; do
SO_FILE="${PREBUILT_DIR}/${mod}.so"
BUILD_SCRIPT="qwen3_6_scripts/build_${mod}.sh"
if [[ -f "$SO_FILE" ]]; then
echo "$mod → prebuilt .so"
PASS=$((PASS+1))
elif [[ -f "$BUILD_SCRIPT" ]]; then
echo "$mod → build脚本存在 (docker内编译)"
WARN=$((WARN+1))
else
echo "$mod → 无.so也无build脚本"
FAIL=$((FAIL+1))
fi
done
echo ""
echo "=== 7. Docker context大小 ==="
# 排除.git和大文件
if [[ -f .dockerignore ]]; then
# 粗略估算
CONTEXT_SIZE=$(du -sh --exclude='.git' --exclude='cccl_upstream' --exclude='upstream_ref' --exclude='*.zip' --exclude='vllm' --exclude='ixformer_sdk' qwen3_6_scripts/ computility-run.yaml Dockerfile 2>/dev/null | tail -1 | awk '{print $1}')
echo " 核心文件大小: ~$CONTEXT_SIZE"
echo " (.dockerignore应排除cccl_upstream/, upstream_ref/, vllm/, *.zip等)"
fi
# 检查.dockerignore是否排除大目录
if [[ -f .dockerignore ]]; then
for dir in cccl_upstream upstream_ref vllm ixformer_sdk "*.zip"; do
if grep -q "$dir" .dockerignore 2>/dev/null; then
echo " ✓ .dockerignore排除: $dir"
else
warn ".dockerignore未排除: $dir (可能导致docker context过大)"
fi
done
fi
echo ""
echo "=== 8. 单卡冒烟测试 ==="
if command -v ixsmi &>/dev/null || command -v nvidia-smi &>/dev/null; then
echo " 检测到GPU, 运行基础验证..."
if python3 -c "import torch; assert torch.cuda.is_available(); print(f' ✓ PyTorch CUDA: {torch.cuda.get_device_name(0)}')" 2>/dev/null; then
PASS=$((PASS+1))
else
echo " ✗ PyTorch CUDA不可用"
FAIL=$((FAIL+1))
fi
# 测试CCCL preload编译
if [[ -f qwen3_6_scripts/cccl_preload/build_cccl_preload.sh ]]; then
echo " 尝试编译CCCL preload .so..."
if bash qwen3_6_scripts/cccl_preload/build_cccl_preload.sh /tmp 2>/dev/null; then
if [[ -s /tmp/libcccl_allocator.so ]]; then
echo " ✓ CCCL preload编译成功"
PASS=$((PASS+1))
# 测试加载
if LD_PRELOAD=/tmp/libcccl_allocator.so python3 -c "import torch; x=torch.zeros(1024,device='cuda'); del x; print(' ✓ LD_PRELOAD加载正常')" 2>/dev/null; then
PASS=$((PASS+1))
else
echo " ✗ LD_PRELOAD加载失败"
FAIL=$((FAIL+1))
fi
rm -f /tmp/libcccl_allocator.so
else
echo " ✗ 编译产物为空"
FAIL=$((FAIL+1))
fi
else
echo " ✗ CCCL preload编译失败"
FAIL=$((FAIL+1))
fi
fi
else
echo " (无GPU, 跳过)"
fi
echo ""
echo "==========================================="
echo " PASS: $PASS FAIL: $FAIL WARN: $WARN"
echo "==========================================="
if [[ "$FAIL" -gt 0 ]]; then
echo ""
echo "⚠ 有 $FAIL 个检查失败, 提交前请修复!"
exit 1
else
echo ""
echo "✓ 全部检查通过, 可以提交"
exit 0
fi