1 /* mplrs.h: header for mplrs.c
2 This program is free software; you can redistribute it and/or
3 modify it under the terms of the GNU General Public License
4 as published by the Free Software Foundation; either version 2
5 of the License, or (at your option) any later version.
6 
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 GNU General Public License for more details.
11 
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
15 
16 Author: Charles Jordan skip@ist.hokudai.ac.jp
17 Based on plrs by Gary Roumanis
18 Initial lrs Author: David Avis avis@cs.mcgill.ca
19 */
20 
21 #ifndef MPLRSH
22 #define MPLRSH 1
23 
24 #ifdef MA
25 #define GMP
26 #endif
27 
28 #include "lrsdriver.h"
29 #include "lrslib.h"
30 
31 #include <mpi.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <signal.h>
35 #include <sys/time.h>
36 #include <stdio.h>
37 
38 extern FILE *lrs_ofp; /* hack to get redund final print in output file */
39 
40 #define USAGE "Usage is: \n mpirun -np <number of processes> mplrs <infile> <outfile> \n or \n mpirun -np <number of processes> mplrs <infile> <outfile> -id <initial depth> -maxc <maxcobases> -maxd <depth> -lmin <int> -lmax <int> -scale <int> -maxbuf <int> -countonly -hist <file> -temp <prefix> -freq <file> -stop <stopfile> -checkp <checkpoint file> -restart <checkpoint file> -time <seconds> -stopafter <int> -redund"
41 
42 /* Default values for options. */
43 #define DEF_LMIN 3	/* default -lmin  */
44 #define DEF_LMAX 0	/* default -lmax. but note orig_lmax behavior!  */
45 #define DEF_ID   2	/* default -id    */
46 #define DEF_MAXD 0	/* default -maxd  */
47 #define DEF_MAXC 50	/* default -maxc  */
48 #define DEF_MAXNCOB 0   /* default -stopafter (disabled) */
49 #define DEF_MAXBUF  500 /* default -maxbuf */
50 
51 #define DEF_TEMP   "/tmp/" /* default prefix for temporary files
52 			 * use /a/b to get files /a/bfilename,
53 			 * use /a/b/ to get files /a/b/filename
54 			 */
55 #define DEF_INPUT  NULL	/* default input filename (or NULL)       */
56 #define DEF_OUTPUT NULL	/* default output filename (or NULL)	  */
57 #define DEF_HIST   NULL	/* default histogram filename (or NULL)   */
58 #define DEF_RESTART NULL/* default restart filename (or NULL)	  */
59 #define DEF_FREQ   NULL /* default sub-problem size filename (NULL) */
60 #define DEF_CHECKP NULL	/* default checkpoint filename (or NULL)  */
61 #define DEF_STOP   NULL	/* default stop-signal filename (or NULL) */
62 
63 #define DEF_SCALEC 100	/* default multiplicative scaling factor for maxc,
64 			 * used when L is too large (controlled by lmax) */
65 
66 #if defined(MA) || (defined(LRSLONG) && !defined(B128))
67 #define mplrs_init_lrs_main lrs1_main
68 #elif defined(LRSLONG) /* B128 */
69 #define mplrs_init_lrs_main lrs2_main
70 #elif defined(GMP)
71 #define mplrs_init_lrs_main lrsgmp_main
72 #elif defined(FLINT)
73 #define mplrs_init_lrs_main lrsv2_main
74 #elif defined(MP)
75 #define mplrs_init_lrs_main lrsv2_main
76 #endif
77 
78 /* singly linked list */
79 typedef struct slist {
80         void *data;
81         struct slist *next;
82 } slist;
83 
84 typedef struct outlist {
85 	char *type;
86 	char *data;
87 	struct outlist *next;
88 } outlist;
89 
90 /* A linked-list of buffers for MPI communications.
91  * req[0...count-1] correspond to buf[0...count-1]
92  *
93  * When req[i] completes, should free buf[i].
94  * When all reqs complete, should free buf, req, tags,sizes,types.
95  */
96 typedef struct msgbuf {
97 	MPI_Request *req;
98 	void **buf;
99 	int count;
100 	int target;
101 	int data;  /* optional, use yourself if needed for something */
102 	int queue;  /* if 1, send items 1...count after 0 has completed */
103 	/* queue pointers must be NULL or something free()able */
104 	int *tags;  /* tags to use on items 1...count if queued */
105 	int *sizes; /* sizes of sends if queued */
106 	MPI_Datatype *types; /* types of sends if queued */
107 
108 	struct msgbuf *next;
109 } msgbuf;
110 
111 /* A structure containing the state of this process.
112  * Each process has one.
113  */
114 typedef struct mplrsv {
115 	/* MPI communication buffers */
116 	msgbuf *outgoing;
117 	slist *cobasis_list;
118 	long (*lrs_main)(int, char **, lrs_dic **, lrs_dat **, long, long, char *, lrs_restart_dat *);
119 	lrs_dic *P;
120 	lrs_dat *Q;
121 	lrs_restart_dat *R;
122 
123 	int caughtsig; /* flag for catching a signal */
124 	unsigned int abortinit; /* lrs_main stage 0 (setup) failed? */
125 	unsigned int overflow; /* 0: lrslong 1:lrslong2 2:lrsgmp */
126 	/* counts */
127 	unsigned long long rays;
128 	unsigned long long vertices;
129 	unsigned long long bases;
130 	unsigned long long facets;
131 	unsigned long long linearities;
132 	unsigned long long intvertices;
133 	unsigned long long deepest;
134         unsigned long long nredundcol;
135 	lrs_mp Tnum, Tden, tN, tD, Vnum, Vden;
136 
137 	struct timeval start, end;
138 
139 	/* MPI info */
140 	int rank; 			/* my rank */
141 	int size;			/* number of MPI processes */
142 	int my_tag;			/* to distinguish MPI sends */
143 	char host[MPI_MAX_PROCESSOR_NAME]; /* name of this host */
144 
145 	/* output_list */
146 	outlist *output_list;
147 	outlist *ol_tail;
148 
149 	char *finalwarn;	/* for process_output "finalwarn" */
150 	int finalwarn_len;	/* length allocated for finalwarn */
151 	char *curwarn;		/* to discard "finalwarn" messages on */
152 	int curwarn_len;	/* overflow, preventing duplicates    */
153 	/* for convenience */
154 	const char *tfn_prefix;
155 	char *tfn;
156 	FILE *tfile;
157 	int initializing;		/* in phase 1? */
158 	int countonly; /* countonly */
159 	int outnum; /* number of output lines buffered */
160 	int maxbuf; /* maximum number of output lines to buffer before flush */
161 	int outputblock; /* temporarily prevent a maxbuf-based output flush */
162 	int redund; /* bool: is this a redund run? */
163 
164 	char *input_filename;		/* input filename */
165 	char *input;			/* buffer for contents of input file */
166 } mplrsv;
167 
168 /* A structure for variables only the master needs */
169 typedef struct masterv {
170 	slist *cobasis_list;		/* list of work to do (L) */
171 	unsigned long tot_L;		/* total size of L (total # jobs) */
172 	unsigned long size_L;		/* current size of L (for histograms
173 					 * and scaling)
174 					 */
175 	unsigned long num_empty;	/* number of times L became empty */
176 	unsigned int num_producers; 	/* number of producers running */
177 	unsigned int *act_producers;    /* whether each producer owes us
178 					 * remaining bases message.
179 					 * Needed only for histograms.
180 					 */
181 	unsigned int live_workers;      /* number that haven't exited */
182 	/* MPI communication buffers */
183 	int *workin; 			/* incoming messages from producers
184 					   desiring work */
185 	MPI_Request *mworkers;		/* MPI_Requests for these messages */
186 	msgbuf *incoming;		/* incoming cobases from producers */
187 	float *sigbuf; 			/*incoming signal/termination requests*/
188 	MPI_Request *sigcheck;		/* MPI_Requests for reporting these*/
189 
190 	int checkpointing;		/* are we checkpointing now? */
191 	int cleanstop;			/* was a cleanstop requested? */
192 	int messages;			/* do we want to set R->messages? */
193 
194 	/* user options */
195 	unsigned int lmin;		/* option -lmin */
196 	unsigned int lmax;		/* option -lmax */
197 	int orig_lmax;			/*user changed lmax? if not,lmax=lmin*/
198 	unsigned int scalec;		/* option -scale*/
199 	unsigned int initdepth;		/* option -id   */
200 	unsigned int maxdepth;		/* option -maxd */
201 	unsigned int maxcobases;	/* option -maxc */
202 	unsigned int time_limit;	/* option -time */
203 	unsigned long maxncob;		/* option -stopafter */
204 	int lponly;			/* bool for -lponly option */
205 	int redund;			/* bool for -redund option */
206 	int max_redundworker;		/* max id for a worker
207 					 * used if m>np-2
208 					 */
209 	/* files */
210 	char *hist_filename;		/*histogram filename (or NULL)*/
211 	FILE *hist;
212 	int doing_histogram;		/* are we doing a histogram? */
213 	char *freq_filename;		/*are we outputting sub-problem sizes?*/
214 	FILE *freq;
215 	char *restart_filename;		/* restart from a checkpoint */
216 	FILE *restart;
217 	char *checkp_filename;		/* filename to save checkpoint*/
218 	FILE *checkp;
219 	char *stop_filename;		/* option -stop */
220 	FILE *stop;
221 	FILE *input;
222 } masterv;
223 
224 /* A structure for variables only the consumer needs */
225 typedef struct consumerv {
226 	/* MPI communication buffers */
227 	  /* for headers */
228 	MPI_Request *prodreq;    	/* consumer keeps an open request
229 					 * for each producer and master
230 					 */
231 	int *prodibf;			/* and two ints as a receive buffer */
232 	  /* for content */
233 	msgbuf *incoming; 		/* incoming MPI communication buffers */
234 
235 	/* output */
236 	char *output_filename;		/* output filename (or NULL) */
237 	FILE *output;			/* output file (NULL for stdout) */
238 
239 	/* status */
240 	unsigned int num_producers;	/* number of producers still going */
241 
242 	/* other */
243 	unsigned int oflow_flag;	/* 0: no overflow message yet */
244 	int *overflow;			/* number of overflowed workers*/
245 	int waiting_initial;		/* waiting for initial producer,
246 					 * hold output until after 'begin'
247 					 */
248 	int final_print;		/* do the final print? (bool) */
249 	long *redineq;     /* bool vector for redund, which rows redundant */
250 	int final_redundcheck;		/* are we in the final redund check? */
251 } consumerv;
252 
253 /* MASTER and CONSUMER and INITIAL must be different */
254 #define MASTER 0   /* the MPI process that becomes master */
255 #define CONSUMER 1 /* the MPI process that becomes consumer */
256 #define INITIAL 2
257 
258 #define CHECKFLAG -3	/* must be distinct negative values */
259 #define RESTARTFLAG -4
260 #define STOPFLAG -5
261 
262 /* define MDEBUG to get many mplrs debug messages */
263 #ifdef MDEBUG
264 #define mprintf(a) printf a
265 #else
266 #define mprintf(a)
267 #endif
268 /* define MDEBUG2 to get even more */
269 #ifdef MDEBUG2
270 #define mprintf2(a) printf a
271 #else
272 #define mprintf2(a)
273 #endif
274 /* define MDEBUG3 to get lots */
275 #ifdef MDEBUG3
276 #define mprintf3(a) printf a
277 #else
278 #define mprintf3(a)
279 #endif
280 
281 /* function prototypes */
282 void mplrs_init(int, char **);
283 void mplrs_caughtsig(int);
284 void master_sendfile(void);
285 void mplrs_initstrucs();
286 void mplrs_commandline(int, char **);
287 void mplrs_initfiles(void);
288 void bad_args(void);
289 int mplrs_fallback(void);
290 
291 int mplrs_master(void);
292 void send_work(int, int);
293 void recv_producer_lists(void);
294 void process_returned_cobases(msgbuf *);
295 void setparams(int *);
296 void check_stop(void);
297 void master_stop_consumer(int);
298 void master_checksigs(void);
299 void master_restart(void);
300 void master_checkpoint(void);
301 void master_checkpointfile(void);
302 void master_checkpointconsumer(void);
303 void print_histogram(struct timeval *, struct timeval *);
304 
305 int mplrs_worker(void);
306 void mplrs_worker_init(void);
307 void clean_outgoing_buffers(void); /* shared with master */
308 void do_work(const int *, char *);
309 void worker_report_overflow(void);
310 void process_output(void);
311 void process_curwarn(void);
312 void send_output(int, char *);
313 void process_cobasis(const char *);
314 slist *addlist(slist *, void *);
315 void return_unfinished_cobases(void);
316 char *append_out(char *, int *, const char *);
317 int mplrs_worker_finished(void);
318 
319 int mplrs_consumer(void);
320 void consumer_start_incoming(void);
321 msgbuf *consumer_queue_incoming(int *, int);
322 void consumer_proc_messages(void);
323 int consumer_checkpoint(void);
324 int outgoing_msgbuf_completed(msgbuf *);
325 void free_msgbuf(msgbuf *);
326 outlist *reverse_list(outlist*);
327 void send_master_stats(void);
328 void recv_master_stats(void);
329 void send_counting_stats(int);
330 void recv_counting_stats(int);
331 void initial_print(void);
332 void phase1_print(void);
333 void consumer_setredineq(void);
334 void final_print(void);
335 char *dupstr(const char *str);
336 
337 int okay_to_flush(void);
338 void post_output(const char *, const char *);
339 void open_outputblock(void);
340 void close_outputblock(void);
341 void mplrs_cleanstop(int);
342 void mplrs_emergencystop(const char *);
343 void overflow_cleanup(void);
344 void set_restart(const int *, char *);
345 #endif /* MPLRSH */
346