Skip to content

Make code_eval reliable in fleets: pin filelock and isolate metrics cache per batch#1

Open
maxidl wants to merge 2 commits into
mainfrom
fix/code-eval-reliability
Open

Make code_eval reliable in fleets: pin filelock and isolate metrics cache per batch#1
maxidl wants to merge 2 commits into
mainfrom
fix/code-eval-reliability

Conversation

@maxidl

@maxidl maxidl commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Two independent fixes, both required for the HF evaluate-based code tasks (HumanEval / MBPP / LBPP + their deu variants) to run in a multi-job eval-hive fleet. Both are latent bugs that only surface under fork + concurrency, so single/serial runs mask them.

1. Pin filelock < 3.16 (pixi.toml)

filelock >= 3.16 adds an at-fork audit that raises

RuntimeError: os.fork is unsafe while filelock is changing descriptor ownership

when code_eval forks to execute generated code. This kills every code task regardless of concurrency.

2. Isolate evaluate's metrics cache per batch (create_run.py)

evaluate names its compute-cache file only by experiment_id:

$HF_METRICS_CACHE/code_eval/default/default_experiment-1-0.arrow

and HF_METRICS_CACHE defaults to $HF_HOME/metrics (usually shared storage). Concurrent batches — parallel_tasks > 1, and across jobs that share HF_HOME — race on that single file: one process finishes and os.remove()s it, the next crashes with FileNotFoundError, failing the whole batch (up to task_batch_size tasks) as collateral. The batch runner now sets a per-batch node-local HF_METRICS_CACHE.

Verification

Hit both on a 31-checkpoint prelude fleet (30 nodes sharing one gpfs HF_HOME). Symptoms: code tasks crashed with the os.fork error (fix 1), then — after pinning filelock — with the default_experiment FileNotFoundError (fix 2); ~2 code-containing batches failed per job → ~15 missing tasks per checkpoint and no code pass@1. With both fixes, a 3-job canary showed 0 race errors and all code tasks landed, and the full fleet then completed 332/332 tasks on every checkpoint.

🤖 Generated with Claude Code

maxidl and others added 2 commits July 21, 2026 16:30
HF `evaluate` metrics (code_eval, bleu, rouge, ...) write a compute-cache
file named only by experiment_id:
  $HF_METRICS_CACHE/code_eval/default/default_experiment-1-0.arrow
HF_METRICS_CACHE defaults to $HF_HOME/metrics, typically on shared storage.
When lm-eval batches run concurrently (parallel_tasks > 1, and across jobs
that share HF_HOME) they all use that one file and race on evaluate's
os.remove() cleanup: one process finishes and removes it, the next crashes
with FileNotFoundError and takes its whole batch (up to task_batch_size
tasks) down as collateral.

Point each batch at its own node-local HF_METRICS_CACHE
($TMPDIR/eh_metrics_$SLURM_JOB_ID_$BATCH_IDX) so concurrent code_eval runs
can't collide. Verified on a 31-checkpoint fleet: without it ~2
code-containing batches per job failed; with it, 0 failures and all code
tasks completed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
filelock >=3.16 adds an at-fork audit that raises "os.fork is unsafe while
filelock is changing descriptor ownership" when evaluate's code_eval forks
to execute generated code (HumanEval/MBPP/LBPP). Pin below it so code
execution tasks run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant