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 JTransforms. 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 ***** */ 034 035package edu.emory.mathcs.jtransforms.fft; 036 037import java.util.Arrays; 038 039import edu.emory.mathcs.utils.ConcurrencyUtils; 040import edu.emory.mathcs.utils.IOUtils; 041 042/** 043 * Benchmark of double precision FFT's 044 * 045 * @author Piotr Wendykier (piotr.wendykier@gmail.com) 046 * 047 */ 048public class BenchmarkDoubleFFT { 049 050 private static int nthread = 8; 051 052 private static int niter = 200; 053 054 private static int nsize = 16; 055 056 private static int threadsBegin2D = 65636; 057 058 private static int threadsBegin3D = 65636; 059 060 private static boolean doWarmup = true; 061 062 private static int[] sizes1D = new int[] { 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 10368, 27000, 75600, 165375, 362880, 1562500, 3211264, 6250000 }; 063 064 private static int[] sizes2D = new int[] { 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 260, 520, 1050, 1458, 1960, 2916, 4116, 5832 }; 065 066 private static int[] sizes3D = new int[] { 8, 16, 32, 64, 128, 256, 512, 1024, 5, 17, 30, 95, 180, 270, 324, 420 }; 067 068 private static boolean doScaling = false; 069 070 private BenchmarkDoubleFFT() { 071 072 } 073 074 public static void parseArguments(String[] args) { 075 if (args.length > 0) { 076 nthread = Integer.parseInt(args[0]); 077 threadsBegin2D = Integer.parseInt(args[1]); 078 threadsBegin3D = Integer.parseInt(args[2]); 079 niter = Integer.parseInt(args[3]); 080 doWarmup = Boolean.parseBoolean(args[4]); 081 doScaling = Boolean.parseBoolean(args[5]); 082 nsize = Integer.parseInt(args[6]); 083 sizes1D = new int[nsize]; 084 sizes2D = new int[nsize]; 085 sizes3D = new int[nsize]; 086 for (int i = 0; i < nsize; i++) { 087 sizes1D[i] = Integer.parseInt(args[7 + i]); 088 } 089 for (int i = 0; i < nsize; i++) { 090 sizes2D[i] = Integer.parseInt(args[7 + nsize + i]); 091 } 092 for (int i = 0; i < nsize; i++) { 093 sizes3D[i] = Integer.parseInt(args[7 + nsize + nsize + i]); 094 } 095 } else { 096 System.out.println("Default settings are used."); 097 } 098 ConcurrencyUtils.setNumberOfThreads(nthread); 099 ConcurrencyUtils.setThreadsBeginN_2D(threadsBegin2D); 100 ConcurrencyUtils.setThreadsBeginN_3D(threadsBegin3D); 101 System.out.println("nthred = " + nthread); 102 System.out.println("threadsBegin2D = " + threadsBegin2D); 103 System.out.println("threadsBegin3D = " + threadsBegin3D); 104 System.out.println("niter = " + niter); 105 System.out.println("doWarmup = " + doWarmup); 106 System.out.println("doScaling = " + doScaling); 107 System.out.println("nsize = " + nsize); 108 System.out.println("sizes1D[] = " + Arrays.toString(sizes1D)); 109 System.out.println("sizes2D[] = " + Arrays.toString(sizes2D)); 110 System.out.println("sizes3D[] = " + Arrays.toString(sizes3D)); 111 } 112 113 public static void benchmarkComplexForward_1D() { 114 double[] x; 115 double[] times = new double[nsize]; 116 for (int i = 0; i < nsize; i++) { 117 System.out.println("Complex forward FFT 1D of size " + sizes1D[i]); 118 DoubleFFT_1D fft = new DoubleFFT_1D(sizes1D[i]); 119 x = new double[2 * sizes1D[i]]; 120 if (doWarmup) { // call the transform twice to warm up 121 IOUtils.fillMatrix_1D(2 * sizes1D[i], x); 122 fft.complexForward(x); 123 IOUtils.fillMatrix_1D(2 * sizes1D[i], x); 124 fft.complexForward(x); 125 } 126 double av_time = 0; 127 long elapsedTime = 0; 128 for (int j = 0; j < niter; j++) { 129 IOUtils.fillMatrix_1D(2 * sizes1D[i], x); 130 elapsedTime = System.nanoTime(); 131 fft.complexForward(x); 132 elapsedTime = System.nanoTime() - elapsedTime; 133 av_time = av_time + elapsedTime; 134 } 135 times[i] = (double) av_time / 1000000.0 / (double) niter; 136 System.out.println("\tAverage execution time: " + String.format("%.2f", av_time / 1000000.0 / (double) niter) + " msec"); 137 x = null; 138 fft = null; 139 System.gc(); 140 ConcurrencyUtils.sleep(5000); 141 } 142 IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleComplexForwardFFT_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times); 143 144 } 145 146 public static void benchmarkRealForward_1D() { 147 double[] times = new double[nsize]; 148 double[] x; 149 for (int i = 0; i < nsize; i++) { 150 System.out.println("Real forward FFT 1D of size " + sizes1D[i]); 151 DoubleFFT_1D fft = new DoubleFFT_1D(sizes1D[i]); 152 x = new double[2 * sizes1D[i]]; 153 if (doWarmup) { // call the transform twice to warm up 154 IOUtils.fillMatrix_1D(sizes1D[i], x); 155 fft.realForwardFull(x); 156 IOUtils.fillMatrix_1D(sizes1D[i], x); 157 fft.realForwardFull(x); 158 } 159 double av_time = 0; 160 long elapsedTime = 0; 161 for (int j = 0; j < niter; j++) { 162 IOUtils.fillMatrix_1D(sizes1D[i], x); 163 elapsedTime = System.nanoTime(); 164 fft.realForwardFull(x); 165 elapsedTime = System.nanoTime() - elapsedTime; 166 av_time = av_time + elapsedTime; 167 } 168 times[i] = (double) av_time / 1000000.0 / (double) niter; 169 System.out.println("\tAverage execution time: " + String.format("%.2f", av_time / 1000000.0 / (double) niter) + " msec"); 170 x = null; 171 fft = null; 172 System.gc(); 173 ConcurrencyUtils.sleep(5000); 174 } 175 IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleRealForwardFFT_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times); 176 177 } 178 179 public static void benchmarkComplexForward_2D_input_1D() { 180 double[] times = new double[nsize]; 181 double[] x; 182 for (int i = 0; i < nsize; i++) { 183 System.out.println("Complex forward FFT 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); 184 DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); 185 x = new double[sizes2D[i] * 2 * sizes2D[i]]; 186 if (doWarmup) { // call the transform twice to warm up 187 IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); 188 fft2.complexForward(x); 189 IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); 190 fft2.complexForward(x); 191 } 192 double av_time = 0; 193 long elapsedTime = 0; 194 for (int j = 0; j < niter; j++) { 195 IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); 196 elapsedTime = System.nanoTime(); 197 fft2.complexForward(x); 198 elapsedTime = System.nanoTime() - elapsedTime; 199 av_time = av_time + elapsedTime; 200 } 201 times[i] = (double) av_time / 1000000.0 / (double) niter; 202 System.out.println("\tAverage execution time: " + String.format("%.2f", av_time / 1000000.0 / (double) niter) + " msec"); 203 x = null; 204 fft2 = null; 205 System.gc(); 206 ConcurrencyUtils.sleep(5000); 207 } 208 IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleComplexForwardFFT_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times); 209 } 210 211 public static void benchmarkComplexForward_2D_input_2D() { 212 double[] times = new double[nsize]; 213 double[][] x; 214 for (int i = 0; i < nsize; i++) { 215 System.out.println("Complex forward FFT 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); 216 DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); 217 x = new double[sizes2D[i]][2 * sizes2D[i]]; 218 if (doWarmup) { // call the transform twice to warm up 219 IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); 220 fft2.complexForward(x); 221 IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); 222 fft2.complexForward(x); 223 } 224 double av_time = 0; 225 long elapsedTime = 0; 226 for (int j = 0; j < niter; j++) { 227 IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); 228 elapsedTime = System.nanoTime(); 229 fft2.complexForward(x); 230 elapsedTime = System.nanoTime() - elapsedTime; 231 av_time = av_time + elapsedTime; 232 } 233 times[i] = (double) av_time / 1000000.0 / (double) niter; 234 System.out.println("\tAverage execution time: " + String.format("%.2f", av_time / 1000000.0 / (double) niter) + " msec"); 235 x = null; 236 fft2 = null; 237 System.gc(); 238 ConcurrencyUtils.sleep(5000); 239 } 240 IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleComplexForwardFFT_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times); 241 } 242 243 public static void benchmarkRealForward_2D_input_1D() { 244 double[] times = new double[nsize]; 245 double[] x; 246 for (int i = 0; i < nsize; i++) { 247 System.out.println("Real forward FFT 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); 248 DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); 249 x = new double[sizes2D[i] * 2 * sizes2D[i]]; 250 if (doWarmup) { // call the transform twice to warm up 251 IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); 252 fft2.realForwardFull(x); 253 IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); 254 fft2.realForwardFull(x); 255 } 256 double av_time = 0; 257 long elapsedTime = 0; 258 for (int j = 0; j < niter; j++) { 259 IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); 260 elapsedTime = System.nanoTime(); 261 fft2.realForwardFull(x); 262 elapsedTime = System.nanoTime() - elapsedTime; 263 av_time = av_time + elapsedTime; 264 } 265 times[i] = (double) av_time / 1000000.0 / (double) niter; 266 System.out.println("\tAverage execution time: " + String.format("%.2f", av_time / 1000000.0 / (double) niter) + " msec"); 267 x = null; 268 fft2 = null; 269 System.gc(); 270 ConcurrencyUtils.sleep(5000); 271 } 272 IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleRealForwardFFT_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times); 273 } 274 275 public static void benchmarkRealForward_2D_input_2D() { 276 double[] times = new double[nsize]; 277 double[][] x; 278 for (int i = 0; i < nsize; i++) { 279 System.out.println("Real forward FFT 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); 280 DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); 281 x = new double[sizes2D[i]][2 * sizes2D[i]]; 282 if (doWarmup) { // call the transform twice to warm up 283 IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); 284 fft2.realForwardFull(x); 285 IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); 286 fft2.realForwardFull(x); 287 } 288 double av_time = 0; 289 long elapsedTime = 0; 290 for (int j = 0; j < niter; j++) { 291 IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); 292 elapsedTime = System.nanoTime(); 293 fft2.realForwardFull(x); 294 elapsedTime = System.nanoTime() - elapsedTime; 295 av_time = av_time + elapsedTime; 296 } 297 times[i] = (double) av_time / 1000000.0 / (double) niter; 298 System.out.println("\tAverage execution time: " + String.format("%.2f", av_time / 1000000.0 / (double) niter) + " msec"); 299 x = null; 300 fft2 = null; 301 System.gc(); 302 ConcurrencyUtils.sleep(5000); 303 } 304 IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleRealForwardFFT_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times); 305 } 306 307 public static void benchmarkComplexForward_3D_input_1D() { 308 double[] times = new double[nsize]; 309 double[] x; 310 for (int i = 0; i < nsize; i++) { 311 if (sizes3D[i] < 1024) { 312 System.out.println("Complex forward FFT 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); 313 DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); 314 x = new double[sizes3D[i] * sizes3D[i] * 2 * sizes3D[i]]; 315 if (doWarmup) { // call the transform twice to warm up 316 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); 317 fft3.complexForward(x); 318 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); 319 fft3.complexForward(x); 320 } 321 double av_time = 0; 322 long elapsedTime = 0; 323 for (int j = 0; j < niter; j++) { 324 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); 325 elapsedTime = System.nanoTime(); 326 fft3.complexForward(x); 327 elapsedTime = System.nanoTime() - elapsedTime; 328 av_time = av_time + elapsedTime; 329 } 330 times[i] = (double) av_time / 1000000.0 / (double) niter; 331 System.out.println("\tAverage execution time: " + String.format("%.2f", av_time / 1000000.0 / (double) niter) + " msec"); 332 x = null; 333 fft3 = null; 334 System.gc(); 335 ConcurrencyUtils.sleep(5000); 336 } 337 } 338 IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleComplexForwardFFT_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times); 339 } 340 341 public static void benchmarkComplexForward_3D_input_3D() { 342 double[] times = new double[nsize]; 343 double[][][] x; 344 for (int i = 0; i < nsize; i++) { 345 System.out.println("Complex forward FFT 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); 346 DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); 347 x = new double[sizes3D[i]][sizes3D[i]][2 * sizes3D[i]]; 348 if (doWarmup) { // call the transform twice to warm up 349 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); 350 fft3.complexForward(x); 351 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); 352 fft3.complexForward(x); 353 } 354 double av_time = 0; 355 long elapsedTime = 0; 356 for (int j = 0; j < niter; j++) { 357 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); 358 elapsedTime = System.nanoTime(); 359 fft3.complexForward(x); 360 elapsedTime = System.nanoTime() - elapsedTime; 361 av_time = av_time + elapsedTime; 362 } 363 times[i] = (double) av_time / 1000000.0 / (double) niter; 364 System.out.println("\tAverage execution time: " + String.format("%.2f", av_time / 1000000.0 / (double) niter) + " msec"); 365 x = null; 366 fft3 = null; 367 System.gc(); 368 ConcurrencyUtils.sleep(5000); 369 } 370 IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleComplexForwardFFT_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times); 371 } 372 373 public static void benchmarkRealForward_3D_input_1D() { 374 double[] times = new double[nsize]; 375 double[] x; 376 for (int i = 0; i < nsize; i++) { 377 if (sizes3D[i] < 1024) { 378 System.out.println("Real forward FFT 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); 379 DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); 380 x = new double[sizes3D[i] * sizes3D[i] * 2 * sizes3D[i]]; 381 if (doWarmup) { // call the transform twice to warm up 382 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); 383 fft3.realForwardFull(x); 384 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); 385 fft3.realForwardFull(x); 386 } 387 double av_time = 0; 388 long elapsedTime = 0; 389 for (int j = 0; j < niter; j++) { 390 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); 391 elapsedTime = System.nanoTime(); 392 fft3.realForwardFull(x); 393 elapsedTime = System.nanoTime() - elapsedTime; 394 av_time = av_time + elapsedTime; 395 } 396 times[i] = (double) av_time / 1000000.0 / (double) niter; 397 System.out.println("\tAverage execution time: " + String.format("%.2f", av_time / 1000000.0 / (double) niter) + " msec"); 398 x = null; 399 fft3 = null; 400 System.gc(); 401 ConcurrencyUtils.sleep(5000); 402 } 403 } 404 IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleRealForwardFFT_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times); 405 } 406 407 public static void benchmarkRealForward_3D_input_3D() { 408 double[] times = new double[nsize]; 409 double[][][] x; 410 for (int i = 0; i < nsize; i++) { 411 System.out.println("Real forward FFT 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); 412 DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); 413 x = new double[sizes3D[i]][sizes3D[i]][2 * sizes3D[i]]; 414 if (doWarmup) { // call the transform twice to warm up 415 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); 416 fft3.realForwardFull(x); 417 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); 418 fft3.realForwardFull(x); 419 } 420 double av_time = 0; 421 long elapsedTime = 0; 422 for (int j = 0; j < niter; j++) { 423 IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); 424 elapsedTime = System.nanoTime(); 425 fft3.realForwardFull(x); 426 elapsedTime = System.nanoTime() - elapsedTime; 427 av_time = av_time + elapsedTime; 428 } 429 times[i] = (double) av_time / 1000000.0 / (double) niter; 430 System.out.println("\tAverage execution time: " + String.format("%.2f", av_time / 1000000.0 / (double) niter) + " msec"); 431 x = null; 432 fft3 = null; 433 System.gc(); 434 ConcurrencyUtils.sleep(5000); 435 } 436 IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleRealForwardFFT_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times); 437 } 438 439 public static void main(String[] args) { 440 parseArguments(args); 441 benchmarkComplexForward_1D(); 442 benchmarkRealForward_1D(); 443 benchmarkComplexForward_2D_input_1D(); 444 benchmarkComplexForward_2D_input_2D(); 445 benchmarkRealForward_2D_input_1D(); 446 benchmarkRealForward_2D_input_2D(); 447 benchmarkComplexForward_3D_input_1D(); 448 benchmarkComplexForward_3D_input_3D(); 449 benchmarkRealForward_3D_input_1D(); 450 benchmarkRealForward_3D_input_3D(); 451 System.exit(0); 452 453 } 454}