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}