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