MFR Prediction#
MFR (Mathematical Formula Recognition) is MinerU's inference stage that converts detected formula regions (bounding boxes from MFD — Mathematical Formula Detection) into LaTeX strings. It runs inside the pipeline and hybrid backends and is one of the more memory-sensitive stages in the PDF parse workflow.
Model Implementations#
Two model backends are available, selectable via the MINERU_MFR_MODEL environment variable . If unset, the default is pp_formulanet_plus_m; the other option is unimernet.
| Backend | Entry point |
|---|---|
pp_formulanet_plus_m (default) | predict_formula.py → FormulaRecognizer |
unimernet | Unimernet.py → UnimernetModel |
Both classes expose the same predict() / batch_predict() interface and share the same batch-grouping utility .
Batch Size Tuning#
The caller in batch_analyze.py sets MFR_BASE_BATCH_SIZE = 16. The actual call is:
batch_size = batch_ratio × MFR_BASE_BATCH_SIZE # default: 1 × 16 = 16
Inside FormulaRecognizer.batch_predict, the requested batch size is halved before being handed to the batch grouper — a deliberate memory-risk reduction introduced in :
formula_requested_batch_size = max(1, batch_size // 2) # → 8 at defaults
UnimernetModel.batch_predict passes batch_size directly to build_mfr_batch_groups without halving .
Dynamic Batch Grouping (build_mfr_batch_groups)#
Formula crops are sorted ascending by pixel area before batching, so that similarly-sized images land in the same group. The grouping algorithm in mineru/model/mfr/utils.py works as follows:
- Effective batch size — clamped to the largest power-of-two ≤ min(requested_size, total_count) .
- Minimum dynamic batch size —
max(16, requested_batch_size // 4). Groups smaller than this threshold are not created mid-stream . - Area-ratio downscaling — For each candidate batch, the mean area is compared against a base mean (the first batch's average). If
ratio ≥ 4, the batch size is halved; atratio ≥ 8it halves again, etc. — all sizes stay powers of two . - Finalization — Trailing groups smaller than their predecessor are merged upward; a single oversized group is split into two power-of-two sub-groups .
This prevents large formulas from triggering OOM while keeping throughput high on pages with mostly small inline formulas.
Device-Specific Memory Behaviour#
UnimernetModel :
- Non-CPU devices (CUDA, MPS, NPU, MUSA): model is cast to
float16to halve activation memory. - MPS / NPU / MUSA: initialised with
attn_implementation="eager"(FlashAttention is not available on these backends). - Pinned memory & non-blocking transfers: enabled only for CUDA —
DataLoader(pin_memory=True)+tensor.to(..., non_blocking=True).
FormulaRecognizer (PP-FormulaNet): PyTorch-based; tensors are moved to the configured device explicitly , with torch.no_grad() for all inference .
After the MFR stage, batch_analyze.py calls clean_vram(device, vram_threshold=8) to release fragmented GPU memory before the next stage .
Inference Locking#
run_mfr_inference() in model_init.py wraps every batch_predict call with PIPELINE_MFR_INFERENCE_LOCK — a threading.RLock() that guards against concurrent access in hybrid mode where pipeline and hybrid backends share the same model object .
The lock is disabled by default; enable it with:
MINERU_ENABLE_PIPELINE_INFERENCE_LOCKS=true
Known Issues & Operational Notes#
- NPU (Ascend 910B) OOM: Frequent OOM when GPU memory is shared with other processes. The maintainer recommendation is to run MinerU with exclusive device access .
- Hang at "Layout Predict: 0%" (also affects MFR stage): Reported on Ascend 910B after upgrading to v3.4.0 in pipeline/hybrid modes; VLM mode works. Workaround: use VLM backend or downgrade .
- Batch size on CPU: The internal halving in
FormulaRecognizerand the area-ratio downscaling are the primary levers for reducing peak memory on CPU deployments whereclean_vramhas no effect.
Key Source Files#
| File | Purpose |
|---|---|
mineru/model/mfr/unimernet/Unimernet.py | UniMERNet model class, device init, DataLoader, batch_predict |
mineru/model/mfr/pp_formulanet_plus_m/predict_formula.py | PP-FormulaNet model class, batch_predict |
mineru/model/mfr/utils.py | build_mfr_batch_groups and all batch-math helpers |
mineru/backend/pipeline/batch_analyze.py | MFR_BASE_BATCH_SIZE, MFR call site, clean_vram |
mineru/backend/pipeline/model_init.py | run_mfr_inference, inference locks |