View Javadoc
1   //******************************************************************************
2   //
3   // File:    PJProperties.java
4   // Package: edu.rit.pj
5   // Unit:    Class edu.rit.pj.PJProperties
6   //
7   // This Java source file is copyright (C) 2008 by Alan Kaminsky. All rights
8   // reserved. For further information, contact the author, Alan Kaminsky, at
9   // ark@cs.rit.edu.
10  //
11  // This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
12  // software; you can redistribute it and/or modify it under the terms of the GNU
13  // General Public License as published by the Free Software Foundation; either
14  // version 3 of the License, or (at your option) any later version.
15  //
16  // PJ is distributed in the hope that it will be useful, but WITHOUT ANY
17  // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18  // A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19  //
20  // Linking this library statically or dynamically with other modules is making a
21  // combined work based on this library. Thus, the terms and conditions of the GNU
22  // General Public License cover the whole combination.
23  //
24  // As a special exception, the copyright holders of this library give you
25  // permission to link this library with independent modules to produce an
26  // executable, regardless of the license terms of these independent modules, and
27  // to copy and distribute the resulting executable under terms of your choice,
28  // provided that you also meet, for each linked independent module, the terms
29  // and conditions of the license of that module. An independent module is a module
30  // which is not derived from or based on this library. If you modify this library,
31  // you may extend this exception to your version of the library, but you are not
32  // obligated to do so. If you do not wish to do so, delete this exception
33  // statement from your version.
34  //
35  // A copy of the GNU General Public License is provided in the file gpl.txt. You
36  // may also obtain a copy of the GNU General Public License on the World Wide
37  // Web at http://www.gnu.org/licenses/gpl.html.
38  //
39  //******************************************************************************
40  package edu.rit.pj;
41  
42  /**
43   * Class PJProperties provides static methods for reading Java system properties
44   * that control the behavior of Parallel Java. The PJ properties are:
45   * <UL>
46   * <LI>
47   * <B>pj.nn</B> -- The number of backend nodes in a parallel program.
48   * ({@link #getPjNn()})
49   * <LI>
50   * <B>pj.np</B> -- The number of processes in a parallel program; also the size
51   * of the world communicator. ({@link #getPjNp()})
52   * <LI>
53   * <B>pj.nt</B> -- The number of CPUs per process in a parallel program; also
54   * the default number of threads in a parallel team. ({@link #getPjNt()})
55   * <p>
56   * When running a Parallel Java program via the job queue on a cluster parallel
57   * computer (see package {@linkplain edu.rit.pj.cluster edu.rit.pj.cluster} for
58   * further information), the Job Scheduler Daemon uses the <I>nn,</I>
59   * <I>np,</I> and <I>nt</I> settings to assign resources to the job.
60   * <p>
61   * If neither <I>nn</I> nor <I>np</I> is specified, the Job Scheduler will run
62   * the job with one process on one node.
63   * <p>
64   * If <I>nn</I> or <I>np</I> is specified but not both, the Job Scheduler will
65   * run the job on <I>nn</I> (or <I>np</I>) nodes with one process on each node.
66   * <p>
67   * If <I>nn</I> and <I>np</I> are both specified and <I>nn</I> &gt;= <I>np</I>,
68   * the Job Scheduler will run the job on <I>np</I> nodes with one process on
69   * each node.
70   * <p>
71   * If <I>nn</I> and <I>np</I> are both specified and <I>nn</I> &lt; <I>np</I>,
72   * the Job Scheduler will run the job on <I>nn</I> nodes with with more than one
73   * process on some or all of the nodes, apportioning the <I>np</I> processes as
74   * equally as possible among the <I>nn</I> nodes. Note that in this case,
75   * different nodes may be assigned different numbers of processes.
76   * <p>
77   * On each node, the Job Scheduler will assign <I>nt</I> CPUs to each process.
78   * If <I>nt</I> is not specified, the default is to use all the CPUs in the
79   * node, apportioning the CPUs as equally as possible among the processes on the
80   * node. Note that in this case, different processes may be assigned different
81   * numbers of CPUs.
82   * <LI>
83   * <B>pj.schedule</B> -- The schedule for a parallel loop in a parallel program.
84   * ({@link #getPjSchedule()})
85   * <LI>
86   * <B>pj.host</B> -- The host name of the Job Scheduler Daemon to use when
87   * running a cluster parallel program. ({@link #getPjHost()})
88   * <LI>
89   * <B>pj.port</B> -- The port number of the Job Scheduler Daemon to use when
90   * running a cluster parallel program. ({@link #getPjPort()})
91   * <LI>
92   * <B>pj.jobtime</B> -- The maximum amount of time (seconds) the job is allowed
93   * to run when running a cluster parallel program. ({@link #getPjJobTime()})
94   * <LI>
95   * <B>pj.jvmflags</B> -- JVM flags to include on the Java command line when
96   * running a backend process in a cluster parallel program. ({@link
97   *#getPjJvmFlags()})
98   * <LI>
99   * <B>pj.prng</B> -- The fully-qualified class name of the default pseudorandom
100  * number generator (PRNG) class. ({@link #getPjPrng()})
101  * </UL>
102  * <p>
103  * You can specify a PJ property on the Java command line like this:
104  * <p>
105  * <code>&nbsp;&nbsp;&nbsp;&nbsp;java -Dpj.nt=4 . . .</code>
106  *
107  * @author Alan Kaminsky
108  * @version 21-May-2008
109  */
110 public class PJProperties {
111 
112     // Prevent construction.
113     private PJProperties() {
114     }
115 
116 // Exported operations.
117 
118     /**
119      * Determine the number of backend nodes in a parallel program.
120      * <p>
121      * If the <code>"pj.nn"</code> Java system property is specified, it must be an
122      * integer greater than or equal to 1.
123      *
124      * @return Number of backend nodes for a parallel program.
125      * @throws java.lang.IllegalArgumentException (unchecked exception) Thrown if the
126      *                                  <code>"pj.nn"</code> property value is not an integer greater than or equal
127      *                                  to 1.
128      */
129     public static int getPjNn() {
130         int k = 1;
131         String pj_nn = System.getProperty("pj.nn");
132         if (pj_nn != null) {
133             try {
134                 k = Integer.parseInt(pj_nn);
135             } catch (NumberFormatException exc) {
136                 throw new IllegalArgumentException("pj.nn system property is not an integer >= 1");
137             }
138             if (k < 1) {
139                 throw new IllegalArgumentException("pj.nn system property is not an integer >= 1");
140             }
141         } else // (pj_nn == null)
142         {
143             String pj_np = System.getProperty("pj.np");
144             if (pj_np != null) {
145                 try {
146                     k = Integer.parseInt(pj_np);
147                 } catch (NumberFormatException exc) {
148                     throw new IllegalArgumentException("pj.np system property is not an integer >= 1");
149                 }
150                 if (k < 1) {
151                     throw new IllegalArgumentException("pj.np system property is not an integer >= 1");
152                 }
153             }
154         }
155         return k;
156     }
157 
158     /**
159      * Determine the number of processes in a parallel program. This is the
160      * number of backend processes set up when the <code>Comm.init()</code> method
161      * is executed (see class {@linkplain Comm}). This is also the size of the
162      * world communicator.
163      * <p>
164      * If the <code>"pj.np"</code> Java system property is specified, it must be an
165      * integer greater than or equal to 1.
166      *
167      * @return Number of processes for a parallel program.
168      * @throws java.lang.IllegalArgumentException (unchecked exception) Thrown if the
169      *                                  <code>"pj.np"</code> property value is not an integer greater than or equal
170      *                                  to 1.
171      */
172     public static int getPjNp() {
173         int k = 1;
174         String pj_np = System.getProperty("pj.np");
175         if (pj_np != null) {
176             try {
177                 k = Integer.parseInt(pj_np);
178             } catch (NumberFormatException exc) {
179                 throw new IllegalArgumentException("pj.np system property is not an integer >= 1");
180             }
181             if (k < 1) {
182                 throw new IllegalArgumentException("pj.np system property is not an integer >= 1");
183             }
184         } else // (pj_np == null)
185         {
186             String pj_nn = System.getProperty("pj.nn");
187             if (pj_nn != null) {
188                 try {
189                     k = Integer.parseInt(pj_nn);
190                 } catch (NumberFormatException exc) {
191                     throw new IllegalArgumentException("pj.nn system property is not an integer >= 1");
192                 }
193                 if (k < 1) {
194                     throw new IllegalArgumentException("pj.nn system property is not an integer >= 1");
195                 }
196             }
197         }
198         return k;
199     }
200 
201     /**
202      * Determine the number of CPUs per process in a parallel program. This is
203      * the number of threads a {@linkplain ParallelTeam} will have if the number
204      * of threads is not specified as a constructor argument.
205      * <p>
206      * If the <code>"pj.nt"</code> Java system property is specified, it must be an
207      * integer greater than or equal to 1.
208      * <p>
209      * If the <code>"pj.nt"</code> Java system property is not specified, this
210      * method returns 0 to signify that all available CPUs should be used.
211      *
212      * @return Number of CPUs per process for a parallel program, or 0 if not
213      * specified.
214      * @throws java.lang.IllegalArgumentException (unchecked exception) Thrown if the
215      *                                  <code>"pj.nt"</code> property value is not an integer greater than or equal
216      *                                  to 1.
217      */
218     public static int getPjNt() {
219         int k = 0;
220         String pj_nt = System.getProperty("pj.nt");
221         if (pj_nt != null) {
222             try {
223                 k = Integer.parseInt(pj_nt);
224             } catch (NumberFormatException exc) {
225                 throw new IllegalArgumentException("pj.nt system property is not an integer >= 1");
226             }
227             if (k < 1) {
228                 throw new IllegalArgumentException("pj.nt system property is not an integer >= 1");
229             } else {
230                 System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", pj_nt);
231             }
232         }
233         return k;
234     }
235 
236     /**
237      * Determine the schedule for a parallel loop in an SMP parallel program.
238      * This is the schedule that will be used if the parallel for loop has a
239      * runtime schedule. For further information, see class {@linkplain
240      * IntegerSchedule} and class {@linkplain LongSchedule}.
241      * <p>
242      * If the <code>"pj.schedule"</code> Java property is specified, that value
243      * gives the type of schedule, which must be one of the following:
244      * <UL>
245      * <LI><code>"fixed"</code> -- Fixed schedule.
246      * <LI><code>"dynamic"</code> -- Dynamic schedule with a chunk size of 1.
247      * <LI><code>"dynamic(&lt;n&gt;)"</code> -- Dynamic schedule with a chunk size
248      * of <code>&lt;n&gt;</code>, an integer &gt;= 1.
249      * <LI><code>"guided"</code> -- Self-guided schedule with a minimum chunk size
250      * of 1.
251      * <LI><code>"guided(&lt;n&gt;)"</code> -- Self-guided schedule with a minimum
252      * chunk size of <code>&lt;n&gt;</code>, an integer &gt;= 1.
253      * <LI><code>"<I>classname</I>"</code> -- Schedule that is an instance of the
254      * given class. <I>classname</I> is the fully-qualified class name of the
255      * schedule class. The instance is constructed using the subclass's
256      * no-argument constructor.
257      * <LI><code>"<I>classname</I>(<I>arg</I>,<I>arg</I>,...)"</code> -- Schedule
258      * that is an instance of the given class. <I>classname</I> is the
259      * fully-qualified class name of the schedule class. The arguments between
260      * the parentheses are split into separate strings separated by commas.
261      * There cannot be parentheses or commas within the arguments themselves.
262      * The instance is constructed using the subclass's constructor whose
263      * argument is an array of Strings, namely the individual arguments between
264      * the parentheses.
265      * </UL>
266      * <p>
267      * If the <code>"pj.schedule"</code> Java property is not specified, the default
268      * schedule for a runtime schedule is used. Normally this is a fixed
269      * schedule, but a program can specify a different default.
270      *
271      * @return Schedule for a parallel for loop (one of the above strings), or
272      * null if the <code>"pj.schedule"</code> Java property is not specified.
273      */
274     public static String getPjSchedule() {
275         return System.getProperty("pj.schedule");
276     }
277 
278     /**
279      * Determine the host name of the Job Scheduler Daemon to use when running a
280      * cluster parallel program. The program contacts the Job Scheduler Daemon
281      * when the <code>Comm.init()</code> method is executed (see class {@linkplain
282      * Comm}). For further information, see package {@linkplain
283      * edu.rit.pj.cluster edu.rit.pj.cluster} and class {@linkplain
284      * edu.rit.pj.cluster.JobScheduler}.
285      * <p>
286      * If the <code>"pj.host"</code> Java system property is specified, it gives the
287      * Job Scheduler Daemon's host name (or IP address).
288      * <p>
289      * If the <code>"pj.host"</code> Java system property is not specified, a host
290      * name of <code>"localhost"</code> is returned.
291      *
292      * @return Job Scheduler Daemon host name.
293      */
294     public static String getPjHost() {
295         return System.getProperty("pj.host", "localhost");
296     }
297 
298     /**
299      * Determine the port number of the Job Scheduler Daemon to use when running
300      * a cluster parallel program. The program contacts the Job Scheduler Daemon
301      * when the <code>Comm.init()</code> method is executed (see class {@linkplain
302      * Comm}). For further information, see package {@linkplain
303      * edu.rit.pj.cluster edu.rit.pj.cluster} and class {@linkplain
304      * edu.rit.pj.cluster.JobScheduler}.
305      * <p>
306      * If the <code>"pj.port"</code> Java system property is specified, it gives the
307      * Job Scheduler Daemon's port number.
308      * <p>
309      * If the <code>"pj.port"</code> Java system property is not specified, the
310      * well-known Parallel Java port number (20617) is returned.
311      *
312      * @return Job Scheduler Daemon port number.
313      * @throws java.lang.IllegalArgumentException (unchecked exception) Thrown if the
314      *                                  <code>"pj.port"</code> property value is not an integer.
315      */
316     public static int getPjPort() {
317         try {
318             String pj_port = System.getProperty("pj.port");
319             int port
320                     = pj_port == null
321                     ? // edu.rit.pj.cluster.Constants.PJ_PORT :
322                     20617
323                     : Integer.parseInt(pj_port);
324             return port;
325         } catch (NumberFormatException exc) {
326             throw new IllegalArgumentException("pj.port system property is not an integer");
327         }
328     }
329 
330     /**
331      * Determine the maximum amount of time (seconds) the job is allowed to run
332      * when running a cluster parallel program. If a program running in the
333      * Parallel Java job queue has not finished in the given amount of time, the
334      * job frontend process automatically termintes the job when the given
335      * number of seconds have elapsed since the job started executing. If a
336      * program is not running in the Parallel Java job queue (if there is no Job
337      * Scheduler Daemon present), then the job time setting is ignored and the
338      * program will not time out.
339      * <p>
340      * If the <code>"pj.jobtime"</code> Java system property is specified, it must
341      * be an integer greater than or equal to 1, and that gives the the maximum
342      * job timeout in seconds.
343      * <p>
344      * If the <code>"pj.jobtime"</code> Java system property is not specified, a
345      * value of 0 is returned to signify that there is no job timeout.
346      *
347      * @return Job timeout (seconds), or 0 if no job timeout.
348      * @throws java.lang.IllegalArgumentException (unchecked exception) Thrown if the
349      *                                  <code>"pj.jobtime"</code> property value is not an integer greater than or
350      *                                  equal to 1.
351      */
352     public static int getPjJobTime() {
353         try {
354             String pj_jobtime = System.getProperty("pj.jobtime");
355             if (pj_jobtime == null) {
356                 return 0;
357             } else {
358                 int jobtime = Integer.parseInt(pj_jobtime);
359                 if (jobtime < 1) {
360                     throw new IllegalArgumentException("pj.jobtime system property is not an integer >= 1");
361                 }
362                 return jobtime;
363             }
364         } catch (NumberFormatException exc) {
365             throw new IllegalArgumentException("pj.jobtime system property is not an integer >= 1");
366         }
367     }
368 
369     /**
370      * Determine the JVM flags to include on the Java command line when running
371      * a backend process in a cluster parallel program. When a job backend
372      * process is started, the JVM flags are included on the command line
373      * immediately after the <code>"java"</code> command. These flags then control
374      * the job backend process's JVM. For further information, see package
375      * {@linkplain edu.rit.pj.cluster edu.rit.pj.cluster}.
376      * <p>
377      * If the <code>"pj.jvmflags"</code> Java system property is specified, it gives
378      * the JVM flags exactly as they are to appear on the Java command line. If
379      * there are multiple flags separated by whitespace, the
380      * <code>"pj.jvmflags"</code> Java system property must be enclosed in quotation
381      * marks.
382      * <p>
383      * If the <code>"pj.jvmflags"</code> Java system property is not specified,
384      * there are no JVM flags, and an empty string is returned.
385      * <p>
386      * <B>Example.</B> To cause the job backend processes' JVMs to use an
387      * initial heap size of 4 MB and a maximum heap size of 128 MB, specify the
388      * <code>"pj.jvmflags"</code> property as follows when running the program:
389      *
390      * <code>&nbsp;&nbsp;&nbsp;&nbsp;java -Dpj.jvmflags="-Xms4m -Xmx128m" . .
391      * .</code>
392      * <p>
393      * Note that quotation marks are needed around the property value because of
394      * the embedded whitespace. This property value causes the Job Launcher
395      * Daemon to launch each job backend process's JVM with this command:
396      *
397      * <code>&nbsp;&nbsp;&nbsp;&nbsp;java -Xms4m -Xmx128m . . .</code>
398      * <p>
399      * which in turn tells each job backend process's JVM to use initial and
400      * maximum heap sizes of 4 MB and 128 MB.
401      *
402      * @return JVM flags.
403      */
404     public static String getPjJvmFlags() {
405         return System.getProperty("pj.jvmflags", "");
406     }
407 
408     /**
409      * Determine the fully-qualified class name of the default pseudorandom
410      * number generator (PRNG) class.
411      * <p>
412      * If the <code>"pj.prng"</code> Java system property is specified, it gives the
413      * fully-qualified class name of the PRNG class that the static
414      * <code>getInstance(long)</code> method in class {@linkplain
415      * edu.rit.util.Random} will construct. Specifying the <code>"pj.prng"</code>
416      * property will substitute a different PRNG algorithm into a program
417      * without needing to recompile. See class {@linkplain edu.rit.util.Random}
418      * for further information.
419      * <p>
420      * If the <code>"pj.prng"</code> Java system property is not specified, a PRNG
421      * class name of <code>"edu.rit.util.DefaultRandom"</code> is returned. See
422      * class {@linkplain edu.rit.util.DefaultRandom} for further information.
423      *
424      * @return Default PRNG class name.
425      */
426     public static String getPjPrng() {
427         return System.getProperty("pj.prng", "edu.rit.util.DefaultRandom");
428     }
429 
430 }