Skip to content

Commit 8d66dba

Browse files
hyperpolymathclaude
andcommitted
perf(dataloader): rejection-sample negatives instead of setdiff per proof
`build_training_examples` was calling `setdiff(all_premises_pool, used_names)` once per proof_state — on the 138k/56k-unique corpus that is ~8 GB of fresh `Vector{String}` allocations before training can start. Cold training stalled for 10+ minutes in GC before epoch 1. Sample-and-reject from the pool instead: for each proof, draw `num_negatives × 8` attempts, skipping anything in `used_set` or already picked. Same distribution, O(num_negatives) per call, no per-proof allocation of the negative pool. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7d107b1 commit 8d66dba

1 file changed

Lines changed: 22 additions & 4 deletions

File tree

src/julia/training/dataloader.jl

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ function build_training_examples(proof_states::Vector{RawProofState},
223223
end
224224

225225
premises_set = Set(all_premises_pool)
226+
pool_len = length(all_premises_pool)
226227

227228
for ps in proof_states
228229
prover = safe_parse_prover(ps.prover)
@@ -238,10 +239,27 @@ function build_training_examples(proof_states::Vector{RawProofState},
238239
push!(positive_premises, Premise(name, "", prover, nothing, 1.0f0, 1.0f0))
239240
end
240241

241-
# Sample negative premises (not used in this proof)
242-
negative_names = setdiff(all_premises_pool, used_names)
243-
num_neg = min(num_negatives, length(negative_names))
244-
sampled_negatives = num_neg > 0 ? sample(collect(negative_names), num_neg; replace=false) : String[]
242+
# Sample negative premises by rejection sampling. Direct
243+
# `setdiff(all_premises_pool, used_names)` builds a fresh
244+
# `Vector{String}` of length ~|pool| per proof_state — on a
245+
# 56k-premise / 138k-proof corpus that is ~8 GB of GC churn
246+
# before the first epoch starts. Sample-and-reject gives the
247+
# same distribution in O(num_negatives × |used|) per call.
248+
used_set = Set(used_names)
249+
num_neg = min(num_negatives, pool_len - length(used_set))
250+
sampled_negatives = String[]
251+
if num_neg > 0
252+
picked = Set{String}()
253+
attempts = 0
254+
max_attempts = num_neg * 8
255+
while length(sampled_negatives) < num_neg && attempts < max_attempts
256+
cand = all_premises_pool[rand(1:pool_len)]
257+
attempts += 1
258+
(cand in used_set || cand in picked) && continue
259+
push!(picked, cand)
260+
push!(sampled_negatives, cand)
261+
end
262+
end
245263

246264
negative_premises = Premise[]
247265
for name in sampled_negatives

0 commit comments

Comments
 (0)