001/* ***** BEGIN LICENSE BLOCK ***** 002 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 003 * 004 * The contents of this file are subject to the Mozilla Public License Version 005 * 1.1 (the "License"); you may not use this file except in compliance with 006 * the License. You may obtain a copy of the License at 007 * http://www.mozilla.org/MPL/ 008 * 009 * Software distributed under the License is distributed on an "AS IS" basis, 010 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 011 * for the specific language governing rights and limitations under the 012 * License. 013 * 014 * The Original Code is Parallel Colt. 015 * 016 * The Initial Developer of the Original Code is 017 * Piotr Wendykier, Emory University. 018 * Portions created by the Initial Developer are Copyright (C) 2007-2009 019 * the Initial Developer. All Rights Reserved. 020 * 021 * Alternatively, the contents of this file may be used under the terms of 022 * either the GNU General Public License Version 2 or later (the "GPL"), or 023 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 024 * in which case the provisions of the GPL or the LGPL are applicable instead 025 * of those above. If you wish to allow use of your version of this file only 026 * under the terms of either the GPL or the LGPL, and not to allow others to 027 * use your version of this file under the terms of the MPL, indicate your 028 * decision by deleting the provisions above and replace them with the notice 029 * and other provisions required by the GPL or the LGPL. If you do not delete 030 * the provisions above, a recipient may use your version of this file under 031 * the terms of any one of the MPL, the GPL or the LGPL. 032 * 033 * ***** END LICENSE BLOCK ***** */ 034package edu.emory.mathcs.utils; 035 036import java.util.concurrent.ExecutionException; 037import java.util.concurrent.ExecutorService; 038import java.util.concurrent.Executors; 039import java.util.concurrent.Future; 040import java.util.concurrent.ThreadFactory; 041 042/** 043 * Concurrency utilities. 044 * 045 * @author Piotr Wendykier (piotr.wendykier@gmail.com) 046 */ 047public class ConcurrencyUtils { 048 /** 049 * Thread pool. 050 */ 051 private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(new CustomThreadFactory(new CustomExceptionHandler())); 052 053 private static int THREADS_BEGIN_N_1D_FFT_2THREADS = 8192; 054 055 private static int THREADS_BEGIN_N_1D_FFT_4THREADS = 65536; 056 057 private static int THREADS_BEGIN_N_2D = 65536; 058 059 private static int THREADS_BEGIN_N_3D = 65536; 060 061 private static int NTHREADS = prevPow2(getNumberOfProcessors()); 062 063 private ConcurrencyUtils() { 064 065 } 066 067 private static class CustomExceptionHandler implements Thread.UncaughtExceptionHandler { 068 public void uncaughtException(Thread t, Throwable e) { 069 e.printStackTrace(); 070 } 071 072 } 073 074 private static class CustomThreadFactory implements ThreadFactory { 075 private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); 076 077 private final Thread.UncaughtExceptionHandler handler; 078 079 CustomThreadFactory(Thread.UncaughtExceptionHandler handler) { 080 this.handler = handler; 081 } 082 083 public Thread newThread(Runnable r) { 084 Thread t = defaultFactory.newThread(r); 085 t.setUncaughtExceptionHandler(handler); 086 t.setDaemon(true); //daemonize the thread 087 return t; 088 } 089 }; 090 091 /** 092 * Returns the number of available processors. 093 * 094 * @return number of available processors 095 */ 096 public static int getNumberOfProcessors() { 097 return Runtime.getRuntime().availableProcessors(); 098 } 099 100 /** 101 * Returns the current number of threads. 102 * 103 * @return the current number of threads. 104 */ 105 public static int getNumberOfThreads() { 106 return NTHREADS; 107 } 108 109 /** 110 * Sets the number of threads. If n is not a power-of-two number, then the 111 * number of threads is set to the closest power-of-two number less than n. 112 * 113 * @param n 114 */ 115 public static void setNumberOfThreads(int n) { 116 NTHREADS = prevPow2(n); 117 } 118 119 /** 120 * Returns the minimal size of 1D data for which two threads are used. 121 * 122 * @return the minimal size of 1D data for which two threads are used 123 */ 124 public static int getThreadsBeginN_1D_FFT_2Threads() { 125 return THREADS_BEGIN_N_1D_FFT_2THREADS; 126 } 127 128 /** 129 * Returns the minimal size of 1D data for which four threads are used. 130 * 131 * @return the minimal size of 1D data for which four threads are used 132 */ 133 public static int getThreadsBeginN_1D_FFT_4Threads() { 134 return THREADS_BEGIN_N_1D_FFT_4THREADS; 135 } 136 137 /** 138 * Returns the minimal size of 2D data for which threads are used. 139 * 140 * @return the minimal size of 2D data for which threads are used 141 */ 142 public static int getThreadsBeginN_2D() { 143 return THREADS_BEGIN_N_2D; 144 } 145 146 /** 147 * Returns the minimal size of 3D data for which threads are used. 148 * 149 * @return the minimal size of 3D data for which threads are used 150 */ 151 public static int getThreadsBeginN_3D() { 152 return THREADS_BEGIN_N_3D; 153 } 154 155 /** 156 * Sets the minimal size of 1D data for which two threads are used. 157 * 158 * @param n 159 * the minimal size of 1D data for which two threads are used 160 */ 161 public static void setThreadsBeginN_1D_FFT_2Threads(int n) { 162 if (n < 512) { 163 THREADS_BEGIN_N_1D_FFT_2THREADS = 512; 164 } else { 165 THREADS_BEGIN_N_1D_FFT_2THREADS = n; 166 } 167 } 168 169 /** 170 * Sets the minimal size of 1D data for which four threads are used. 171 * 172 * @param n 173 * the minimal size of 1D data for which four threads are used 174 */ 175 public static void setThreadsBeginN_1D_FFT_4Threads(int n) { 176 if (n < 512) { 177 THREADS_BEGIN_N_1D_FFT_4THREADS = 512; 178 } else { 179 THREADS_BEGIN_N_1D_FFT_4THREADS = n; 180 } 181 } 182 183 /** 184 * Sets the minimal size of 2D data for which threads are used. 185 * 186 * @param n 187 * the minimal size of 2D data for which threads are used 188 */ 189 public static void setThreadsBeginN_2D(int n) { 190 THREADS_BEGIN_N_2D = n; 191 } 192 193 /** 194 * Sets the minimal size of 3D data for which threads are used. 195 * 196 * @param n 197 * the minimal size of 3D data for which threads are used 198 */ 199 public static void setThreadsBeginN_3D(int n) { 200 THREADS_BEGIN_N_3D = n; 201 } 202 203 /** 204 * Resets the minimal size of 1D data for which two and four threads are 205 * used. 206 */ 207 public static void resetThreadsBeginN_FFT() { 208 THREADS_BEGIN_N_1D_FFT_2THREADS = 8192; 209 THREADS_BEGIN_N_1D_FFT_4THREADS = 65536; 210 } 211 212 /** 213 * Resets the minimal size of 2D and 3D data for which threads are used. 214 */ 215 public static void resetThreadsBeginN() { 216 THREADS_BEGIN_N_2D = 65536; 217 THREADS_BEGIN_N_3D = 65536; 218 } 219 220 /** 221 * Returns the closest power-of-two number greater than or equal to x. 222 * 223 * @param x 224 * @return the closest power-of-two number greater than or equal to x 225 */ 226 public static int nextPow2(int x) { 227 if (x < 1) 228 throw new IllegalArgumentException("x must be greater or equal 1"); 229 if ((x & (x - 1)) == 0) { 230 return x; // x is already a power-of-two number 231 } 232 x |= (x >>> 1); 233 x |= (x >>> 2); 234 x |= (x >>> 4); 235 x |= (x >>> 8); 236 x |= (x >>> 16); 237 x |= (x >>> 32); 238 return x + 1; 239 } 240 241 /** 242 * Returns the closest power-of-two number less than or equal to x. 243 * 244 * @param x 245 * @return the closest power-of-two number less then or equal to x 246 */ 247 public static int prevPow2(int x) { 248 if (x < 1) 249 throw new IllegalArgumentException("x must be greater or equal 1"); 250 return (int) Math.pow(2, Math.floor(Math.log(x) / Math.log(2))); 251 } 252 253 /** 254 * Checks if x is a power-of-two number. 255 * 256 * @param x 257 * @return true if x is a power-of-two number 258 */ 259 public static boolean isPowerOf2(int x) { 260 if (x <= 0) 261 return false; 262 else 263 return (x & (x - 1)) == 0; 264 } 265 266 /** 267 * Causes the currently executing thread to sleep (temporarily cease 268 * execution) for the specified number of milliseconds. 269 * 270 * @param millis 271 */ 272 public static void sleep(long millis) { 273 try { 274 Thread.sleep(5000); 275 } catch (InterruptedException e) { 276 e.printStackTrace(); 277 } 278 } 279 280 /** 281 * Submits a Runnable task for execution and returns a Future representing 282 * that task. 283 * 284 * @param task a Runnable task for execution 285 * @return a Future representing the task 286 */ 287 public static Future<?> submit(Runnable task) { 288 return THREAD_POOL.submit(task); 289 } 290 291 /** 292 * Waits for all threads to complete computation. 293 * 294 * @param futures 295 */ 296 public static void waitForCompletion(Future<?>[] futures) { 297 int size = futures.length; 298 try { 299 for (int j = 0; j < size; j++) { 300 futures[j].get(); 301 } 302 } catch (ExecutionException ex) { 303 ex.printStackTrace(); 304 } catch (InterruptedException e) { 305 e.printStackTrace(); 306 } 307 } 308}