Skip to content

Commit 9e6cd3e

Browse files
authored
ENH: release global interpreter lock (#101)
* ENH: release global interpreter lock Release GIL when execute `Synthesis` `CheapTrick` `Dio` `Harvest` `D4C` `StoneMask`. Update World. NOTE: Updating the world is necessary to prevent a data race in `randn()`. Other small optimizations. * BLD: Fix build scripts
1 parent 343e6eb commit 9e6cd3e

File tree

2 files changed

+34
-28
lines changed

2 files changed

+34
-28
lines changed

pyworld/pyworld.pyx

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ cdef extern from "world/synthesis.h":
1111
int f0_length, const double * const *spectrogram,
1212
const double * const *aperiodicity,
1313
int fft_size, double frame_period,
14-
int fs, int y_length, double *y) except +
14+
int fs, int y_length, double *y) except + nogil
1515

1616

1717
cdef extern from "world/cheaptrick.h":
@@ -25,7 +25,7 @@ cdef extern from "world/cheaptrick.h":
2525
void InitializeCheapTrickOption(int fs, CheapTrickOption *option) except +
2626
void CheapTrick(const double *x, int x_length, int fs, const double *temporal_positions,
2727
const double *f0, int f0_length, const CheapTrickOption *option,
28-
double **spectrogram) except +
28+
double **spectrogram) except + nogil
2929

3030

3131
cdef extern from "world/dio.h":
@@ -40,7 +40,7 @@ cdef extern from "world/dio.h":
4040
void InitializeDioOption(DioOption *option) except +
4141
int GetSamplesForDIO(int fs, int x_length, double frame_period)
4242
void Dio(const double *x, int x_length, int fs, const DioOption *option,
43-
double *temporal_positions, double *f0) except +
43+
double *temporal_positions, double *f0) except + nogil
4444

4545

4646
cdef extern from "world/harvest.h":
@@ -52,7 +52,7 @@ cdef extern from "world/harvest.h":
5252
void InitializeHarvestOption(HarvestOption *option)
5353
int GetSamplesForHarvest(int fs, int x_length, double frame_period)
5454
void Harvest(const double *x, int x_length, int fs, const HarvestOption *option,
55-
double *temporal_positions, double *f0) except +
55+
double *temporal_positions, double *f0) except + nogil
5656

5757

5858
cdef extern from "world/d4c.h":
@@ -62,13 +62,13 @@ cdef extern from "world/d4c.h":
6262
void InitializeD4COption(D4COption *option) except +
6363
void D4C(const double *x, int x_length, int fs, const double *temporal_positions,
6464
const double *f0, int f0_length, int fft_size, const D4COption *option,
65-
double **aperiodicity) except +
65+
double **aperiodicity) except + nogil
6666

6767

6868
cdef extern from "world/stonemask.h":
6969
void StoneMask(const double *x, int x_length, int fs,
7070
const double *temporal_positions, const double *f0, int f0_length,
71-
double *refined_f0) except +
71+
double *refined_f0) except + nogil
7272

7373

7474
cdef extern from "world/codec.h":
@@ -147,7 +147,8 @@ def dio(np.ndarray[double, ndim=1, mode="c"] x not None, int fs,
147147
np.zeros(f0_length, dtype=np.dtype('float64'))
148148
cdef np.ndarray[double, ndim=1, mode="c"] temporal_positions = \
149149
np.zeros(f0_length, dtype=np.dtype('float64'))
150-
Dio(&x[0], x_length, fs, &option, &temporal_positions[0], &f0[0])
150+
with (nogil, cython.boundscheck(False)):
151+
Dio(&x[0], x_length, fs, &option, &temporal_positions[0], &f0[0])
151152
return f0, temporal_positions
152153

153154

@@ -190,7 +191,8 @@ def harvest(np.ndarray[double, ndim=1, mode="c"] x not None, int fs,
190191
np.zeros(f0_length, dtype=np.dtype('float64'))
191192
cdef np.ndarray[double, ndim=1, mode="c"] temporal_positions = \
192193
np.zeros(f0_length, dtype=np.dtype('float64'))
193-
Harvest(&x[0], x_length, fs, &option, &temporal_positions[0], &f0[0])
194+
with (nogil, cython.boundscheck(False)):
195+
Harvest(&x[0], x_length, fs, &option, &temporal_positions[0], &f0[0])
194196
return f0, temporal_positions
195197

196198

@@ -220,12 +222,13 @@ def stonemask(np.ndarray[double, ndim=1, mode="c"] x not None,
220222
cdef int f0_length = <int>len(f0)
221223
cdef np.ndarray[double, ndim=1, mode="c"] refined_f0 = \
222224
np.zeros(f0_length, dtype=np.dtype('float64'))
223-
StoneMask(&x[0], x_length, fs, &temporal_positions[0],
224-
&f0[0], f0_length, &refined_f0[0])
225+
with (nogil, cython.boundscheck(False)):
226+
StoneMask(&x[0], x_length, fs, &temporal_positions[0],
227+
&f0[0], f0_length, &refined_f0[0])
225228
return refined_f0
226229

227230

228-
def get_cheaptrick_fft_size(fs, f0_floor=default_f0_floor):
231+
def get_cheaptrick_fft_size(int fs, f0_floor=default_f0_floor):
229232
"""Calculate suitable FFT size for CheapTrick given F0 floor.
230233
231234
Parameters
@@ -247,7 +250,7 @@ def get_cheaptrick_fft_size(fs, f0_floor=default_f0_floor):
247250
cdef int fft_size = GetFFTSizeForCheapTrick(fs, &option)
248251
return fft_size
249252

250-
def get_cheaptrick_f0_floor(fs, fft_size):
253+
def get_cheaptrick_f0_floor(int fs, int fft_size):
251254
"""Calculates actual lower F0 limit for CheapTrick
252255
based on the sampling frequency and FFT size used. Whenever F0 is below
253256
this threshold the spectrum will be analyzed as if the frame is unvoiced
@@ -319,11 +322,12 @@ def cheaptrick(np.ndarray[double, ndim=1, mode="c"] x not None,
319322
cdef np.intp_t[:] tmp = np.zeros(f0_length, dtype=np.intp)
320323
cdef double **cpp_spectrogram = <double**> (<void*> &tmp[0])
321324
cdef np.intp_t i
322-
for i in range(f0_length):
323-
cpp_spectrogram[i] = &spectrogram[i, 0]
325+
with (nogil, cython.boundscheck(False)):
326+
for i in range(f0_length):
327+
cpp_spectrogram[i] = &spectrogram[i, 0]
324328

325-
CheapTrick(&x[0], x_length, fs, &temporal_positions[0],
326-
&f0[0], f0_length, &option, cpp_spectrogram)
329+
CheapTrick(&x[0], x_length, fs, &temporal_positions[0],
330+
&f0[0], f0_length, &option, cpp_spectrogram)
327331
return np.array(spectrogram, dtype=np.float64)
328332

329333

@@ -386,12 +390,13 @@ def d4c(np.ndarray[double, ndim=1, mode="c"] x not None,
386390
cdef np.intp_t[:] tmp = np.zeros(f0_length, dtype=np.intp)
387391
cdef double **cpp_aperiodicity = <double**> (<void*> &tmp[0])
388392
cdef np.intp_t i
389-
for i in range(f0_length):
390-
cpp_aperiodicity[i] = &aperiodicity[i, 0]
393+
with (nogil, cython.boundscheck(False)):
394+
for i in range(f0_length):
395+
cpp_aperiodicity[i] = &aperiodicity[i, 0]
391396

392-
D4C(&x[0], x_length, fs, &temporal_positions[0],
393-
&f0[0], f0_length, fft_size0, &option,
394-
cpp_aperiodicity)
397+
D4C(&x[0], x_length, fs, &temporal_positions[0],
398+
&f0[0], f0_length, fft_size0, &option,
399+
cpp_aperiodicity)
395400
return np.array(aperiodicity, dtype=np.float64)
396401

397402

@@ -433,7 +438,7 @@ def synthesize(np.ndarray[double, ndim=1, mode="c"] f0 not None,
433438
.format(spectrogram.shape[1], aperiodicity.shape[1]))
434439

435440
cdef int f0_length = <int>len(f0)
436-
y_length = int(f0_length * frame_period * fs / 1000)
441+
cdef int y_length = <int>(f0_length * frame_period * fs / 1000)
437442
cdef int fft_size = (<int>spectrogram.shape[1] - 1)*2
438443
cdef np.ndarray[double, ndim=1, mode="c"] y = \
439444
np.zeros(y_length, dtype=np.dtype('float64'))
@@ -445,12 +450,13 @@ def synthesize(np.ndarray[double, ndim=1, mode="c"] f0 not None,
445450
cdef double **cpp_spectrogram = <double**> (<void*> &tmp[0])
446451
cdef double **cpp_aperiodicity = <double**> (<void*> &tmp2[0])
447452
cdef np.intp_t i
448-
for i in range(f0_length):
449-
cpp_spectrogram[i] = &spectrogram0[i, 0]
450-
cpp_aperiodicity[i] = &aperiodicity0[i, 0]
453+
with (nogil, cython.boundscheck(False)):
454+
for i in range(f0_length):
455+
cpp_spectrogram[i] = &spectrogram0[i, 0]
456+
cpp_aperiodicity[i] = &aperiodicity0[i, 0]
451457

452-
Synthesis(&f0[0], f0_length, cpp_spectrogram,
453-
cpp_aperiodicity, fft_size, frame_period, fs, y_length, &y[0])
458+
Synthesis(&f0[0], f0_length, cpp_spectrogram,
459+
cpp_aperiodicity, fft_size, frame_period, fs, y_length, &y[0])
454460
return y
455461

456462

0 commit comments

Comments
 (0)