Speed Benchmark

July 21, 2026 · View on GitHub

中文阅读

Setup

  • Hardware: single NVIDIA H20 (80 GB) per server
  • Dataset: OmnidocBench, document / PPT / book / textbook images
  • Config: concurrency=1 (single-request latency), max_tokens=8000, temperature=0.0
  • Metric: end-to-end latency from HTTP request to complete response

HunyuanOCR AR vs DFlash

The core comparison — same base model, different inference paths:

Configwall timeavg latencypage/sspeedup
HunyuanOCR base (AR)2821.9 s3.032 s0.3301.00×
HunyuanOCR + DFlash (14.7k packs, finetune)1316.5 s1.408 s0.7062.14×

Key results:

  • DFlash achieves 2.14× end-to-end speedup vs AR baseline
  • Speculative decoding is essentially lossless: total-tokens difference < 0.15% vs AR

Cross-Model Comparison

Comparison with other open-source OCR VLMs, all under identical eval conditions (c=1, max_tokens=8000):

RankModelLatency (s/img)Page/svs HunyuanOCR ARNotes
🥇HunyuanOCR + DFlash1.410.7062.14×Speculative decoding
🥈GLM-OCR (SDK page pipeline)1.650.6041.83×Layout + region OCR concurrent
🥉PaddleOCR-VL 1.6 (0.9B)1.740.5621.71×0.9B small model + two-stage
4HunyuanOCR base (AR)3.030.3301.00×Baseline
5Unlimited-OCR (SGLang)3.660.2550.77×image tiling (gundam mode)
6DeepSeek-OCR-25.460.1790.54×Large model + grounding
7dots.ocr7.150.1360.41×Slow but structured

Reproducing These Numbers

  1. Deploy your desired inference server (see docs/inference/inference.md)
  2. Run a compatible benchmark script — a minimal example:
import time, base64, glob, json, os
from openai import OpenAI

# ← configure these
IMAGE_DIR = "/path/to/eval/images"
SAMPLE_LIST = "./speed_eval_set_930.txt"
SERVER_URL = "http://127.0.0.1:8001/v1"
MODEL_NAME = "/path/to/HunyuanOCR/base"
PROMPT = "提取文档图片中正文的所有信息用markdown格式表示,其中页眉、页脚部分忽略,表格用html格式表达,文档中公式用latex格式表示,按照阅读顺序组织进行解析。"

# collect images
want = set(l.strip() for l in open(SAMPLE_LIST))
imgs = sorted(p for p in glob.glob(f"{IMAGE_DIR}/*") if os.path.basename(p) in want)

# encode all to base64 upfront (avoids I/O in timing loop)
items = []
for p in imgs:
    with open(p, "rb") as f:
        items.append(base64.b64encode(f.read()).decode())

client = OpenAI(api_key="EMPTY", base_url=SERVER_URL)
os.environ.pop("http_proxy", None); os.environ.pop("https_proxy", None)

t0 = time.time()
latencies, tokens = [], []
for b64 in items:
    t = time.time()
    r = client.chat.completions.create(
        model=MODEL_NAME,
        messages=[{
            "role": "user",
            "content": [
                {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{b64}"}},
                {"type": "text", "text": PROMPT},
            ],
        }],
        temperature=0.0, max_tokens=8000, extra_body={"top_k": 1},
    )
    latencies.append(time.time() - t)
    tokens.append(r.usage.completion_tokens)

wall = time.time() - t0
n = len(latencies)
print(json.dumps({
    "n": n,
    "wall_s": round(wall, 3),
    "avg_latency_s": round(sum(latencies)/n, 3),
    "page_per_s": round(n/wall, 4),
    "token_per_s": round(sum(tokens)/wall, 2),
}))
  1. Compare page_per_s — this is the truly fair cross-model metric.

Fairness Notes

  • Fair: wall time, avg_latency, page_per_s — comparable across all models
  • NOT fair: token_per_s, total_tokens — different tokenizers count differently
  • Each model uses its native prompt (forcing a common prompt breaks output quality)
  • All models tested on identical H20 (80GB) hardware