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