annotate src/fftw-3.3.5/mpi/choose-radix.c @ 43:5ea0608b923f

Current zlib source
author Chris Cannam
date Tue, 18 Oct 2016 14:33:52 +0100
parents 2cd0e3b3e1fd
children
rev   line source
Chris@42 1 /*
Chris@42 2 * Copyright (c) 2003, 2007-14 Matteo Frigo
Chris@42 3 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
Chris@42 4 *
Chris@42 5 * This program is free software; you can redistribute it and/or modify
Chris@42 6 * it under the terms of the GNU General Public License as published by
Chris@42 7 * the Free Software Foundation; either version 2 of the License, or
Chris@42 8 * (at your option) any later version.
Chris@42 9 *
Chris@42 10 * This program is distributed in the hope that it will be useful,
Chris@42 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@42 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@42 13 * GNU General Public License for more details.
Chris@42 14 *
Chris@42 15 * You should have received a copy of the GNU General Public License
Chris@42 16 * along with this program; if not, write to the Free Software
Chris@42 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Chris@42 18 *
Chris@42 19 */
Chris@42 20
Chris@42 21 #include "ifftw-mpi.h"
Chris@42 22
Chris@42 23 /* Return the radix r for a 1d MPI transform of a distributed dimension d,
Chris@42 24 with the given flags and transform size. That is, decomposes d.n
Chris@42 25 as r * m, Cooley-Tukey style. Also computes the block sizes rblock
Chris@42 26 and mblock. Returns 0 if such a decomposition is not feasible.
Chris@42 27 This is unfortunately somewhat complicated.
Chris@42 28
Chris@42 29 A distributed Cooley-Tukey algorithm works as follows (see dft-rank1.c):
Chris@42 30
Chris@42 31 d.n is initially distributed as an m x r array with block size mblock[IB].
Chris@42 32 Then it is internally transposed to an r x m array with block size
Chris@42 33 rblock[IB]. Then it is internally transposed to m x r again with block
Chris@42 34 size mblock[OB]. Finally, it is transposed to r x m with block size
Chris@42 35 rblock[IB].
Chris@42 36
Chris@42 37 If flags & SCRAMBLED_IN, then the first transpose is skipped (the array
Chris@42 38 starts out as r x m). If flags & SCRAMBLED_OUT, then the last transpose
Chris@42 39 is skipped (the array ends up as m x r). To make sure the forward
Chris@42 40 and backward transforms use the same "scrambling" format, we swap r
Chris@42 41 and m when sign != FFT_SIGN.
Chris@42 42
Chris@42 43 There are some downsides to this, especially in the case where
Chris@42 44 either m or r is not divisible by n_pes. For one thing, it means
Chris@42 45 that in general we can't use the same block size for the input and
Chris@42 46 output. For another thing, it means that we can't in general honor
Chris@42 47 a user's "requested" block sizes in d.b[]. Therefore, for simplicity,
Chris@42 48 we simply ignore d.b[] for now.
Chris@42 49 */
Chris@42 50 INT XM(choose_radix)(ddim d, int n_pes, unsigned flags, int sign,
Chris@42 51 INT rblock[2], INT mblock[2])
Chris@42 52 {
Chris@42 53 INT r, m;
Chris@42 54
Chris@42 55 UNUSED(flags); /* we would need this if we paid attention to d.b[*] */
Chris@42 56
Chris@42 57 /* If n_pes is a factor of d.n, then choose r to be d.n / n_pes.
Chris@42 58 This not only ensures that the input (the m dimension) is
Chris@42 59 equally distributed if possible, and at the r dimension is
Chris@42 60 maximally equally distributed (if d.n/n_pes >= n_pes), it also
Chris@42 61 makes one of the local transpositions in the algorithm
Chris@42 62 trivial. */
Chris@42 63 if (d.n % n_pes == 0 /* it's good if n_pes divides d.n ...*/
Chris@42 64 && d.n / n_pes >= n_pes /* .. unless we can't use n_pes processes */)
Chris@42 65 r = d.n / n_pes;
Chris@42 66 else { /* n_pes does not divide d.n, pick a factor close to sqrt(d.n) */
Chris@42 67 for (r = X(isqrt)(d.n); d.n % r != 0; ++r)
Chris@42 68 ;
Chris@42 69 }
Chris@42 70 if (r == 1 || r == d.n) return 0; /* punt if we can't reduce size */
Chris@42 71
Chris@42 72 if (sign != FFT_SIGN) { /* swap {m,r} so that scrambling is reversible */
Chris@42 73 m = r;
Chris@42 74 r = d.n / m;
Chris@42 75 }
Chris@42 76 else
Chris@42 77 m = d.n / r;
Chris@42 78
Chris@42 79 rblock[IB] = rblock[OB] = XM(default_block)(r, n_pes);
Chris@42 80 mblock[IB] = mblock[OB] = XM(default_block)(m, n_pes);
Chris@42 81
Chris@42 82 return r;
Chris@42 83 }