simonbyrne / libcg

MIT License
73 stars 7 forks source link

move to module, generate precompile statements #14

Closed simonbyrne closed 4 years ago

simonbyrne commented 4 years ago

@kristofferc I tried moving the @ccallables into a module, but it doesn't seem to work.

KristofferC commented 4 years ago

Since https://github.com/JuliaLang/julia/pull/35574 it should work. I will try it out.

KristofferC commented 4 years ago

Hm, it indeed doesn't look like it is in there

❯ objdump -t libcg.dylib | grep julia_cg
0000000000006d70 l     F __TEXT,__text  _jlcapi_julia_cg_33008
00000000002139d0 l     F __TEXT,__text  _julia_cglobal_tfunc_17765
0000000000006d70 g     F __TEXT,__text  _julia_cg
KristofferC commented 4 years ago

What doesn't work here? I tried this PR on 1.5.1 and I get:

❯ ./main
success

You mean that you still get precompile(Tuple{typeof(CG.julia_cg), Ptr{Nothing}, Ptr{Float64}, Ptr{Float64}, UInt64})?

KristofferC commented 4 years ago

Ok, I think I figured out that problem. It seems that @ccallable functions are sometimes not emitted even when running with --trace-compile=stderr. For example:

~/JuliaPkgs/libcg sb/module*
❯ julia --project --trace-compile=stderr generate_precompile.jl 2>&1 | grep julia_cg

~/JuliaPkgs/libcg sb/module*

But they also "hide" the functions they call from being emitted, so the end result is that nothing gets precompiled. So making the ccallble a very simple wrapper function and calling the Julia function works around it:

diff --git a/generate_precompile.jl b/generate_precompile.jl
index a670302..a0824f8 100644
--- a/generate_precompile.jl
+++ b/generate_precompile.jl
@@ -17,4 +17,4 @@ end
 b = ones(len)
 x = zeros(len)

-CG.julia_cg(@cfunction(laplace,Cint,(Ptr{Float64}, Ptr{Float64})), pointer(x), pointer(b), Csize_t(len))
+CG._julia_cg(@cfunction(laplace,Cint,(Ptr{Float64}, Ptr{Float64})), pointer(x), pointer(b), Csize_t(len))
diff --git a/src/CG.jl b/src/CG.jl
index 32bbb8b..39b8809 100644
--- a/src/CG.jl
+++ b/src/CG.jl
@@ -25,6 +25,11 @@ end

 Base.@ccallable function julia_cg(fptr::Ptr{Cvoid}, cx::Ptr{Cdouble}, cb::Ptr{Cdouble}, len::Csize_t)::Cint
+    _julia_cg(fptr, cx, cb, len)
+end
+
+# Call this in the precompile script
+function _julia_cg(fptr, cx, cb, len)
     try
         x = unsafe_wrap(Array, cx, (len,))
         b = unsafe_wrap(Array, cb, (len,))

With this I get

❯ julia --project --trace-compile=stderr generate_precompile.jl 2>&1 | grep julia_cg
precompile(Tuple{typeof(CG._julia_cg), Ptr{Nothing}, Ptr{Float64}, Ptr{Float64}, UInt64})

and making the executable:

❯ time ./main
success./main  0.06s user 0.03s system 96% cpu 0.089 total
simonbyrne commented 4 years ago

@KristofferC The problem seems to be that @ccallables defined inside modules aren't being exported by the dynamic library.

simonbyrne commented 4 years ago

@KristofferC The problem seems to be that @ccallables defined inside modules aren't being exported by the dynamic library.

Ah, that was just a Julia 1.4 issue.

Okay, it still looks like the @ccallable entrypoint is not being precompiled (but everything else is): https://github.com/simonbyrne/libcg/pull/14/checks?check_run_id=1150489900#step:7:4

KristofferC commented 4 years ago

Ah, that was just a Julia 1.4 issue.

Yep, got fixed in 1.5 in https://github.com/JuliaLang/julia/pull/35574

simonbyrne commented 4 years ago

@KristofferC any idea why the @ccallable entrypoint isn't being precompiled?:

https://github.com/simonbyrne/libcg/pull/14/checks?check_run_id=1150489900#step:7:4

KristofferC commented 4 years ago

The reason is that it doesn't show up in the output when running with --trace-compile and the sysimage is building. Why that happens I don't know. However, since it just passes the arguments to another function is should be extremely quick to compile.

simonbyrne commented 4 years ago

I agree it's odd. It seems I can work around this by adding the C entry point manually to a precompile_statements_file.