DeepSeek GCP A100 Setup¶
This note captures the current known-good baseline for bringing up GlossAPI DeepSeek OCR on fresh GCP A100 nodes and the required diagnosis workflow when a fresh node does not behave like the already-converged fleet.
Goal¶
Treat a fresh OCR node as a reproducible setup target, not as a one-off machine that is repaired interactively until it happens to work.
The target is a clean path from:
- create instance
- bootstrap machine
- prepare GlossAPI runtime
- run a normal GlossAPI OCR workflow
Known-good baseline¶
This rollout has validated the following stack on working OCR fleet nodes:
- Ubuntu
22.04.5 - NVIDIA driver
590.48.01 A100 40GBGPUs- host Python
3.10 - DeepSeek venv Python
3.11from a stable final CPython, not a prerelease distro build torch 2.10.0+cu130vllm 0.18.0transformers 4.57.6workers_per_gpu=1
The runner also expects GPU persistence mode to be enabled and will record the
preflight result under sidecars/ocr_runtime/gpu_preflight.json.
First command on a fresh node¶
Run the checked-in runtime report before changing code or applying ad hoc fixes:
python -m glossapi.scripts.deepseek_runtime_report --repo-root /opt/glossapi/repo
The report prints:
- OS and hostname
- repo revision
- GPU model, driver, and memory
- selected Python executable and venv root
torch/vllm/transformersimport details- wheel-managed NVIDIA library directories
- a focused
pip freezesubset - selected runtime environment variables
Prefer comparing this output against a known-good OCR node before modifying GlossAPI itself.
Fresh-node diagnosis rule¶
If a fresh node fails, classify the problem before patching code:
- instance creation choice
- wrong image
- wrong driver path
- wrong machine family or GPU shape
- bootstrap incompleteness
- missing system packages
- missing wheel-managed CUDA libraries
- model / cache / filesystem layout mismatch
- missing env wiring
- actual GlossAPI runtime assumption
- hidden dependency on a particular venv layout
- hidden dependency on a specific CUDA wheel layout
- hidden runner / vLLM startup assumption
Write down which class the current failure belongs to before making broad code changes.
Current benchmark-node findings¶
The fresh a2-highgpu-2g benchmark node used during the April 3, 2026 work
surfaced two setup classes:
- early missing shared-library failure:
ImportError: libcudart.so.12: cannot open shared object file- later engine startup failure after bootstrap fixes:
RuntimeError: Engine core initialization failed. Failed core proc(s): {}
This means instance creation itself worked, but bootstrap/runtime reproducibility was incomplete.
The concrete bootstrap issues found on that node were:
uvexisted only in~/.local/bin, which non-interactive shells were not using- the default DeepSeek venv was created against
/usr/bin/python3.11, which on that node wasPython 3.11.0rc1 - system cargo/rustc were too old to parse the repo
Cargo.lock - the DeepSeek venv still needed the cu12 runtime pair for
vllm._Cto import: nvidia-cuda-runtime-cu12nvidia-cuda-nvrtc-cu12
After correcting those bootstrap defects, the same fresh node was able to:
- import
vllm._C - initialize a direct one-GPU
LLM(...) - start a real
openarchives_ocr_run_nodeworkload withruntime_backend=vllm
The same node was also used for a real 10-PDF extract -> clean -> ocr
checkpoint:
- the stable end-to-end shape on that node was:
- multi-GPU extraction
workers_per_device=1- multi-GPU DeepSeek OCR with
workers_per_gpu=1 - an isolated extraction benchmark with
workers_per_device=2was faster on the same sample, but the first full-pipeline replay hit a Docling allocator crash: malloc_consolidate(): unaligned fastbin chunk detected- treat
workers_per_device=2as benchmark-only / experimental until it is proven stable in the full Corpus pipeline, not just in extract-only tests
The full-pipeline checkpoint harness also now retries the JSONL export when OCR has already filled text into parquet rows but the first export pass still emits zero records. This guards the observed end-of-run export race on the benchmark node without changing the OCR output contract itself.
Current runner expectation¶
glossapi.ocr.deepseek.runner._build_env() now auto-discovers
site-packages/nvidia/*/lib directories under the selected DeepSeek virtualenv
and prepends them to LD_LIBRARY_PATH.
This is the right place to normalize wheel-managed CUDA library discovery. Do not rely on manual shell-session exports as the primary contract.
Practical bring-up checklist¶
- confirm the node matches the OS / driver baseline
- export user-local tool paths explicitly for non-interactive shells:
export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$PATH"- install a stable CPython explicitly, for example:
~/.local/bin/uv python install 3.11.11- run
deepseek_runtime_report - compare report output to a known-good node
- fix bootstrap mismatches first
- rerun the report
- only then run a small OCR validation workload
- if OCR still fails, inspect worker logs and decide whether the remaining gap belongs in GlossAPI runtime code or external bootstrap
Rust note¶
If editable installs fail while building glossapi_rs_cleaner or
glossapi_rs_noise, prefer a user-local modern Rust toolchain:
curl https://sh.rustup.rs -sSf | sh -s -- -y
export PATH="$HOME/.cargo/bin:$PATH"
rustup toolchain install stable
rustup default stable