@@ -214,7 +214,7 @@ void MelderThread_run (
214214 autoINTVEC imax = zero_INTVEC (maxnCandidates);
215215 autoVEC localMean = zero_VEC (my ny);
216216
217- MelderThread_FOR (iframe)
217+ MelderThread_FOR (iframe) {
218218
219219 Pitch_Frame pitchFrame = & thy frames [iframe];
220220 Sound_into_PitchFrame (me, pitchFrame, maxnCandidates,
@@ -231,7 +231,7 @@ void MelderThread_run (
231231 );
232232 }
233233
234- MelderThread_ENDFOR
234+ } MelderThread_ENDFOR
235235
236236 Melder_progress (0.95, U"Sound to Pitch: path finder");
237237 return thee;
@@ -241,5 +241,86 @@ void MelderThread_run (
241241 }
242242*/
243243
244+ /*
245+ How to parallelize an existing analysis function
246+ ================================================
247+
248+ Suppose you have something like
249+
250+ autoPitch Sound_to_Pitch (Sound me) {
251+ try {
252+ autoPitch thee = ...;
253+ autoVEC window = ...; // the window shape
254+ autoMAT frame = zero_MAT (my ny, ...);
255+ autoNUMFourierTable fftTable = NUMFourierTable_create (...);
256+ autoVEC ac = zero_VEC (...);
257+ autoVEC rbuffer = zero_VEC (...);
258+ double *r = & rbuffer [...];
259+ autoVEC windowR = ...; // the autocorrelation of the window shape
260+ autoINTVEC imax = zero_INTVEC (maxnCandidates);
261+ autoVEC localMean = zero_VEC (my ny);
262+ autoMelderProgress progress (U"Sound to Pitch...");
263+ for (integer iframe = 1; iframe <= thy nx; iframe ++) {
264+ Pitch_Frame pitchFrame = & thy frames [iframe];
265+ const double fractionAnalysed = (double) iframe / thy nx;
266+ Melder_progress (0.1 + 0.8 * fractionAnalysed,
267+ U"Sound to Pitch: analysed ", iframe,
268+ U" out of ", thy nx, U" frames"
269+ );
270+ Sound_into_PitchFrame (me, pitchFrame, maxnCandidates,
271+ window.get(), windowR.get(),
272+ frame.get(), fftTable.get(), ac.get(),
273+ r, imax.get(), localMean.get()
274+ );
275+ }
276+ Melder_progress (0.95, U"Sound to Pitch: path finder");
277+ return thee;
278+ } catch (MelderError) {
279+ Melder_throw (me, U": pitch analysis not performed.");
280+ }
281+ }
282+
283+ The first step is to divide all those initializations into two sets:
284+ 1. the ones that all threads can use at the same time;
285+ these are:
286+ 1a. the target Pitch object, because each threads will write a separate part of it:
287+ autoPitch thee = ...;
288+ 1b. the "constant" things that are computed only once, before the loop over the frames:
289+ autoVEC window = ...; // the window shape
290+ autoVEC windowR = ...; // the autocorrelation of the window shape
291+ 1c. the initialization of the progress bar:
292+ autoMelderProgress progress (U"Sound to Pitch...");
293+ 2. the ones of which each thread need its own copy, like buffers:
294+ autoMAT frame = zero_MAT (my ny, ...);
295+ autoNUMFourierTable fftTable = NUMFourierTable_create (...);
296+ autoVEC ac = zero_VEC (...);
297+ autoVEC rbuffer = zero_VEC (...);
298+ double *r = & rbuffer [...];
299+ autoINTVEC imax = zero_INTVEC (maxnCandidates);
300+ autoVEC localMean = zero_VEC (my ny);
301+
302+ This reordering is the preparation. You then make the following simple changes:
303+ 3. between 1abc and 2 above you insert:
304+ MelderThread_PARALLELIZE (thy nx, 5, false, threadNumber)
305+ 4. instead of
306+ for (integer iframe = 1; iframe <= thy nx; iframe ++) {
307+ you write
308+ MelderThread_FOR (iframe) {
309+ 5. instead of the frame-loop-closing "}" you write
310+ } MelderThread_ENDFOR
311+ 6. you update the progress bar only in the master thread, by inserting
312+ if (threadNumber == 0) {
313+ and
314+ }
315+ 7. instead of computing the progress as
316+ const double fractionAnalysed = (double) iframe / thy nx;
317+ you write
318+ const double fractionAnalysed = MelderThread_ESTIMATE_PROGRESS (iframe);
319+ and you may reword the variable name and the text to acknowledge that this progress
320+ is just an estimate;
321+ 8. you tune the "thresholdNumberOfElementsPerThread" to what turns out to be fastest
322+ for low numbers of threads; see `manually/Sound_to_Pitch.praat` for an example.
323+ */
324+
244325/* End of file MelderThread.h */
245326#endif
0 commit comments