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 * <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(<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 }