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 */
048@SuppressWarnings("javadoc")
049public class BenchmarkDoubleFFT {
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 BenchmarkDoubleFFT() {
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[2]);
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                double[] 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                        DoubleFFT_1D fft = new DoubleFFT_1D(sizes1D[i]);
122                        x = new double[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                        double 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("benchmarkDoubleComplexForwardFFT_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                double[] x;
154                for (int i = 0; i < nsize; i++) {
155                        System.out.println("Real forward FFT 1D of size " + sizes1D[i]);
156                        DoubleFFT_1D fft = new DoubleFFT_1D(sizes1D[i]);
157                        x = new double[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                        double 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("benchmarkDoubleRealForwardFFT_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                double[] 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                        DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]);
192                        x = new double[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                        double 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("benchmarkDoubleComplexForwardFFT_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                double[][] 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                        DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]);
226                        x = new double[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                        double 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("benchmarkDoubleComplexForwardFFT_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                double[] 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                        DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]);
260                        x = new double[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                        double 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("benchmarkDoubleRealForwardFFT_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                double[][] 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                        DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]);
294                        x = new double[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                        double 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("benchmarkDoubleRealForwardFFT_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                double[] 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                                DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]);
330                                x = new double[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                                double 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("benchmarkDoubleComplexForwardFFT_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                double[][][] 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                        DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]);
366                        x = new double[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                        double 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("benchmarkDoubleComplexForwardFFT_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                double[] 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                                DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]);
402                                x = new double[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                                double 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("benchmarkDoubleRealForwardFFT_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                double[][][] 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                        DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]);
438                        x = new double[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                        double 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("benchmarkDoubleRealForwardFFT_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        }
481}