Skip to content

Conversation

@johroj
Copy link

@johroj johroj commented Nov 15, 2025

This PR is the result a series of fixes I implemented for FFTW to play nicely with juliac --trim. Sort of solves #319. Its not perfect, but I think it should be better than nothing for those of us who depend on FFTW for making meaningful evaluations of --trim.

Library Loading

This temporarily solves the issues surrounding the current way of loading libraries, which should be replaced in the future (as suggested by the comment at https://github.com/JuliaMath/FFTW.jl/blob/master/src/FFTW.jl#L33)

  1. Add type parameter to FakeLazyLibrary for type stability.

And two issues related to ccall(::FakeLazyLibrary, ...) forwarding the call to dlopen(::FakeLazyLibrary):

  1. Call dlopen in __init__to ensure it gets precompiled (which won't happen by default since it is only called from the C layer).
  2. Manually running Base.unsafe_store!(cglobal(:jl_libdl_dlopen_func, Any), dlopen) before calling fft is necessary in all entrypoints for ccall to become aware of dlopen. Theoretically this could be done in FFTW, but I think its best to avoid messing with Julias internal mechanisms for applications outside of experimenting with --trim.

The related code on the Julia side is https://github.com/JuliaLang/julia/blob/f5f4c0174ed51de3811da861c0bf01b4e9f10972/src/runtime_ccall.cpp#L86 and https://github.com/JuliaLang/julia/blob/41e50a77e6f6b9b2cfea9056529224c56923dac6/base/libdl.jl#L488.

Other Type-Instability Fixes

Some additional type instabilities that are probably worth fixing even if the library loading mechanism is updated in the future:

  1. Add FFTWPlanDestructor for type stable destruction.
  2. Replace an occurence of string(args...) with join([str1, str2, ...]).
  3. Use a minimal type-stable equivalent of @sync in spawnloop. I would be happy for a better proposal for how to solve this. The core issue is that spawnloop is precompiled even if only one thread is used. The internal use of a Channel{Any} in @sync makes this problematic. Compared to https://github.com/JuliaLang/julia/blob/29a4bbf950aefa6116b296d48ef966ab36c5ca84/base/task.jl#L584, the only significant difference I can only see is that the real @sync gives a nicer handling and representation of errors. I hope I did not miss anything. Worst case, we could drop this from the PR and leave it to the user to override spawnloop using --trim.

Example

With this PR the following will build with --trim and run without errors:

using FFTW
using Libdl

function @main(ARGS)
    # Must be called before anything from FFTW
    Base.unsafe_store!(cglobal(:jl_libdl_dlopen_func, Any), dlopen)

    x = [1., 2., 3.]
    println(Core.stdout, "rfft([$(join(x, ", "))]) = [$(join(rfft(x), ", "))]")
    return 0
end

@codecov
Copy link

codecov bot commented Nov 15, 2025

Codecov Report

❌ Patch coverage is 95.23810% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 74.40%. Comparing base (062fddb) to head (b06d563).

Files with missing lines Patch % Lines
src/fft.jl 87.50% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #327      +/-   ##
==========================================
+ Coverage   73.64%   74.40%   +0.76%     
==========================================
  Files           5        5              
  Lines         535      547      +12     
==========================================
+ Hits          394      407      +13     
+ Misses        141      140       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@johroj johroj marked this pull request as ready for review November 15, 2025 13:51
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