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 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(<n>)"</code> -- Dynamic schedule with a chunk size 248 * of <code><n></code>, an integer >= 1. 249 * <LI><code>"guided"</code> -- Self-guided schedule with a minimum chunk size 250 * of 1. 251 * <LI><code>"guided(<n>)"</code> -- Self-guided schedule with a minimum 252 * chunk size of <code><n></code>, an integer >= 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> 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> 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 }