- patch_ops.sh: call cccl_preload/build_cccl_preload.sh (new CCCL deps) instead of old build_cccl_preload_allocator.sh (mock) - computility-run.yaml: add LD_PRELOAD + CCCL_ALLOC_DISABLE env vars - Remove old mock files: cccl_preload_allocator.cu, build script, test - .dockerignore: exclude cccl_upstream/ upstream_ref/ vllm/ *.zip - verify_submission.sh: 31-point pre-submission check (file structure, CCCL chain, path matching, prebuilt integrity, corex imports, docker context, GPU smoke test)
236 lines
8.1 KiB
Bash
Executable File
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 -o '/workspace/[^ ]*' | head -1)
|
|
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
|