Repository navigation
feat(competitions): GPU slices for submission runners - #42
Merged
Merged
Conversation
Competitions could not use a GPU: the docker runner never passed a card, so a GPU environment trained on the CPU without a word, and the broker refused GPU images outright (shown as a metric failure). - The owner gives whole cards to submissions in Resources («Видеокарты для посылок»), with runs per card (1..8); those cards leave the rooms' pool. - Each run gets a VRAM share (card memory / runs per card), held from two sides: torch is capped through the harness's sitecustomize (CatBoost's gpu_ram_part follows the share), and a root-side watchdog stops a run above its share + 256 MB on two samples in a row (fail closed when unreadable). - A competition has a «Видеокарта» switch, only on CUDA environments; uploads are refused with a clear reason when no card is given. The metric never gets a card. - The queue binds a card and the run's share on the row; GPU rows never block CPU rows; changing runs per card mid-class cannot over-commit a card. - New built-in environment kaggle-gpu (base-gpu + kaggle-base pins, seaborn, opencv-python-headless, timm); base-gpu pins torch 2.14.1 (CUDA 13.0, driver 580+); rental scripts take CUDA 13 hosts only. - Kubernetes: GPU notebook jobs request gpu.competitions.resource; GPU images run CPU jobs; slots, shm, pull allowance and refusals handled. - Console, running list, participant conditions and outcomes show the card.
This was referenced Oct 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Competitions could not use a GPU. Verified on a rented VM (2 × RTX 4090, driver 580.95.05) on 0.21.0: a competition on
base-gpuran CUDA torch without a card (torch 2.14.1+cu130 | available False | devices 0, nonvidia-smi), and nobody was told; on Kubernetes the broker refused every GPU image and the app showed it as «упала метрика». The owner asked for runners that hold a slice of a card so neural-network submissions can train.What
Cards for submissions (Resources → «Видеокарты для посылок»). The owner gives whole cards (
KERNEL_GPUSentries) to submission runners and sets runs per card (1..8). A card given to submissions leaves the rooms' pool, so a class and submissions never share a card. The panel lists every card with its model and memory (probed through docker from inside the app container, at start and every 10 min), who holds it, and the resulting share. «Как поделена машина» gets a cards bar.COMPETITION_GPUS/COMPETITION_GPU_PER_DEVICEare the env fallbacks (colloq-host, compose, .env.example).The share is held from two sides. share = card memory / runs per card.
site/sitecustomize.py; withCOLLOQ_GPU_MEMORY_MB(share − 512 MB for the CUDA context) torch's allocator is capped at its share; a probe oftorchbefore the real import no longer disables it. CatBoost'sgpu_ram_partdefaults to the share (it preallocates ~95 % of the card otherwise — measured 22.9 GB of 24 GB; with the share 6.3 GB). xgboost grows on demand.nvidia-smiin the run container as root every 3 s (a uid-1000 participant cannot kill it — checked on the card); above share + 256 MB on two samples in a row the run is stopped with our own words; if the share cannot be read several times in a row on a shared card the run is stopped too (fail closed).Per competition. A «Видеокарта: нет / срез ≈ N ГБ» switch, only on CUDA environments (the server refuses the combination otherwise). With the switch on and no card given, uploads and the baseline check are refused at the door with a reason (
gpu_unavailable); metric checks and rescores still work (the metric never gets a card). Existing competitions keepgpu: falseand behave as before.Queue. The take binds a card and the run's share/per-card count on the queue row; a card's load is counted in shares, so raising runs per card mid-class cannot over-commit it. A GPU job waiting for a card never blocks CPU jobs. Deleting a competition stops its runs first. Rooms never get a card the queue has bound, even before the run's container is up. Places and ETAs simulate the card shares.
Environment
kaggle-gpu=base-gpu+ the kaggle-base pins + seaborn 0.13.2, opencv-python-headless 5.0.0.93, timm 1.0.30 (built on a card: 12.7 GB,pip checkclean, torch/xgboost/catboost/timm on CUDA).base-gpunow pins torch 2.14.1 / torchvision 0.29.1 (CUDA 13.0 wheels, driver 580+); the Vast rental scripts take CUDA 13 hosts only. GPU images stay local builds (publish.yml unchanged).Kubernetes. GPU notebook jobs request
gpu.competitions.resource×count(the cluster's device plugin defines the unit: time-slicing, MPS, MIG), with the GPU RuntimeClass/selector/tolerations and a /dev/shm volume; GPU images run every other job kind on the CPU; at mostgpu.competitions.slotsGPU notebooks at once so CPU work is not starved; API refusals (quota, RuntimeClass) come back as agpudeferral; GPU Pods get a pull allowance. Helm values/schema/templates/README, release.py.UI (Paper page «15 · Видеокарты для посылок», G1–G4): the Resources block and bar, the editor's GPU row with its states, «GPU 0» chips and «видеокарты N из M» on the console, the card in «Работают сейчас», the participant's «Видеокарта» condition, the stop and OOM texts (with a hint: «У посылки срез видеокарты 6 ГБ: уменьшите batch_size или модель.»).
Verified on hardware (before the review fixes)
Letters competition (CNN seminar), reference notebook, 2 CPU / 4 GB / 600 s,
kaggle-gpu, VM 61 vCPU / 98 GB / 2 × RTX 4090:cuda:0, torch capped at 5.50 GiB for a 6141 MB share; a run that lifted the cap and took 10.4 GB was stopped by the watchdog; an 8 GB allocation failed inside the cell with the hint; a class onkaggle-gpugot the other card; all cards given to submissions → the class refused with the new reason.A mixed load (10 GPU + 4 CPU) showed the CPU submissions do not wait behind the GPU ones.
docker exec nvidia-smiin the hardened container; uid 1000 cannot kill it; CatBoost withgpu_ram_partstays within the share). The fixed tree itself was not rerun on a card (the rented VM ran out of credit; the owner chose to release without a second hardware run).Review
Seven-dimension adversarial review: 45 findings, all confirmed by an independent judge (19 important, 20 minor, 6 nits), fixed in six lanes plus a seams pass, each fix with a regression test that fails without it.
Tests
npm run typecheck: 0 errors.npm test(Node 22, helm 3.19.0): 5337 tests, 5295 pass, 41 skipped, 1 fail —tests/class-zip.test.mts, the known local-only failure (reads PUBLIC_URL from the repo's .env); CI is unaffected.