Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

codegen of cfunction #35252

Closed
raminammour opened this issue Mar 24, 2020 · 4 comments
Closed

codegen of cfunction #35252

raminammour opened this issue Mar 24, 2020 · 4 comments

Comments

@raminammour
Copy link
Contributor

Hello,

Originally seen when using FunctionWrappers. @yuyichao was nice enough to provide a MWE, that shows non-repeatably inefficient code. I am out of my depth here for such julia internals, just relaying the message :)

julia> using BenchmarkTools

julia> f3(x, y) = x - x + 0.5
f3 (generic function with 1 method)

julia> g3(f, x, y) = f3(x, y)
g3 (generic function with 1 method)

julia> p3 = @cfunction(g3, Float64, (Ref{typeof(f3)}, Float64, Float64))
Ptr{Nothing} @0x00007f8405b31650

julia> @benchmark ccall($p3, Float64, (Ref{typeof(f3)}, Float64, Float64), f3, 1.0, 2.0)
BenchmarkTools.Trial:
  memory estimate:  48 bytes
  allocs estimate:  3
  --------------
  minimum time:     66.488 ns (0.00% GC)
  median time:      68.980 ns (0.00% GC)
  mean time:        74.425 ns (0.45% GC)
  maximum time:     510.097 ns (73.69% GC)
  --------------
  samples:          10000
  evals/sample:     977


julia> p3 = @cfunction(g3, Float64, (Ref{typeof(f3)}, Float64, Float64))
Ptr{Nothing} @0x00007f8405b42ec0

julia> @benchmark ccall($p3, Float64, (Ref{typeof(f3)}, Float64, Float64), f3, 1.0, 2.0)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     4.527 ns (0.00% GC)
  median time:      4.554 ns (0.00% GC)
  mean time:        4.965 ns (0.00% GC)
  maximum time:     44.207 ns (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1000

Cheers!

@Micket
Copy link
Contributor

Micket commented Apr 4, 2020

Boiling down MWE even further i reached an even minimal'er example;

g(f) = Nothing
cfun = @cfunction(g, Type{Nothing}, (Ref{typeof(g)},))
function m()
    for i in 1:10000000
        ccall(cfun, Type{Nothing}, (Ref{typeof(g)},), g)
    end
end

@time m() # slow
@time m() # still slow
cfun = @cfunction(g, Type{Nothing}, (Ref{typeof(g)},)) # redefining after use and it becomes fast.
@time m() # fast!
@time m() # still fast!

g(f) = Nothing
cfun = @cfunction(g, Type{Nothing}, (Ref{typeof(g)},)) # redefining both g and cfun it's slow again
@time m() # slow again
cfun = @cfunction(g, Type{Nothing}, (Ref{typeof(g)},)) # redeining after use and it becomes fast (again)
@time m() # fast again!
  0.755742 seconds (371 allocations: 25.359 KiB) # slow
  0.752667 seconds                               # still slow
  0.031359 seconds                               # fast!
  0.031574 seconds                               # still fast!
  0.766401 seconds (371 allocations: 25.359 KiB) # slow again
  0.034139 seconds                               # fast again!

@StefanKarpinski
Copy link
Member

Looks superficially like garbage collection might make the difference.

@Micket
Copy link
Contributor

Micket commented May 10, 2020

I'm unable to reproduce this in latest git version. I tried to bisect to find out what fixed it, but, it took so long and was such a hassle with branches and dependency chances I gave up.

@vtjnash
Copy link
Member

vtjnash commented Oct 25, 2022

duplicate of #36977

@vtjnash vtjnash closed this as completed Oct 25, 2022
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

No branches or pull requests

4 participants