Files
AICASGC/.ipynb_checkpoints/README_CN-checkpoint.md
2026-02-26 08:15:21 +00:00

13 KiB
Executable File
Raw Blame History

AICAS 2026 - 面向AI芯片的VLM高效推理与优化赛道

目录

概述

本次竞赛专注于优化视觉语言模型VLM的推理性能。参赛者需要修改 evaluation_wrapper.py 中的 VLMModel 类,在保持准确率的同时提升首 Token 时间TTFT和吞吐量Throughput

代码结构

AICASGC/
├── benchmark.py              # 基准测试脚本
├── evaluation_wrapper.py     # 模型包装器(选手在此实现优化)
├── requirements.txt          # Python 依赖包
├── data/                     # 验证数据集
│   ├── data-*.arrow          # 数据集文件
│   ├── dataset_info.json     # 数据集元信息
│   └── state.json            # 数据集状态
├── Qwen3-VL-2B-Instruct/    # 模型权重目录(需要选手自行下载)
└── README.md / README_CN.md   # 说明文档

核心文件

  • benchmark.py - 自测基准脚本(⚠️ 不建议修改
  • evaluation_wrapper.py - 模型包装器,参赛者在此实现优化
  • Qwen3-VL-2B-Instruct/ - 竞赛模型权重(需要选手自行下载,见"快速开始"部分)
  • data/ - 验证数据集
  • requirements.txt - Python 依赖包

快速开始

0. 下载模型(首次使用)

模型文件较大,需要单独下载。请先创建模型目录,然后下载模型:

# 创建模型目录
mkdir -p Qwen3-VL-2B-Instruct

# 安装 huggingface_hub如果未安装
pip install -U huggingface_hub

# 设置镜像源(国内用户推荐,加速下载)
export HF_ENDPOINT=https://hf-mirror.com

# 下载模型到指定目录
huggingface-cli download \
  --resume-download \
  Qwen/Qwen3-VL-2B-Instruct \
  --local-dir ./Qwen3-VL-2B-Instruct \
  --local-dir-use-symlinks False

注意:

  • 模型大小约 4-5GB下载可能需要一些时间
  • 如果下载中断,可以重新运行命令,会自动续传(--resume-download
  • 下载完成后,Qwen3-VL-2B-Instruct/ 文件夹会包含所有模型文件
  • 确保有足够的磁盘空间(至少 5GB

1. 安装依赖

pip install -r requirements.txt

2. 运行测试

python benchmark.py \
    --model-path ./Qwen3-VL-2B-Instruct \
    --dataset-path ./data \
    --output result.json \
    --num-samples 100

3. 实现你的优化

编辑 evaluation_wrapper.py 中的 VLMModel 类。优化采用模块化设计,每个优化方向对应一个独立方法。

3.1 探索模型结构(可选)

在开始优化前,可以先探索模型结构,了解优化目标:

class VLMModel:
    def __init__(self, model_path: str, device: str = "cuda:0"):
        # ... 加载模型 ...
        
        # 可选:探索模型结构
        self._explore_model_structure()  # 会打印模型结构信息

3.2 启用优化方法

__init__ 方法中,通过注释/取消注释来启用/禁用不同的优化:

class VLMModel:
    def __init__(self, model_path: str, device: str = "cuda:0"):
        # ... 加载模型 ...
        
        # ================================================================
        # 选手优化区域 - 启用/禁用优化方法
        # ================================================================
        
        # 1. Vision Encoder 加速(优化大分辨率图像处理)
        # self._optimize_vision_encoder()
        
        # 2. KV Cache 管理(优化生成过程中的内存碎片)
        # self._optimize_kv_cache()
        
        # 3. 跨模态融合层优化(优化 Cross-modal Connector
        # self._optimize_cross_modal_connector()
        
        # 4. Flash Attention 优化
        # self._enable_flash_attention()
        
        # 5. 量化优化
        # self._apply_quantization()

3.3 实现优化代码

在各个优化方法中实现你的优化逻辑。例如,优化 Vision Encoder

def _optimize_vision_encoder(self):
    """在 evaluation_wrapper.py 中找到这个方法,实现你的优化"""
    
    # 示例:替换注意力算子
    # from your_optimization import optimized_attention
    # if hasattr(self._model, 'vision_model'):
    #     for layer in self._model.vision_model.encoder.layers:
    #         layer.self_attn.forward = optimized_attention
    
    # TODO: 实现你的 Vision Encoder 优化
    pass

4. 测试你的优化模型

python benchmark.py \
    --model-path ./Qwen3-VL-2B-Instruct \
    --dataset-path ./data \
    --output result_optimized.json \
    --num-samples 100

5. 生成完整结果用于提交

python benchmark.py \
    --model-path ./Qwen3-VL-2B-Instruct \
    --dataset-path ./data \
    --output result.json \
    --num-samples 5000

评测指标

最终得分计算公式:

最终得分 = 0.4 × 准确率 + 0.3 × TTFT提升率 + 0.3 × 吞吐量提升率

指标说明

  • TTFT (Time To First Token): 从输入准备到生成第一个 Token 的时间(毫秒)

    • 包含图像编码、文本编码、跨模态交互、Prefill 阶段、第一个 Token 生成
    • Baseline: ~80ms
    • 提升率 = (Baseline - 你的TTFT) / Baseline
  • Throughput (吞吐量): 端到端 Token 生成速率tokens/秒)

    • Baseline: ~55 tokens/sec
    • 提升率 = (你的吞吐量 - Baseline) / Baseline
  • Accuracy (准确率): 验证集上的 VQA 准确率5000 个样本)

    • 支持多个标准答案的软匹配

比赛规则

重要规则

  1. 不要修改 benchmark.py

    • 此基准脚本仅用于自测
    • 最终评测将使用独立的官方基准系统
    • 修改此文件可能导致本地结果与最终评测结果不一致
  2. 仅修改 evaluation_wrapper.py

  3. 保持必需的属性

    • VLMModel 类必须暴露 processormodeldevice 属性
    • Benchmark 使用这些属性来访问模型和处理器
    • generate() 方法是可选的,主要用于调试
  4. 禁止行为

    • 禁止硬编码答案
    • 禁止修改数据集
    • 禁止使用外部 API 或服务
    • 所有优化必须是本地且自包含的

优化方向

  • 鼓励实现算子替换与内核优化使用Triton、CUDA C++等重写或替换标准算子实现如Attention、LayerNorm、Conv2d等

  • 鼓励实现内存与缓存优化优化KV Cache内存布局、减少内存碎片、优化显存访问模式

  • 鼓励实现编译与图优化使用torch.compile进行计算图优化、自定义内核调度

  • 鼓励实现注意力机制优化实现Flash Attention、内存高效注意力、稀疏注意力

  • 鼓励实现生成过程优化:优化解码策略、缓存管理、生成配置参数

不允许:

  • 使用外部服务禁止调用外部API、云服务或任何需要网络连接的功能

  • 数据与答案作弊:禁止使用测试数据进行训练、预计算答案、硬编码输出

  • 模型替换与篡改:希望选手着重做算子优化,不要用额外的数据集去训练模型、改变模型架构、直接修改权重数值等。

  • 过拟合优化:禁止针对特定评测样本进行条件分支或特殊处理

  • 黑盒工具套用:仅修改配置文件而无实质性代码贡献的行为不被认可

  • 环境操纵禁止通过修改系统环境、GPU频率锁定等方式干扰公平评测

重要提示

样本选择

  • 提供的 benchmark.py 使用固定顺序(从索引 0 开始的前 N 个样本)
  • 运行 --num-samples 100 时,会评测样本 0-99
  • 这确保了本地自测的可复现性
  • 注意:竞赛委员会使用的官方评测系统可能采用不同的采样策略(包括随机采样)进行最终验证

硬件信息

基准测试会自动记录详细的硬件信息:

  • Python 版本、PyTorch 版本、CUDA 版本
  • GPU 名称、显存、计算能力
  • CPU 型号、核心数、频率
  • 系统信息(操作系统、内核、架构)
  • PPU 信息(如果可用)

这些信息保存在 result.jsonsystem_info 字段中,用于统计分析。

性能测量

  • 预热:在实际测量前使用 10 个样本进行 GPU 预热
  • TTFT 测量:测量从输入准备到第一个 Token 的时间(包含所有预处理)
  • 吞吐量测量:测量生成 128 个 Token 的端到端时间
  • 状态隔离:在测量之间清理 GPU 缓存,确保公平性

随机种子

  • --random-seed 参数仅影响 PyTorch 的随机数生成器
  • 不会影响样本选择顺序(始终是固定的)
  • 用于模型推理随机性的可复现性

输出格式

result.json 文件包含:

{
  "system_info": {
    "timestamp": "...",
    "python_version": "...",
    "torch_version": "...",
    "cuda_version": "...",
    "gpu_name": "...",
    ...
  },
  "performance": {
    "avg_ttft_ms": 90.55,
    "avg_throughput_tokens_per_sec": 57.77
  },
  "answers": [
    {
      "question_id": 34602,
      "prediction": "你的答案文本"
    },
    ...
  ]
}

提交指南

初赛提交必需文件

  1. result.json - 通过运行 benchmark.py 生成

    • 包含所有样本的预测
    • 必须包含有效的 performance 指标
    • 重要:上传到天池平台的 result.json 仅用于参考。最终成绩将由竞赛委员会使用标准化硬件和官方评测系统进行评测。
  2. 你的优化代码 - 包含你优化的 VLMModel 类的 evaluation_wrapper.py

  3. Docker 镜像- 包含你优化环境的容器

评测流程

  1. 自测:使用提供的 benchmark.py 在本地测试你的优化
  2. 提交:将你的 result.json 上传到天池平台(仅用于参考)
  3. 官方评测:竞赛委员会将使用以下方式评测你的代码:
    • 提交Docker镜像
    • 标准化硬件环境
    • 官方评测代码
    • 完整验证集,随机采样进行验证
  4. 最终排名:基于官方评测系统计算的最终得分

祝你好运!

希望你会专注于算子级优化、内核替换和高效的内存管理。记住:准确率和速度同样重要!祝你好运!

Qwen3VLForConditionalGeneration( (model): Qwen3VLModel( (visual): Qwen3VLVisionModel( (patch_embed): Qwen3VLVisionPatchEmbed( (proj): Conv3d(3, 1024, kernel_size=(2, 16, 16), stride=(2, 16, 16)) ) (pos_embed): Embedding(2304, 1024) (rotary_pos_emb): Qwen3VLVisionRotaryEmbedding() (blocks): ModuleList( (0-23): 24 x Qwen3VLVisionBlock( (norm1): LayerNorm((1024,), eps=1e-06, elementwise_affine=True) (norm2): LayerNorm((1024,), eps=1e-06, elementwise_affine=True) (attn): Qwen3VLVisionAttention( (qkv): Linear(in_features=1024, out_features=3072, bias=True) (proj): Linear(in_features=1024, out_features=1024, bias=True) ) (mlp): Qwen3VLVisionMLP( (linear_fc1): Linear(in_features=1024, out_features=4096, bias=True) (linear_fc2): Linear(in_features=4096, out_features=1024, bias=True) (act_fn): GELUTanh() ) ) ) (merger): Qwen3VLVisionPatchMerger( (norm): LayerNorm((1024,), eps=1e-06, elementwise_affine=True) (linear_fc1): Linear(in_features=4096, out_features=4096, bias=True) (act_fn): GELU(approximate='none') (linear_fc2): Linear(in_features=4096, out_features=2048, bias=True) ) (deepstack_merger_list): ModuleList( (0-2): 3 x Qwen3VLVisionPatchMerger( (norm): LayerNorm((4096,), eps=1e-06, elementwise_affine=True) (linear_fc1): Linear(in_features=4096, out_features=4096, bias=True) (act_fn): GELU(approximate='none') (linear_fc2): Linear(in_features=4096, out_features=2048, bias=True) ) ) ) (language_model): Qwen3VLTextModel( (embed_tokens): Embedding(151936, 2048) (layers): ModuleList( (0-27): 28 x Qwen3VLTextDecoderLayer( (self_attn): Qwen3VLTextAttention( (q_proj): Linear(in_features=2048, out_features=2048, bias=False) (k_proj): Linear(in_features=2048, out_features=1024, bias=False) (v_proj): Linear(in_features=2048, out_features=1024, bias=False) (o_proj): Linear(in_features=2048, out_features=2048, bias=False) (q_norm): Qwen3VLTextRMSNorm((128,), eps=1e-06) (k_norm): Qwen3VLTextRMSNorm((128,), eps=1e-06) ) (mlp): Qwen3VLTextMLP( (gate_proj): Linear(in_features=2048, out_features=6144, bias=False) (up_proj): Linear(in_features=2048, out_features=6144, bias=False) (down_proj): Linear(in_features=6144, out_features=2048, bias=False) (act_fn): SiLUActivation() ) (input_layernorm): Qwen3VLTextRMSNorm((2048,), eps=1e-06) (post_attention_layernorm): Qwen3VLTextRMSNorm((2048,), eps=1e-06) ) ) (norm): Qwen3VLTextRMSNorm((2048,), eps=1e-06) (rotary_emb): Qwen3VLTextRotaryEmbedding() ) ) (lm_head): Linear(in_features=2048, out_features=151936, bias=False) )