via environment variable OMP_NUM_THREADS or via omp_set_num_threads(). The function 'hypre_NumThreads()' returns the number of threads.
264 lines
6.4 KiB
C
264 lines
6.4 KiB
C
/*BHEADER**********************************************************************
|
|
* See the file COPYRIGHT_and_DISCLAIMER for a complete copyright
|
|
* notice, contact person, and disclaimer.
|
|
*
|
|
* $Revision$
|
|
*********************************************************************EHEADER*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "utilities.h"
|
|
|
|
#if defined(HYPRE_USING_OPENMP) || defined (HYPRE_USING_PGCC_SMP)
|
|
|
|
int
|
|
hypre_NumThreads( )
|
|
{
|
|
int num_threads;
|
|
|
|
#ifdef HYPRE_USING_OPENMP
|
|
#pragma omp parallel
|
|
num_threads = omp_get_num_threads();
|
|
#endif
|
|
#ifdef HYPRE_USING_PGCC_SMP
|
|
num_threads = 2;
|
|
#endif
|
|
|
|
return num_threads;
|
|
}
|
|
|
|
#endif
|
|
|
|
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
|
|
/* The pthreads stuff needs to be reworked */
|
|
|
|
#define HYPRE_THREAD_GLOBALS
|
|
|
|
#ifdef HYPRE_USE_PTHREADS
|
|
|
|
#ifdef HYPRE_USE_UMALLOC
|
|
#include "umalloc_local.h"
|
|
#endif
|
|
|
|
int iteration_counter = 0;
|
|
volatile int hypre_thread_counter;
|
|
volatile int work_continue = 1;
|
|
|
|
|
|
int HYPRE_InitPthreads( int num_threads )
|
|
{
|
|
int err;
|
|
int i;
|
|
hypre_qptr =
|
|
(hypre_workqueue_t) malloc(sizeof(struct hypre_workqueue_struct));
|
|
|
|
hypre_NumThreads = num_threads;
|
|
initial_thread = pthread_self();
|
|
|
|
if (hypre_qptr != NULL) {
|
|
pthread_mutex_init(&hypre_qptr->lock, NULL);
|
|
pthread_cond_init(&hypre_qptr->work_wait, NULL);
|
|
pthread_cond_init(&hypre_qptr->finish_wait, NULL);
|
|
hypre_qptr->n_working = hypre_qptr->n_waiting = hypre_qptr->n_queue = 0;
|
|
hypre_qptr->inp = hypre_qptr->outp = 0;
|
|
for (i=0; i < hypre_NumThreads; i++) {
|
|
#ifdef HYPRE_USE_UMALLOC
|
|
/* Get initial area to start heap */
|
|
assert ((_uinitial_block[i] = malloc(INITIAL_HEAP_SIZE))!=NULL);
|
|
|
|
/* Create a user heap */
|
|
assert ((_uparam[i].myheap = _ucreate(initial_block[i],
|
|
INITIAL_HEAP_SIZE,
|
|
_BLOCK_CLEAN,
|
|
_HEAP_REGULAR,
|
|
_uget_fn,
|
|
_urelease_fn)) != NULL);
|
|
#endif
|
|
err=pthread_create(&hypre_thread[i], NULL,
|
|
(void *(*)(void *))hypre_pthread_worker,
|
|
(void *)i);
|
|
assert(err == 0);
|
|
}
|
|
}
|
|
|
|
pthread_mutex_init(&hypre_mutex_boxloops, NULL);
|
|
pthread_mutex_init(&mpi_mtx, NULL);
|
|
pthread_mutex_init(&talloc_mtx, NULL);
|
|
pthread_mutex_init(&time_mtx, NULL);
|
|
pthread_mutex_init(&worker_mtx, NULL);
|
|
hypre_thread_counter = 0;
|
|
hypre_thread_release = 0;
|
|
|
|
return (err);
|
|
}
|
|
|
|
void hypre_StopWorker(void *i)
|
|
{
|
|
work_continue = 0;
|
|
}
|
|
|
|
void HYPRE_DestroyPthreads( void )
|
|
{
|
|
int i;
|
|
void *status;
|
|
|
|
for (i=0; i < hypre_NumThreads; i++) {
|
|
hypre_work_put(hypre_StopWorker, (void *) &i);
|
|
}
|
|
|
|
#ifdef HYPRE_USE_UMALLOC
|
|
for (i=0; i<hypre_NumThreads; i++)
|
|
{
|
|
_udestroy (_uparam[i].myheap, _FORCE);
|
|
}
|
|
#endif
|
|
|
|
for (i=0; i<hypre_NumThreads; i++)
|
|
pthread_join(hypre_thread[i], &status);
|
|
pthread_mutex_destroy(&hypre_qptr->lock);
|
|
pthread_mutex_destroy(&hypre_mutex_boxloops);
|
|
pthread_mutex_destroy(&mpi_mtx);
|
|
pthread_mutex_destroy(&talloc_mtx);
|
|
pthread_mutex_destroy(&time_mtx);
|
|
pthread_mutex_destroy(&worker_mtx);
|
|
pthread_cond_destroy(&hypre_qptr->work_wait);
|
|
pthread_cond_destroy(&hypre_qptr->finish_wait);
|
|
free (hypre_qptr);
|
|
}
|
|
|
|
|
|
void hypre_pthread_worker( int threadid )
|
|
{
|
|
void *argptr;
|
|
hypre_work_proc_t funcptr;
|
|
|
|
pthread_mutex_lock(&hypre_qptr->lock);
|
|
|
|
hypre_qptr->n_working++;
|
|
|
|
while(work_continue) {
|
|
while (hypre_qptr->n_queue == 0) {
|
|
if (--hypre_qptr->n_working == 0)
|
|
pthread_cond_signal(&hypre_qptr->finish_wait);
|
|
hypre_qptr->n_waiting++;
|
|
pthread_cond_wait(&hypre_qptr->work_wait, &hypre_qptr->lock);
|
|
hypre_qptr->n_waiting--;
|
|
hypre_qptr->n_working++;
|
|
}
|
|
hypre_qptr->n_queue--;
|
|
funcptr = hypre_qptr->worker_proc_queue[hypre_qptr->outp];
|
|
argptr = hypre_qptr->argqueue[hypre_qptr->outp];
|
|
|
|
hypre_qptr->outp = (hypre_qptr->outp + 1) % MAX_QUEUE;
|
|
|
|
pthread_mutex_unlock(&hypre_qptr->lock);
|
|
|
|
(*funcptr)(argptr);
|
|
|
|
hypre_barrier(&worker_mtx, 0);
|
|
|
|
if (work_continue)
|
|
pthread_mutex_lock(&hypre_qptr->lock);
|
|
}
|
|
}
|
|
|
|
void
|
|
hypre_work_put( hypre_work_proc_t funcptr, void *argptr )
|
|
{
|
|
pthread_mutex_lock(&hypre_qptr->lock);
|
|
if (hypre_qptr->n_waiting) {
|
|
/* idle workers to be awakened */
|
|
pthread_cond_signal(&hypre_qptr->work_wait);
|
|
}
|
|
assert(hypre_qptr->n_queue != MAX_QUEUE);
|
|
|
|
hypre_qptr->n_queue++;
|
|
hypre_qptr->worker_proc_queue[hypre_qptr->inp] = funcptr;
|
|
hypre_qptr->argqueue[hypre_qptr->inp] = argptr;
|
|
hypre_qptr->inp = (hypre_qptr->inp + 1) % MAX_QUEUE;
|
|
pthread_mutex_unlock(&hypre_qptr->lock);
|
|
}
|
|
|
|
|
|
/* Wait until all work is done and workers quiesce. */
|
|
void
|
|
hypre_work_wait( void )
|
|
{
|
|
pthread_mutex_lock(&hypre_qptr->lock);
|
|
while(hypre_qptr->n_queue !=0 || hypre_qptr->n_working != 0)
|
|
pthread_cond_wait(&hypre_qptr->finish_wait, &hypre_qptr->lock);
|
|
pthread_mutex_unlock(&hypre_qptr->lock);
|
|
}
|
|
|
|
|
|
int
|
|
hypre_fetch_and_add( int *w )
|
|
{
|
|
int temp;
|
|
|
|
temp = *w;
|
|
*w += 1;
|
|
|
|
return temp;
|
|
}
|
|
|
|
int
|
|
ifetchadd( int *w, pthread_mutex_t *mutex_fetchadd )
|
|
{
|
|
int n;
|
|
|
|
pthread_mutex_lock(mutex_fetchadd);
|
|
n = *w;
|
|
*w += 1;
|
|
pthread_mutex_unlock(mutex_fetchadd);
|
|
|
|
return n;
|
|
}
|
|
|
|
static volatile int thb_count = 0;
|
|
static volatile int thb_release = 0;
|
|
|
|
void hypre_barrier(pthread_mutex_t *mtx, int unthreaded)
|
|
{
|
|
if (!unthreaded) {
|
|
pthread_mutex_lock(mtx);
|
|
thb_count++;
|
|
|
|
if (thb_count < hypre_NumThreads) {
|
|
pthread_mutex_unlock(mtx);
|
|
while (!thb_release);
|
|
pthread_mutex_lock(mtx);
|
|
thb_count--;
|
|
pthread_mutex_unlock(mtx);
|
|
while (thb_release);
|
|
}
|
|
else if (thb_count == hypre_NumThreads) {
|
|
thb_count--;
|
|
pthread_mutex_unlock(mtx);
|
|
thb_release++;
|
|
while (thb_count);
|
|
thb_release = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
hypre_GetThreadID( void )
|
|
{
|
|
int i;
|
|
|
|
if (pthread_equal(pthread_self(), initial_thread))
|
|
return hypre_NumThreads;
|
|
|
|
for (i = 0; i < hypre_NumThreads; i++)
|
|
{
|
|
if (pthread_equal(pthread_self(), hypre_thread[i]))
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
#endif
|
|
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
|