Skip to content

Commit e477922

Browse files
devmotionclaude
andauthored
Fix allocation tests on Julia >= 1.13 (#536)
OpenLibm is a `Libdl.LazyLibrary` on Julia >= 1.13. Its `ccall` targets are resolved on first use and cached per callsite, and resolving one allocates 16 bytes. Each test measured a single call of a newly created closure, into which the `ccall` is inlined by constant propagation. So every measurement included the 16 bytes of resolving a fresh callsite. Affected are the paths that call `gamma` (`1 <= a <= 20`) or `erfc` (`a == 0.5`). Now each closure is called twice and only the second measurement is used. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent c9ff360 commit e477922

1 file changed

Lines changed: 21 additions & 13 deletions

File tree

test/gamma_inc.jl

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,14 @@ end
305305
@test_throws DomainError loggamma(6, -3.2)
306306
end
307307

308+
# Run `f(args...)` twice and return only the result of the second call, so that
309+
# one-time costs of the first execution of a freshly compiled callsite are not
310+
# measured. On Julia >= 1.13 OpenLibm is a `Libdl.LazyLibrary`, so resolving the
311+
# target of a `ccall` into it allocates 16 bytes on that callsite's first
312+
# execution. Warming up with a separate call does not help, because the binding
313+
# is cached per callsite and not per callee.
314+
run_twice(f, args...) = (f(args...); f(args...))
315+
308316
@testset "GPU compatibility ($FT)" for FT in (Float64, Float32, Float16)
309317
# Note: This test is a proxy for GPU compatibility by checking that the functions
310318
# are type stable and do not allocate memory. It does not launch any GPU kernels.
@@ -319,38 +327,38 @@ end
319327
# `@allocated` checks for allocations for specific code paths
320328
## a >= 1
321329
### gamma_inc_temme_1: simplified Temme expansion
322-
@test iszero((FT -> @allocated(gamma_inc(FT(30.0), FT(29.99999), 0)))(FT))
330+
@test iszero(run_twice(FT -> @allocated(gamma_inc(FT(30.0), FT(29.99999), 0)), FT))
323331
### gamma_inc_minimax: minimax approximation
324-
@test iszero((FT -> @allocated(gamma_inc(FT(100.0), FT(80.0), 0)))(FT))
332+
@test iszero(run_twice(FT -> @allocated(gamma_inc(FT(100.0), FT(80.0), 0)), FT))
325333
### gamma_inc_temme: Temme expansion
326-
@test iszero((FT -> @allocated(gamma_inc(FT(100.0), FT(80.0), 1)))(FT))
334+
@test iszero(run_twice(FT -> @allocated(gamma_inc(FT(100.0), FT(80.0), 1)), FT))
327335
### gamma_inc_cf: Continued fraction
328-
@test iszero((FT -> @allocated(gamma_inc(FT(1.7), FT(2.5))))(FT))
336+
@test iszero(run_twice(FT -> @allocated(gamma_inc(FT(1.7), FT(2.5))), FT))
329337
### gamma_inc_taylor: Taylor series
330-
@test iszero((FT -> @allocated(gamma_inc(FT(11.1), FT(0.001))))(FT))
338+
@test iszero(run_twice(FT -> @allocated(gamma_inc(FT(11.1), FT(0.001))), FT))
331339
### gamma_inc_asym: Asymptotic expansion
332-
@test iszero((FT -> @allocated(gamma_inc(FT(10.0), FT(35.0))))(FT))
340+
@test iszero(run_twice(FT -> @allocated(gamma_inc(FT(10.0), FT(35.0))), FT))
333341
### gamma_inc_fsum: Finite sums
334-
@test iszero((FT -> @allocated(gamma_inc(FT(24.0), FT(25))))(FT))
342+
@test iszero(run_twice(FT -> @allocated(gamma_inc(FT(24.0), FT(25))), FT))
335343
## a==0.5
336344
### erfc
337-
@test iszero((FT -> @allocated(gamma_inc(FT(0.5), FT(0.5))))(FT))
345+
@test iszero(run_twice(FT -> @allocated(gamma_inc(FT(0.5), FT(0.5))), FT))
338346
## x < 1.1
339347
### gamma_inc_taylor_x
340-
@test iszero((FT -> @allocated(gamma_inc(FT(0.9), FT(0.8))))(FT))
348+
@test iszero(run_twice(FT -> @allocated(gamma_inc(FT(0.9), FT(0.8))), FT))
341349
## else
342350
### gamma_inc_cf
343-
@test iszero((FT -> @allocated(gamma_inc(FT(0.7), FT(2.5))))(FT))
351+
@test iszero(run_twice(FT -> @allocated(gamma_inc(FT(0.7), FT(2.5))), FT))
344352
end
345353

346354
@testset "gamma_inc_inv allocations" begin
347355
# `@allocated` checks for allocations for specific code paths
348356
## x0 approximation paths
349357
### gamma_inc_inv_psmall
350-
@test iszero((FT -> @allocated(gamma_inc_inv(FT(1.0), FT(0.01), FT(0.99))))(FT))
358+
@test iszero(run_twice(FT -> @allocated(gamma_inc_inv(FT(1.0), FT(0.01), FT(0.99))), FT))
351359
### gamma_inc_inv_qsmall
352-
@test iszero((FT -> @allocated(gamma_inc_inv(FT(5.0), FT(0.99), FT(0.01))))(FT))
360+
@test iszero(run_twice(FT -> @allocated(gamma_inc_inv(FT(5.0), FT(0.99), FT(0.01))), FT))
353361
### gamma_inc_inv_alarge
354-
@test iszero((FT -> @allocated(gamma_inc_inv(FT(50.0), FT(0.3), FT(0.7))))(FT))
362+
@test iszero(run_twice(FT -> @allocated(gamma_inc_inv(FT(50.0), FT(0.3), FT(0.7))), FT))
355363
end
356364
end

0 commit comments

Comments
 (0)