From 29f5b628317bcf83ddc5bfeaec92108b6bb1e89d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 26 Jul 2020 18:39:53 +0200 Subject: Switch to external threadpool library. --- Makefile | 3 +- init.c | 9 +-- nlsolve.c | 11 ++-- nlsolve.h | 5 +- pssolve.c | 17 +++--- pssolve.h | 5 +- threadpool.c | 178 ----------------------------------------------------------- threadpool.h | 32 ----------- 8 files changed, 25 insertions(+), 235 deletions(-) delete mode 100644 threadpool.c delete mode 100644 threadpool.h diff --git a/Makefile b/Makefile index 457489d..fae7da1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ TARGET = libteukolskydata.so CFLAGS = -std=c99 -D_XOPEN_SOURCE=700 -fPIC -g -I. -TARGET_LDFLAGS = -Wl,--version-script=libteukolskydata.v -shared -lm -llapacke -pthread +TARGET_LDFLAGS = -Wl,--version-script=libteukolskydata.v -shared -lm -llapacke -lthreadpool TEST_LIBS = -lm -llapacke -lcblas -lpthread CC = cc @@ -14,7 +14,6 @@ OBJS = basis.o \ nlsolve.o \ pssolve.o \ td_constraints.o \ - threadpool.o \ TESTPROGS = nlsolve \ pssolve diff --git a/init.c b/init.c index e39d1b1..f4d130f 100644 --- a/init.c +++ b/init.c @@ -31,6 +31,8 @@ #include #endif +#include + #include "basis.h" #include "common.h" #include "cpu.h" @@ -38,7 +40,6 @@ #include "nlsolve.h" #include "td_constraints.h" #include "teukolsky_data.h" -#include "threadpool.h" #define NB_EQUATIONS 3 @@ -46,7 +47,7 @@ typedef struct TDPriv { unsigned int basis_order[NB_EQUATIONS][2]; BasisSetContext *basis[NB_EQUATIONS][2]; - ThreadPoolContext *tp; + TPContext *tp; TDLogger logger; double *coeffs; @@ -152,7 +153,7 @@ static int teukolsky_init_check_options(TDContext *td) td->nb_threads = 1; } - ret = tdi_threadpool_init(&s->tp, td->nb_threads); + ret = tp_init(&s->tp, td->nb_threads); if (ret < 0) return ret; @@ -487,7 +488,7 @@ void td_context_free(TDContext **ptd) s = td->priv; - tdi_threadpool_free(&s->tp); + tp_free(&s->tp); #if HAVE_OPENCL if (s->ocl_queue) diff --git a/nlsolve.c b/nlsolve.c index d1ab0ff..6f89e8b 100644 --- a/nlsolve.c +++ b/nlsolve.c @@ -34,12 +34,13 @@ #include #endif +#include + #include "basis.h" #include "common.h" #include "log.h" #include "pssolve.h" #include "nlsolve.h" -#include "threadpool.h" #define NB_COEFFS(td) (td->nb_coeffs[0] * td->nb_coeffs[1]) #define NB_COLLOC_POINTS(td) (td->nb_colloc_points[0] * td->nb_colloc_points[1]) @@ -87,8 +88,8 @@ struct NLSolvePriv { double *delta; double *rhs; - ThreadPoolContext *tp; - ThreadPoolContext *tp_internal; + TPContext *tp; + TPContext *tp_internal; uint64_t solve_count; uint64_t solve_time; @@ -455,7 +456,7 @@ int tdi_nlsolve_context_init(NLSolveContext *ctx) if (ctx->tp) { s->tp = ctx->tp; } else { - ret = tdi_threadpool_init(&s->tp_internal, 1); + ret = tp_init(&s->tp_internal, 1); if (ret < 0) return ret; s->tp = s->tp_internal; @@ -545,7 +546,7 @@ void tdi_nlsolve_context_free(NLSolveContext **pctx) tdi_pssolve_context_free(&ctx->priv->ps_ctx); - tdi_threadpool_free(&ctx->priv->tp_internal); + tp_free(&ctx->priv->tp_internal); } free(ctx->priv); diff --git a/nlsolve.h b/nlsolve.h index 426cb24..eaa2b64 100644 --- a/nlsolve.h +++ b/nlsolve.h @@ -19,10 +19,11 @@ #ifndef TEUKOLSKY_DATA_NLSOLVE_H #define TEUKOLSKY_DATA_NLSOLVE_H +#include + #include "basis.h" #include "log.h" #include "pssolve.h" -#include "threadpool.h" typedef struct NLSolvePriv NLSolvePriv; @@ -43,7 +44,7 @@ typedef struct NLSolveContext { * caller before tdi_nlsolve_context_init(), otherwise a single thread will * be used. */ - ThreadPoolContext *tp; + TPContext *tp; /** * Number of equations/unknown functions in the set. diff --git a/pssolve.c b/pssolve.c index 28333e2..36e09cf 100644 --- a/pssolve.c +++ b/pssolve.c @@ -28,12 +28,12 @@ #include #include +#include #include "bicgstab.h" #include "common.h" #include "log.h" #include "pssolve.h" -#include "threadpool.h" #define NB_COEFFS(eq_ctx) ((eq_ctx)->nb_coeffs[0] * (eq_ctx)->nb_coeffs[1]) #define NB_COLLOC_POINTS(eq_ctx) ((eq_ctx)->nb_colloc_points[0] * (eq_ctx)->nb_colloc_points[1]) @@ -58,8 +58,8 @@ struct PSSolvePriv { int *ipiv; double *mat; - ThreadPoolContext *tp; - ThreadPoolContext *tp_internal; + TPContext *tp; + TPContext *tp_internal; }; typedef struct ConstructMatrixThread { @@ -70,9 +70,7 @@ typedef struct ConstructMatrixThread { unsigned int var_idx; } ConstructMatrixThread; -static void construct_matrix(void *arg, - unsigned int job_idx, unsigned int nb_jobs, - unsigned int thread_idx, unsigned int nb_threads) +static void construct_matrix(void *arg, unsigned int job_idx, unsigned int thread_idx) { ConstructMatrixThread *cmt = arg; const PSEquationContext *eq_ctx = cmt->eq_ctx; @@ -192,8 +190,7 @@ int tdi_pssolve_solve(PSSolveContext *ctx, .mat_stride = s->nb_coeffs, .var_idx = j, }; - tdi_threadpool_execute(s->tp, NB_COEFFS(&s->eqs[j]), construct_matrix, - &thread); + tp_execute(s->tp, NB_COEFFS(&s->eqs[j]), construct_matrix, &thread); mat += NB_COEFFS(&s->eqs[j]) * s->nb_coeffs; } } @@ -347,7 +344,7 @@ int tdi_pssolve_context_init(PSSolveContext *ctx) if (ctx->tp) { s->tp = ctx->tp; } else { - ret = tdi_threadpool_init(&s->tp_internal, 1); + ret = tp_init(&s->tp_internal, 1); if (ret < 0) return ret; s->tp = s->tp_internal; @@ -487,7 +484,7 @@ void tdi_pssolve_context_free(PSSolveContext **pctx) free(ctx->priv->mat); tdi_bicgstab_context_free(&ctx->priv->bicgstab); - tdi_threadpool_free(&ctx->priv->tp_internal); + tp_free(&ctx->priv->tp_internal); } free(ctx->priv); diff --git a/pssolve.h b/pssolve.h index 6d5d1c0..160e179 100644 --- a/pssolve.h +++ b/pssolve.h @@ -51,9 +51,10 @@ typedef void* cl_command_queue; #include +#include + #include "basis.h" #include "log.h" -#include "threadpool.h" enum PSSolveDiffOrder { PSSOLVE_DIFF_ORDER_00, @@ -122,7 +123,7 @@ typedef struct PSSolveContext { * caller before tdi_pssolve_context_init(), otherwise a single thread will * be used. */ - ThreadPoolContext *tp; + TPContext *tp; cl_context ocl_ctx; cl_command_queue ocl_queue; diff --git a/threadpool.c b/threadpool.c deleted file mode 100644 index ab5cf1d..0000000 --- a/threadpool.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2016 Anton Khirnov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include - -#include "cpu.h" -#include "threadpool.h" - -typedef struct WorkerContext { - ThreadPoolContext *parent; - pthread_t thread; - unsigned int idx; -} WorkerContext; - -struct ThreadPoolContext { - WorkerContext *workers; - unsigned int nb_workers; - - pthread_mutex_t mutex; - pthread_cond_t cond; - void (*func)(void *arg, - unsigned int job_idx, unsigned int nb_jobs, - unsigned int thread_idx, unsigned int nb_threads); - void *func_arg; - int next_job; - int nb_jobs; - int nb_jobs_finished; - - int finish; -}; - -void *worker_thread(void *arg) -{ - WorkerContext *w = arg; - ThreadPoolContext *ctx = w->parent; - int nb_jobs, job_idx; - - while (1) { - pthread_mutex_lock(&ctx->mutex); - while (!ctx->finish && ctx->next_job >= ctx->nb_jobs) - pthread_cond_wait(&ctx->cond, &ctx->mutex); - - if (ctx->finish) { - pthread_mutex_unlock(&ctx->mutex); - break; - } - - nb_jobs = ctx->nb_jobs; - job_idx = ctx->next_job++; - - pthread_mutex_unlock(&ctx->mutex); - - ctx->func(ctx->func_arg, job_idx, nb_jobs, w->idx, ctx->nb_workers); - - pthread_mutex_lock(&ctx->mutex); - - ctx->nb_jobs_finished++; - - pthread_cond_broadcast(&ctx->cond); - pthread_mutex_unlock(&ctx->mutex); - } - return NULL; -} - -int tdi_threadpool_init(ThreadPoolContext **pctx, unsigned int nb_threads) -{ - ThreadPoolContext *ctx; - int ret = 0; - - if (!nb_threads) { - nb_threads = tdi_cpu_count(); - if (!nb_threads) - return -ENOSYS; - } - - ctx = calloc(1, sizeof(*ctx)); - if (!ctx) - return -ENOMEM; - - pthread_mutex_init(&ctx->mutex, NULL); - pthread_cond_init(&ctx->cond, NULL); - - ctx->workers = calloc(nb_threads, sizeof(*ctx->workers)); - if (!ctx->workers) { - ret = -ENOMEM; - goto fail; - } - - for (int i = 0; i < nb_threads; i++) { - WorkerContext *w = &ctx->workers[i]; - - w->idx = i; - w->parent = ctx; - - ret = pthread_create(&w->thread, NULL, worker_thread, w); - if (ret) { - ret = -ret; - goto fail; - } - - ctx->nb_workers++; - } - - - *pctx = ctx; - return 0; -fail: - tdi_threadpool_free(&ctx); - return ret; -} - -void tdi_threadpool_free(ThreadPoolContext **pctx) -{ - ThreadPoolContext *ctx = *pctx; - - if (!ctx) - return; - - pthread_mutex_lock(&ctx->mutex); - ctx->finish = 1; - pthread_cond_broadcast(&ctx->cond); - pthread_mutex_unlock(&ctx->mutex); - - - for (int i = 0; i < ctx->nb_workers; i++) { - WorkerContext *w = &ctx->workers[i]; - pthread_join(w->thread, NULL); - } - - pthread_mutex_destroy(&ctx->mutex); - pthread_cond_destroy(&ctx->cond); - - free(ctx->workers); - - free(ctx); - *pctx = NULL; -} - -void tdi_threadpool_execute(ThreadPoolContext *ctx, unsigned int nb_jobs, - void (*func)(void *arg, - unsigned int job_idx, unsigned int nb_jobs, - unsigned int thread_idx, unsigned int nb_threads), - void *arg) -{ - pthread_mutex_lock(&ctx->mutex); - - ctx->func = func; - ctx->func_arg = arg; - - ctx->nb_jobs = nb_jobs; - ctx->nb_jobs_finished = 0; - ctx->next_job = 0; - - pthread_cond_broadcast(&ctx->cond); - while (ctx->nb_jobs_finished < ctx->nb_jobs) - pthread_cond_wait(&ctx->cond, &ctx->mutex); - - ctx->func = NULL; - ctx->func_arg = NULL; - - pthread_mutex_unlock(&ctx->mutex); -} diff --git a/threadpool.h b/threadpool.h deleted file mode 100644 index b22caab..0000000 --- a/threadpool.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 Anton Khirnov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef TEUKOLSKY_DATA_THREADPOOL_H -#define TEUKOLSKY_DATA_THREADPOOL_H - -typedef struct ThreadPoolContext ThreadPoolContext; - -int tdi_threadpool_init(ThreadPoolContext **ctx, unsigned int nb_threads); -void tdi_threadpool_free(ThreadPoolContext **ctx); - -void tdi_threadpool_execute(ThreadPoolContext *ctx, unsigned int nb_jobs, - void (*func)(void *arg, - unsigned int job_idx, unsigned int nb_jobs, - unsigned int thread_idx, unsigned int nb_threads), - void *arg); - -#endif /* TEUKOLSKY_DATA_THREADPOOL_H */ -- cgit v1.2.3