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 whether a {@linkplain ParallelTeam} should use virtual threads.
238      * <p>
239      * If the <code>"pj.vt"</code> Java system property is true, then virtual threads
240      * will be used. If the property is false or not specified, then the
241      * program will use platform threads.
242      * <p>
243      * The default is false, meaning that the program will use platform threads.
244      * <p>
245      * @return true if the program should use virtual threads, false otherwise.
246      */
247     public static boolean getPjVt() {
248         String pjVtProperty = System.getProperty("pj.vt");
249         if (pjVtProperty != null) {
250             return Boolean.parseBoolean(pjVtProperty);
251         } else {
252             return false; // Default is false
253         }
254     }
255 
256     /**
257      * Determine the schedule for a parallel loop in an SMP parallel program.
258      * This is the schedule that will be used if the parallel for loop has a
259      * runtime schedule. For further information, see class {@linkplain
260      * IntegerSchedule} and class {@linkplain LongSchedule}.
261      * <p>
262      * If the <code>"pj.schedule"</code> Java property is specified, that value
263      * gives the type of schedule, which must be one of the following:
264      * <UL>
265      * <LI><code>"fixed"</code> -- Fixed schedule.
266      * <LI><code>"dynamic"</code> -- Dynamic schedule with a chunk size of 1.
267      * <LI><code>"dynamic(&lt;n&gt;)"</code> -- Dynamic schedule with a chunk size
268      * of <code>&lt;n&gt;</code>, an integer &gt;= 1.
269      * <LI><code>"guided"</code> -- Self-guided schedule with a minimum chunk size
270      * of 1.
271      * <LI><code>"guided(&lt;n&gt;)"</code> -- Self-guided schedule with a minimum
272      * chunk size of <code>&lt;n&gt;</code>, an integer &gt;= 1.
273      * <LI><code>"<I>classname</I>"</code> -- Schedule that is an instance of the
274      * given class. <I>classname</I> is the fully-qualified class name of the
275      * schedule class. The instance is constructed using the subclass's
276      * no-argument constructor.
277      * <LI><code>"<I>classname</I>(<I>arg</I>,<I>arg</I>,...)"</code> -- Schedule
278      * that is an instance of the given class. <I>classname</I> is the
279      * fully-qualified class name of the schedule class. The arguments between
280      * the parentheses are split into separate strings separated by commas.
281      * There cannot be parentheses or commas within the arguments themselves.
282      * The instance is constructed using the subclass's constructor whose
283      * argument is an array of Strings, namely the individual arguments between
284      * the parentheses.
285      * </UL>
286      * <p>
287      * If the <code>"pj.schedule"</code> Java property is not specified, the default
288      * schedule for a runtime schedule is used. Normally this is a fixed
289      * schedule, but a program can specify a different default.
290      *
291      * @return Schedule for a parallel for loop (one of the above strings), or
292      * null if the <code>"pj.schedule"</code> Java property is not specified.
293      */
294     public static String getPjSchedule() {
295         return System.getProperty("pj.schedule");
296     }
297 
298     /**
299      * Determine the host name of the Job Scheduler Daemon to use when running a
300      * 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.host"</code> Java system property is specified, it gives the
307      * Job Scheduler Daemon's host name (or IP address).
308      * <p>
309      * If the <code>"pj.host"</code> Java system property is not specified, a host
310      * name of <code>"localhost"</code> is returned.
311      *
312      * @return Job Scheduler Daemon host name.
313      */
314     public static String getPjHost() {
315         return System.getProperty("pj.host", "localhost");
316     }
317 
318     /**
319      * Determine the port number of the Job Scheduler Daemon to use when running
320      * a cluster parallel program. The program contacts the Job Scheduler Daemon
321      * when the <code>Comm.init()</code> method is executed (see class {@linkplain
322      * Comm}). For further information, see package {@linkplain
323      * edu.rit.pj.cluster edu.rit.pj.cluster} and class {@linkplain
324      * edu.rit.pj.cluster.JobScheduler}.
325      * <p>
326      * If the <code>"pj.port"</code> Java system property is specified, it gives the
327      * Job Scheduler Daemon's port number.
328      * <p>
329      * If the <code>"pj.port"</code> Java system property is not specified, the
330      * well-known Parallel Java port number (20617) is returned.
331      *
332      * @return Job Scheduler Daemon port number.
333      * @throws java.lang.IllegalArgumentException (unchecked exception) Thrown if the
334      *                                  <code>"pj.port"</code> property value is not an integer.
335      */
336     public static int getPjPort() {
337         try {
338             String pj_port = System.getProperty("pj.port");
339             int port
340                     = pj_port == null
341                     ? // edu.rit.pj.cluster.Constants.PJ_PORT :
342                     20617
343                     : Integer.parseInt(pj_port);
344             return port;
345         } catch (NumberFormatException exc) {
346             throw new IllegalArgumentException("pj.port system property is not an integer");
347         }
348     }
349 
350     /**
351      * Determine the maximum amount of time (seconds) the job is allowed to run
352      * when running a cluster parallel program. If a program running in the
353      * Parallel Java job queue has not finished in the given amount of time, the
354      * job frontend process automatically termintes the job when the given
355      * number of seconds have elapsed since the job started executing. If a
356      * program is not running in the Parallel Java job queue (if there is no Job
357      * Scheduler Daemon present), then the job time setting is ignored and the
358      * program will not time out.
359      * <p>
360      * If the <code>"pj.jobtime"</code> Java system property is specified, it must
361      * be an integer greater than or equal to 1, and that gives the the maximum
362      * job timeout in seconds.
363      * <p>
364      * If the <code>"pj.jobtime"</code> Java system property is not specified, a
365      * value of 0 is returned to signify that there is no job timeout.
366      *
367      * @return Job timeout (seconds), or 0 if no job timeout.
368      * @throws java.lang.IllegalArgumentException (unchecked exception) Thrown if the
369      *                                  <code>"pj.jobtime"</code> property value is not an integer greater than or
370      *                                  equal to 1.
371      */
372     public static int getPjJobTime() {
373         try {
374             String pj_jobtime = System.getProperty("pj.jobtime");
375             if (pj_jobtime == null) {
376                 return 0;
377             } else {
378                 int jobtime = Integer.parseInt(pj_jobtime);
379                 if (jobtime < 1) {
380                     throw new IllegalArgumentException("pj.jobtime system property is not an integer >= 1");
381                 }
382                 return jobtime;
383             }
384         } catch (NumberFormatException exc) {
385             throw new IllegalArgumentException("pj.jobtime system property is not an integer >= 1");
386         }
387     }
388 
389     /**
390      * Determine the JVM flags to include on the Java command line when running
391      * a backend process in a cluster parallel program. When a job backend
392      * process is started, the JVM flags are included on the command line
393      * immediately after the <code>"java"</code> command. These flags then control
394      * the job backend process's JVM. For further information, see package
395      * {@linkplain edu.rit.pj.cluster edu.rit.pj.cluster}.
396      * <p>
397      * If the <code>"pj.jvmflags"</code> Java system property is specified, it gives
398      * the JVM flags exactly as they are to appear on the Java command line. If
399      * there are multiple flags separated by whitespace, the
400      * <code>"pj.jvmflags"</code> Java system property must be enclosed in quotation
401      * marks.
402      * <p>
403      * If the <code>"pj.jvmflags"</code> Java system property is not specified,
404      * there are no JVM flags, and an empty string is returned.
405      * <p>
406      * <B>Example.</B> To cause the job backend processes' JVMs to use an
407      * initial heap size of 4 MB and a maximum heap size of 128 MB, specify the
408      * <code>"pj.jvmflags"</code> property as follows when running the program:
409      *
410      * <code>&nbsp;&nbsp;&nbsp;&nbsp;java -Dpj.jvmflags="-Xms4m -Xmx128m" . .
411      * .</code>
412      * <p>
413      * Note that quotation marks are needed around the property value because of
414      * the embedded whitespace. This property value causes the Job Launcher
415      * Daemon to launch each job backend process's JVM with this command:
416      *
417      * <code>&nbsp;&nbsp;&nbsp;&nbsp;java -Xms4m -Xmx128m . . .</code>
418      * <p>
419      * which in turn tells each job backend process's JVM to use initial and
420      * maximum heap sizes of 4 MB and 128 MB.
421      *
422      * @return JVM flags.
423      */
424     public static String getPjJvmFlags() {
425         return System.getProperty("pj.jvmflags", "");
426     }
427 
428     /**
429      * Determine the fully-qualified class name of the default pseudorandom
430      * number generator (PRNG) class.
431      * <p>
432      * If the <code>"pj.prng"</code> Java system property is specified, it gives the
433      * fully-qualified class name of the PRNG class that the static
434      * <code>getInstance(long)</code> method in class {@linkplain
435      * edu.rit.util.Random} will construct. Specifying the <code>"pj.prng"</code>
436      * property will substitute a different PRNG algorithm into a program
437      * without needing to recompile. See class {@linkplain edu.rit.util.Random}
438      * for further information.
439      * <p>
440      * If the <code>"pj.prng"</code> Java system property is not specified, a PRNG
441      * class name of <code>"edu.rit.util.DefaultRandom"</code> is returned. See
442      * class {@linkplain edu.rit.util.DefaultRandom} for further information.
443      *
444      * @return Default PRNG class name.
445      */
446     public static String getPjPrng() {
447         return System.getProperty("pj.prng", "edu.rit.util.DefaultRandom");
448     }
449 
450 }