1 /*********************************************************************
2 A test program to multithreaded building using Gnuastro's helpers.
3 
4 Original author:
5      Mohammad Akhlaghi <mohammad@akhlaghi.org>
6 Contributing author(s):
7 Copyright (C) 2017-2021, Free Software Foundation, Inc.
8 
9 Gnuastro is free software: you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation, either version 3 of the License, or (at your
12 option) any later version.
13 
14 Gnuastro is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
21 **********************************************************************/
22 #include <stdio.h>
23 #include <stdlib.h>
24 
25 #include "gnuastro/fits.h"
26 #include "gnuastro/threads.h"
27 
28 
29 /* This structure can keep all information you want to pass onto the worker
30    function on each thread. */
31 struct params
32 {
33   gal_data_t *image;            /* Dataset to print values of. */
34 };
35 
36 
37 
38 
39 /* This is the main worker function which will be called by the different
40    threads. 'gal_threads_params' is defined in 'gnuastro/threads.h' and
41    contains the pointer to the paramter we want. Note that its input and
42    output must have 'void *' types. */
43 void *
worker_on_thread(void * in_prm)44 worker_on_thread(void *in_prm)
45 {
46   /* Low-level definitions to be done first. */
47   struct gal_threads_params *tprm=(struct gal_threads_params *)in_prm;
48   struct params *p=(struct params *)tprm->params;
49 
50 
51   /* Subsequent definitions. */
52   float *array=p->image->array;
53   size_t i, index, *dsize=p->image->dsize;
54 
55 
56   /* Go over all the pixels that were assigned to this thread. */
57   for(i=0; tprm->indexs[i] != GAL_BLANK_SIZE_T; ++i)
58     {
59       /* For easy reading. */
60       index = tprm->indexs[i];
61 
62 
63       /* Print the information. */
64       printf("(%zu, %zu) on thread %zu: %g\n", index%dsize[1]+1,
65              index/dsize[1]+1, tprm->id, array[index]);
66     }
67 
68 
69   /* Wait for all the other threads to finish, then return. */
70   if(tprm->b) pthread_barrier_wait(tprm->b);
71   return NULL;
72 }
73 
74 
75 
76 
77 /* A simple program to open a FITS image, distributes its pixels between
78    different threads and print the value of each pixel and the thread it
79    was assigned to, this will test both the opening of a FITS file and also
80    the multi-threaded functions. After running 'make check' you can see the
81    outputs in 'tests/multithread.log'.
82 
83    Please run the following command for an explanation on easily linking
84    and compiling C programs that use Gnuastro's libraries (without having
85    to worry about the libraries to link to) anywhere on your system:
86 
87       $ info gnuastro "Automatic linking script"
88 */
89 int
main(void)90 main(void)
91 {
92   struct params p;
93   int quietmmap=1;
94   size_t minmapsize=-1;
95   char *filename="psf.fits", *hdu="1";
96   size_t numthreads=gal_threads_number();
97 
98 
99   /* Read the image into memory as a float32 data type. */
100   p.image=gal_fits_img_read_to_type(filename, hdu, GAL_TYPE_FLOAT32,
101                                     minmapsize, quietmmap);
102 
103 
104   /* Print some basic information before the actual contents: */
105   printf("Pixel values of %s (HDU: %s) on %zu threads.\n", filename, hdu,
106          numthreads);
107   printf("Used to check the compiled library's capability in opening a "
108          "FITS file, and also spinning-off threads.\n");
109 
110 
111   /* A small sanity check: this is only intended for 2D arrays. */
112   if(p.image->ndim!=2)
113     {
114       fprintf(stderr, "only 2D images are supported.");
115       exit(EXIT_FAILURE);
116     }
117 
118 
119   /* Spin-off the threads and do the processing on each thread. */
120   gal_threads_spin_off(worker_on_thread, &p, p.image->size, numthreads,
121                        minmapsize, quietmmap);
122 
123 
124   /* Clean up and return. */
125   gal_data_free(p.image);
126   return EXIT_SUCCESS;
127 }
128