Merge remote server-edition: cpu-fast lane deploy docs
Both sides extended DEPLOY(_ZH): remote documented the cpu-fast lane (weights subset, config comparison, systemd note, OOM troubleshooting), local added the measured GPU profile and the reuse-off default. Conflict was the capacity-section memory bullet: kept the GPU deployment bullet and remote's cpu-fast-aware memory bullet (which supersedes the old three-models line). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -143,6 +143,9 @@ Notes:
|
||||
- **anime-seg**: only `isnetis.onnx` is read; nothing else is required.
|
||||
- `anime-seg` and `BiRefNet_HR-matting` are optional — omit their folders unless you
|
||||
use `seg_model=anime-seg` / the cross-check veto respectively.
|
||||
- The **`cpu-fast` lane** (§6) loads only **ViTMatte + BiRefNet**; on an 8 GB box
|
||||
using that lane you can skip `anime-seg` and `BiRefNet_HR-matting` entirely.
|
||||
(`scripts/fetch_weights.py` still fetches all four for full functionality.)
|
||||
|
||||
The easiest way to populate the folders is to let `hf download` fetch them (it also
|
||||
pulls a couple of unused files like `README.md`, which is harmless):
|
||||
@@ -204,6 +207,32 @@ redirect back to `huggingface.co`, which recent `huggingface_hub` rejects with
|
||||
| `HF_HUB_OFFLINE` / `TRANSFORMERS_OFFLINE` | — | Set to `1` in production once weights are cached |
|
||||
| `OMP_NUM_THREADS` / `MKL_NUM_THREADS` | — | Cap CPU threads (e.g. `4`) |
|
||||
|
||||
### Config file: `default.yaml` vs the `cpu-fast` lane
|
||||
|
||||
`BGFILTER_CONFIG` selects the pipeline config. Two are shipped:
|
||||
|
||||
- **`configs/default.yaml`** — full quality. Cross-check veto **on** (loads the extra
|
||||
`BiRefNet_HR-matting` at 2048 as a second opinion), best edges. Heavier: on large
|
||||
inputs the peak working set runs well into double-digit GB, so it wants a roomy box
|
||||
(or a GPU).
|
||||
- **`configs/cpu-fast.yaml`** — the lean CPU lane, tuned for an **8 GB box**. fp32,
|
||||
BiRefNet segmentation only, **no cross-check, no anime-seg**, chunked attention
|
||||
(`attn_query_chunk: 512`). Loads only **two** weights (base ViTMatte + BiRefNet).
|
||||
Measured peak working set: **~5.6 GB @ 2048×1152 (2.4 MP)**, ~7.1 GB @ 2048×2048
|
||||
(4.2 MP); ~14–15 s per 1.5 MP image.
|
||||
|
||||
> **On a ≤8 GB server, set `BGFILTER_CONFIG=configs/cpu-fast.yaml`.** The default lane
|
||||
> plus a large input is exactly what drives ViTMatte's attention transient into an
|
||||
> OOM — the worker is killed (SIGKILL) and a fronting nginx returns **502** while the
|
||||
> app log shows `DefaultCPUAllocator: can't allocate memory`.
|
||||
|
||||
Two model knobs live in the **config file** (`model:` section), not env vars:
|
||||
|
||||
| Config key | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `model.precision` | `fp32` | `fp32` or `bf16`. bf16 is used **only** on hardware with native kernels (CUDA, or a CPU with AVX512-BF16/AMX); otherwise it warns and falls back to fp32. Also settable per model under `segmentation:` / `cross_check:`. |
|
||||
| `model.attn_query_chunk` | `2048` | Query-row chunk for ViTMatte's global attention. Smaller (e.g. `512`) caps the O(N²) memory transient for a few % more compute; output is bit-for-bit identical. `0` disables chunking (stock one-shot attention). |
|
||||
|
||||
## 7. Run the service
|
||||
|
||||
```bash
|
||||
@@ -252,6 +281,10 @@ ReadWritePaths=/opt/genarrative-image-host
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
On a ≤8 GB box, change the config line to the lean lane:
|
||||
`Environment=BGFILTER_CONFIG=configs/cpu-fast.yaml` (see §6) — the default lane can
|
||||
OOM on large inputs.
|
||||
|
||||
If you use Option B (local `models/` folders) instead of the HF cache, drop the
|
||||
`HF_HOME`/offline lines — those weights need no cache or network.
|
||||
|
||||
@@ -285,9 +318,10 @@ service has **no authentication**. To reach it from other hosts:
|
||||
|
||||
## 11. Capacity & performance
|
||||
|
||||
- CPU throughput is ~**45 s per 1.5 MP image** with the default (base ViTMatte +
|
||||
BiRefNet); requests are serialized by the global lock, so ~1–2 images/min per
|
||||
instance. Bottleneck is full-resolution ViTMatte + pymatting foreground estimation.
|
||||
- CPU throughput: the **`cpu-fast` lane** does ~**14–15 s per 1.5 MP image** (base
|
||||
ViTMatte + one BiRefNet@1024, chunked attention). The **default lane** is slower —
|
||||
the cross-check adds a second HR-matting@2048 forward. Requests are serialized by
|
||||
the global lock, so plan for a handful of images/min per instance.
|
||||
- For throughput: use a GPU (`BGFILTER_DEVICE=cuda`, install a CUDA torch build) —
|
||||
roughly an order of magnitude faster — and/or run multiple instances behind a load
|
||||
balancer (each with `--workers 1`).
|
||||
@@ -303,8 +337,11 @@ service has **no authentication**. To reach it from other hosts:
|
||||
expandable segments (e.g. native Windows) reserved is ~15.3–16.2 GB:
|
||||
borderline-to-overflow on a 16 GB card. Precision `bf16` is what makes 16 GB
|
||||
viable at all — fp32 reserved ~17 GB overflows.
|
||||
- Memory: one worker holds all three models (~1 GB weights + runtime). `MemoryMax=8G`
|
||||
is a safe ceiling for a single CPU worker.
|
||||
- Memory: chunked attention (`attn_query_chunk`) caps ViTMatte's O(N²) transient, so
|
||||
the peak is set by dense compute, not the attention map. On the `cpu-fast` lane the
|
||||
measured peak is **~5.6 GB @ 2.4 MP / ~7.1 GB @ 4.2 MP** — `MemoryMax=8G` with the
|
||||
default 4 MP input cap is a safe ceiling for a single CPU worker. The default lane
|
||||
(cross-check on) needs more headroom.
|
||||
- **Keeping RSS flat (glibc).** After each image the service calls glibc
|
||||
`malloc_trim(0)` (`bgfilter/memtune.py`) to hand a large BiRefNet@2048 forward's
|
||||
freed activations back to the OS — without it, ptmalloc keeps them in the arena
|
||||
@@ -333,4 +370,6 @@ service has **no authentication**. To reach it from other hosts:
|
||||
| `503 service not ready` | Models still loading at startup; wait for "Application startup complete". |
|
||||
| `500 inference failed` right after enabling `BGFILTER_CROSS_CHECK` (offline) | `BiRefNet_HR-matting` not provisioned; download it into the cache/`models/` (§5). |
|
||||
| OOM / killed under load | More than one worker, or `MemoryMax` too low. Keep `--workers 1`. |
|
||||
| Worker `killed` (SIGKILL) / `502` on a large image; log shows `DefaultCPUAllocator: can't allocate memory` | ViTMatte OOM on a big input. Use `BGFILTER_CONFIG=configs/cpu-fast.yaml` (§6), and/or lower `BGFILTER_MAX_IMAGE_PIXELS`. |
|
||||
| `413`/large upload rejected at the proxy | nginx `client_max_body_size` (default 1 MB) — raise it in the server block (e.g. `client_max_body_size 12m;`); this is separate from the app's `BGFILTER_MAX_IMAGE_PIXELS`. |
|
||||
| `400 could not auto-detect background colour` | Input has no clean flat border; pass `screen_color=#RRGGBB`. |
|
||||
|
||||
Reference in New Issue
Block a user