Previous: Implementation of pthread_barrier, Up: Multithreaded programming [Contents][Index]
The POSIX Threads functions offered in the C library are very low-level and offer a great range of control over the properties of the threads. So if you are interested in customizing your tools for complicated thread applications, it is strongly encouraged to get a nice familiarity with them. Some resources were introduced in Multithreaded programming (threads.h).
However, in many cases used in astronomical data analysis, you don’t need
communication between threads and each target operation can be done
independently. Since such operations are very common, Gnuastro provides the
tools below to facilitate the creation and management of jobs without any
particular knowledge of POSIX Threads for such operations. The most
interesting high-level functions of this section are the
gal_threads_number
and gal_threads_spin_off
that identify the
number of threads on the system and spin-off threads. You can see a
demonstration of using these functions in Library demo - multi-threaded operation.
struct
: gal_threads_paramsStructure keeping the parameters of each thread. When each thread is
created, a pointer to this structure is passed to it. The params
element can be the pointer to a structure defined by the user which
contains all the necessary parameters to pass onto the worker function. The
rest of the elements within this structure are set internally by
gal_threads_spin_off
and are relevant to the worker function.
struct gal_threads_params { size_t id; /* Id of this thread. */ void *params; /* User-identified pointer. */ size_t *indexs; /* Target indexs given to this thread. */ pthread_barrier_t *b; /* Barrier for all threads. */ };
Return the number of threads that the operating system has available for your program. This number is usually fixed for a single machine and doesn’t change. So this function is useful when you want to run your program on different machines (with different CPUs).
*(*worker)(void *)
, void *caller_params
, size_t numactions
, size_t numthreads
)Distribute numactions
jobs between numthreads
threads and
spin-off each thread by calling the worker
function. The
caller_params
pointer will also be passed to worker
as part
of the gal_threads_params
structure. For a fully working example of
this function, please see Library demo - multi-threaded operation.
*attr
, pthread_barrier_t *b
, size_t limit
)This is a low-level function in case you don’t want to use
gal_threads_spin_off
. It will initialize the general thread
attribute attr
and the barrier b
with limit
threads to
wait behind the barrier. For maximum efficiency, the threads initialized
with this function will be detached. Therefore no communication is
possible between these threads and in particular pthread_join
won’t
work on these threads. You have to use the barrier constructs to wait for
all threads to finish.
numactions
, size_t numthreads
, size_t **outthrds
, size_t *outthrdcols
)This is a low-level function in case you don’t want to use
gal_threads_spin_off
. Identify the “index”es (starting from 0) of
the actions to be done on each thread in the outthrds
array. outthrds
is treated as a 2D array with numthreads
rows
and outthrdcols
columns. The indexs in each row, identify the
actions that should be done by one thread. Please see the explanation below
to understand the purpose of this operation.
Let’s assume you have \(A\) actions (where there is only one function and the input values differ for each action) and \(T\) threads available to the system with \(A>T\) (common values for these two would be \(A>1000\) and \(T<10\)). Spinning off a thread is not a cheap job and requires a significant number of CPU cycles. Therefore, creating \(A\) threads is not the best way to address such a problem. The most efficient way to manage the actions is such that only \(T\) threads are created, and each thread works on a list of actions identified for it in series (one after the other). This way your CPU will get all the actions done with minimal overhead.
The purpose of this function is to do what we explained above: each row in
the outthrds
array contains the indexs of actions which must be done
by one thread. outthrds
contains outthrdcols
columns. In
using outthrds
, you don’t have to know the number of columns. The
GAL_BLANK_SIZE_T
macro has a role very similar to a
string’s \0
: every row finishes with this macro, so can easily stop
parsing the indexes in the row when you confront it. Please see the example
program in tests/lib/multithread.c for a demonstration.
Previous: Implementation of pthread_barrier, Up: Multithreaded programming [Contents][Index]
JavaScript license information
GNU Astronomy Utilities 0.13 manual, September 2020.