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> >= <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> < <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> 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 *
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(<n>)"</code> -- Dynamic schedule with a chunk size
268 * of <code><n></code>, an integer >= 1.
269 * <LI><code>"guided"</code> -- Self-guided schedule with a minimum chunk size
270 * of 1.
271 * <LI><code>"guided(<n>)"</code> -- Self-guided schedule with a minimum
272 * chunk size of <code><n></code>, an integer >= 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> 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> 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 }