@@ -84,6 +84,27 @@ alignment_of(A::FakeArray) = Int32(0)
84
84
85
85
# # Julia wrappers around FFTW functions
86
86
87
+ # _init_() must be called before any FFTW planning routine.
88
+ # -- Once FFTW is split into its own module, this can be called
89
+ # in the module __init__(), but for now we must call it lazily
90
+ # in every routine that might initialize the FFTW planner.
91
+ # -- This initializes FFTW's threads support (defaulting to 1 thread).
92
+ # If this isn't called before the FFTW planner is created, then
93
+ # FFTW's threads algorithms won't be registered or used at all.
94
+ # (Previously, we called fftw_cleanup, but this invalidated existing
95
+ # plans, causing issue #19892.)
96
+ const threads_initialized = Ref (false )
97
+ function _init_ ()
98
+ if ! threads_initialized[]
99
+ stat = ccall ((:fftw_init_threads ,libfftw), Int32, ())
100
+ statf = ccall ((:fftwf_init_threads ,libfftwf), Int32, ())
101
+ if stat == 0 || statf == 0
102
+ error (" could not initialize FFTW threads" )
103
+ end
104
+ threads_initialized[] = true
105
+ end
106
+ end
107
+
87
108
# Wisdom
88
109
89
110
# Import and export wisdom to/from a single file for all precisions,
@@ -96,6 +117,7 @@ alignment_of(A::FakeArray) = Int32(0)
96
117
# FFTW's api/import-wisdom-from-file.c file].
97
118
98
119
function export_wisdom (fname:: AbstractString )
120
+ _init_ ()
99
121
f = ccall (:fopen , Ptr{Void}, (Cstring,Cstring), fname, :w )
100
122
systemerror (" could not open wisdom file $fname for writing" , f == C_NULL )
101
123
ccall ((:fftw_export_wisdom_to_file ,libfftw), Void, (Ptr{Void},), f)
@@ -105,6 +127,7 @@ function export_wisdom(fname::AbstractString)
105
127
end
106
128
107
129
function import_wisdom (fname:: AbstractString )
130
+ _init_ ()
108
131
f = ccall (:fopen , Ptr{Void}, (Cstring,Cstring), fname, :r )
109
132
systemerror (" could not open wisdom file $fname for reading" , f == C_NULL )
110
133
if ccall ((:fftw_import_wisdom_from_file ,libfftw),Int32,(Ptr{Void},),f)== 0 ||
@@ -115,32 +138,23 @@ function import_wisdom(fname::AbstractString)
115
138
end
116
139
117
140
function import_system_wisdom ()
141
+ _init_ ()
118
142
if ccall ((:fftw_import_system_wisdom ,libfftw), Int32, ()) == 0 ||
119
143
ccall ((:fftwf_import_system_wisdom ,libfftwf), Int32, ()) == 0
120
144
error (" failed to import system wisdom" )
121
145
end
122
146
end
123
147
124
148
function forget_wisdom ()
149
+ _init_ ()
125
150
ccall ((:fftw_forget_wisdom ,libfftw), Void, ())
126
151
ccall ((:fftwf_forget_wisdom ,libfftwf), Void, ())
127
152
end
128
153
129
154
# Threads
130
155
131
- const threads_initialized = Ref (false )
132
156
function set_num_threads (nthreads:: Integer )
133
- if ! threads_initialized[]
134
- # must forget wisdom if any FFTW routines have been called
135
- # (don't call fftw_cleanup, since that would invalidate existing plans)
136
- forget_wisdom ()
137
- stat = ccall ((:fftw_init_threads ,libfftw), Int32, ())
138
- statf = ccall ((:fftwf_init_threads ,libfftwf), Int32, ())
139
- if stat == 0 || statf == 0
140
- error (" could not initialize FFTW threads" )
141
- end
142
- threads_initialized[] = true
143
- end
157
+ _init_ ()
144
158
ccall ((:fftw_plan_with_nthreads ,libfftw), Void, (Int32,), nthreads)
145
159
ccall ((:fftwf_plan_with_nthreads ,libfftwf), Void, (Int32,), nthreads)
146
160
end
@@ -154,11 +168,15 @@ const PlanPtr = Ptr{fftw_plan_struct}
154
168
155
169
const NO_TIMELIMIT = - 1.0 # from fftw3.h
156
170
157
- set_timelimit (precision:: fftwTypeDouble ,seconds) =
171
+ function set_timelimit (precision:: fftwTypeDouble ,seconds)
172
+ _init_ ()
158
173
ccall ((:fftw_set_timelimit ,libfftw), Void, (Float64,), seconds)
174
+ end
159
175
160
- set_timelimit (precision:: fftwTypeSingle ,seconds) =
176
+ function set_timelimit (precision:: fftwTypeSingle ,seconds)
177
+ _init_ ()
161
178
ccall ((:fftwf_set_timelimit ,libfftwf), Void, (Float64,), seconds)
179
+ end
162
180
163
181
# Array alignment mod 16:
164
182
# FFTW plans may depend on the alignment of the array mod 16 bytes,
0 commit comments