diff options
author | Pasha <pasha@member.fsf.org> | 2023-01-27 00:54:07 +0000 |
---|---|---|
committer | Pasha <pasha@member.fsf.org> | 2023-01-27 00:54:07 +0000 |
commit | ef800d4ffafdbde7d7a172ad73bd984b1695c138 (patch) | |
tree | 920cc189130f1e98f252283fce94851443641a6d /glpk-5.0/examples/threads/multiseed.c | |
parent | ec4ae3c2b5cb0e83fb667f14f832ea94f68ef075 (diff) | |
download | oneapi-ef800d4ffafdbde7d7a172ad73bd984b1695c138.tar.gz oneapi-ef800d4ffafdbde7d7a172ad73bd984b1695c138.tar.bz2 |
Diffstat (limited to 'glpk-5.0/examples/threads/multiseed.c')
-rw-r--r-- | glpk-5.0/examples/threads/multiseed.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/glpk-5.0/examples/threads/multiseed.c b/glpk-5.0/examples/threads/multiseed.c new file mode 100644 index 0000000..eb5d215 --- /dev/null +++ b/glpk-5.0/examples/threads/multiseed.c @@ -0,0 +1,255 @@ +/* multiseed.c (multithreading demo) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* Copyright (C) 2017 Free Software Foundation, Inc. +* Written by Heinrich Schuchardt <xypron.glpk@gmx.de>. +* +* GLPK 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. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +/* + * This program demonstrates running the GLPK library with multiple threads. + * + * When called the program requires two arguments: + * + * filename - the name of the MathProg model to be solved + * threads - the count of parallel threads to be run. + * + * Each thread is run with a different seed for the random number generator + * provided by the GLPK library. + */ + +#include <glpk.h> +#include <malloc.h> +#include <setjmp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "thread.h" + +#define BUFLEN 256 + +/* Task descriptor */ +struct task { + pthread_t tid; + char *filename; + int seed; + size_t pos; + char buf[BUFLEN + 1]; + int line; + jmp_buf jmp; +}; + +/* Mutex for console output */ +pthread_mutex_t mutex; + +/* Console output handler */ +int term_hook(void *info, const char *text) +{ + struct task *task = (struct task *) info; + size_t len = strlen(text); + + /* Lock mutex so this is the only task creating console output. */ + pthread_mutex_lock(&mutex); + + /* Append the new text to the buffer. */ + if (task->pos + len > BUFLEN) { + printf("%02d-%05d %s%s", task->seed, ++task->line, task->buf, text); + task->pos = 0; + task->buf[0] = 0; + } else { + strcpy(task->buf + task->pos, text); + task->pos += len; + } + + /* If a complete line is available, send it to the console. */ + if (strchr(task->buf, '\n')) { + printf("%02d-%05d %s", task->seed, ++task->line, task->buf); + task->pos = 0; + task->buf[0] = 0; + } + + /* Unlock the mutex. */ + pthread_mutex_unlock(&mutex); + + /* Disable default output. */ + return -1; +} + +/* Error handler */ +void error_hook(void *info) +{ + struct task *task = (struct task *) info; + + term_hook(task, "Error caught\n"); + glp_free_env(); + longjmp(task->jmp, 1); +} + +void worker(void *arg) +{ + struct task *task = (struct task *) arg; + int ret; + glp_prob *lp; + glp_tran *tran; + glp_iocp iocp; + + if (setjmp(task->jmp)) { + /* If an error is caught leave the function. */ + return; + } + + /* Set the error handler. */ + glp_error_hook(error_hook, task); + + /* Set the console output handler. */ + glp_term_hook(term_hook, arg); + + glp_printf("Seed %02d\n", task->seed); + + /* Create the problem object. */ + lp = glp_create_prob(); + if (!lp) { + glp_error("Out of memory\n"); + } + + /* Create the MathProg translator workspace. */ + tran = glp_mpl_alloc_wksp(); + if (!lp) { + glp_error("Out of memory\n"); + } + + /* Set the pseudo random number generator seed. */ + glp_mpl_init_rand(tran, task->seed); + + /* Read the model file. */ + ret = glp_mpl_read_model (tran, task->filename, GLP_OFF); + if (ret != 0) { + glp_error("Model %s is not valid\n", task->filename); + } + + /* Generate the model. */ + ret = glp_mpl_generate(tran, NULL); + if (ret != 0) { + glp_error("Cannot generate model %s\n", task->filename); + } + + /* Build the problem. */ + glp_mpl_build_prob(tran, lp); + + /* Solve the problem. */ + glp_init_iocp(&iocp); + iocp.presolve = GLP_ON; + ret = glp_intopt(lp, &iocp); + if (ret == 0) { + /* Execute the post solve part of the model. */ + glp_mpl_postsolve(tran, lp, GLP_MIP); + } + + /* Release the memory. */ + glp_mpl_free_wksp (tran); + glp_delete_prob(lp); + + if (0 == task->seed % 3) { + glp_error("Voluntarily throwing an error in %s at line %d\n", + __FILE__, __LINE__); + } + + glp_term_hook(NULL, NULL); + + glp_error_hook(NULL, NULL); + + glp_free_env(); +} + +#ifdef __WOE__ +DWORD run(void *arg) +{ +#else +void *run(void *arg) +{ +#endif + worker(arg); + pthread_exit(NULL); +} + +int main(int argc, char *argv[]) +{ + int i, n, rc; + struct task *tasks; + + /* Make sure thread local memory is used by the GLPK library. */ + if (!glp_config("TLS")) { + printf("The loaded GLPK library does not support thread local memory.\n" + "You need a version of the library configured with " + "--enable-reentrant=yes to run this program.\n"); + exit(EXIT_FAILURE); + } + + /* Check program arguments. */ + if (argc != 3) { + printf("Usage %s filename threads\n" + " filename - MathProg model file\n" + " threads - number of threads\n", + argv[0]); + exit(EXIT_FAILURE); + } + + /* Parse the arguments. */ + n = atoi(argv[2]); + if (n > 50) { + printf("Number of threads is to high (> 50).\n"); + exit(EXIT_FAILURE); + } + if (n <= 1) { + printf("Need positive number of threads\n"); + exit(EXIT_FAILURE); + } + + /* Allocate memory for the task descriptors. */ + tasks = calloc(n, sizeof(struct task)); + if (!tasks) { + printf("Out of memory"); + exit(EXIT_FAILURE); + } + + /* Create a mutex for console output. */ + pthread_mutex_init(&mutex, NULL); + + /* Create the threads. */ + for (i = 0; i < n; ++i) { + tasks[i].filename = argv[1]; + tasks[i].seed = i + 1; + tasks[i].pos = 0; + tasks[i].buf[0] = 0; + tasks[i].line = 0; + rc = pthread_create(&tasks[i].tid, NULL, run, &tasks[i]); + if (rc) { + printf("ERROR; return code from pthread_create() is %d\n", rc); + exit(EXIT_FAILURE); + } + } + + /* Wait for all threads to complete. */ + for (i = 0; i < n; ++i) { + pthread_join(tasks[i].tid, NULL); + } + + /* Destroy the mutex. */ + pthread_mutex_destroy(&mutex); + + return EXIT_SUCCESS; +} |