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