cannam@95: /* cannam@95: * Copyright (c) 2003, 2007-11 Matteo Frigo cannam@95: * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology cannam@95: * cannam@95: * This program is free software; you can redistribute it and/or modify cannam@95: * it under the terms of the GNU General Public License as published by cannam@95: * the Free Software Foundation; either version 2 of the License, or cannam@95: * (at your option) any later version. cannam@95: * cannam@95: * This program is distributed in the hope that it will be useful, cannam@95: * but WITHOUT ANY WARRANTY; without even the implied warranty of cannam@95: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the cannam@95: * GNU General Public License for more details. cannam@95: * cannam@95: * You should have received a copy of the GNU General Public License cannam@95: * along with this program; if not, write to the Free Software cannam@95: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA cannam@95: * cannam@95: */ cannam@95: cannam@95: /* openmp.c: thread spawning via OpenMP */ cannam@95: cannam@95: #include "threads.h" cannam@95: cannam@95: #if !defined(_OPENMP) cannam@95: #error OpenMP enabled but not using an OpenMP compiler cannam@95: #endif cannam@95: cannam@95: int X(ithreads_init)(void) cannam@95: { cannam@95: return 0; /* no error */ cannam@95: } cannam@95: cannam@95: /* Distribute a loop from 0 to loopmax-1 over nthreads threads. cannam@95: proc(d) is called to execute a block of iterations from d->min cannam@95: to d->max-1. d->thr_num indicate the number of the thread cannam@95: that is executing proc (from 0 to nthreads-1), and d->data is cannam@95: the same as the data parameter passed to X(spawn_loop). cannam@95: cannam@95: This function returns only after all the threads have completed. */ cannam@95: void X(spawn_loop)(int loopmax, int nthr, spawn_function proc, void *data) cannam@95: { cannam@95: int block_size; cannam@95: spawn_data d; cannam@95: int i; cannam@95: cannam@95: A(loopmax >= 0); cannam@95: A(nthr > 0); cannam@95: A(proc); cannam@95: cannam@95: if (!loopmax) return; cannam@95: cannam@95: /* Choose the block size and number of threads in order to (1) cannam@95: minimize the critical path and (2) use the fewest threads that cannam@95: achieve the same critical path (to minimize overhead). cannam@95: e.g. if loopmax is 5 and nthr is 4, we should use only 3 cannam@95: threads with block sizes of 2, 2, and 1. */ cannam@95: block_size = (loopmax + nthr - 1) / nthr; cannam@95: nthr = (loopmax + block_size - 1) / block_size; cannam@95: cannam@95: THREAD_ON; /* prevent debugging mode from failing under threads */ cannam@95: #pragma omp parallel for private(d) cannam@95: for (i = 0; i < nthr; ++i) { cannam@95: d.max = (d.min = i * block_size) + block_size; cannam@95: if (d.max > loopmax) cannam@95: d.max = loopmax; cannam@95: d.thr_num = i; cannam@95: d.data = data; cannam@95: proc(&d); cannam@95: } cannam@95: THREAD_OFF; /* prevent debugging mode from failing under threads */ cannam@95: } cannam@95: cannam@95: void X(threads_cleanup)(void) cannam@95: { cannam@95: }