Mercurial > hg > sv-dependency-builds
comparison src/fftw-3.3.3/mpi/block.c @ 10:37bf6b4a2645
Add FFTW3
author | Chris Cannam |
---|---|
date | Wed, 20 Mar 2013 15:35:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
9:c0fb53affa76 | 10:37bf6b4a2645 |
---|---|
1 /* | |
2 * Copyright (c) 2003, 2007-11 Matteo Frigo | |
3 * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology | |
4 * | |
5 * This program is free software; you can redistribute it and/or modify | |
6 * it under the terms of the GNU General Public License as published by | |
7 * the Free Software Foundation; either version 2 of the License, or | |
8 * (at your option) any later version. | |
9 * | |
10 * This program is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 * GNU General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU General Public License | |
16 * along with this program; if not, write to the Free Software | |
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
18 * | |
19 */ | |
20 | |
21 #include "ifftw-mpi.h" | |
22 | |
23 INT XM(num_blocks)(INT n, INT block) | |
24 { | |
25 return (n + block - 1) / block; | |
26 } | |
27 | |
28 int XM(num_blocks_ok)(INT n, INT block, MPI_Comm comm) | |
29 { | |
30 int n_pes; | |
31 MPI_Comm_size(comm, &n_pes); | |
32 return n_pes >= XM(num_blocks)(n, block); | |
33 } | |
34 | |
35 /* Pick a default block size for dividing a problem of size n among | |
36 n_pes processes. Divide as equally as possible, while minimizing | |
37 the maximum block size among the processes as well as the number of | |
38 processes with nonzero blocks. */ | |
39 INT XM(default_block)(INT n, int n_pes) | |
40 { | |
41 return ((n + n_pes - 1) / n_pes); | |
42 } | |
43 | |
44 /* For a given block size and dimension n, compute the block size | |
45 on the given process. */ | |
46 INT XM(block)(INT n, INT block, int which_block) | |
47 { | |
48 INT d = n - which_block * block; | |
49 return d <= 0 ? 0 : (d > block ? block : d); | |
50 } | |
51 | |
52 static INT num_blocks_kind(const ddim *dim, block_kind k) | |
53 { | |
54 return XM(num_blocks)(dim->n, dim->b[k]); | |
55 } | |
56 | |
57 INT XM(num_blocks_total)(const dtensor *sz, block_kind k) | |
58 { | |
59 if (FINITE_RNK(sz->rnk)) { | |
60 int i; | |
61 INT ntot = 1; | |
62 for (i = 0; i < sz->rnk; ++i) | |
63 ntot *= num_blocks_kind(sz->dims + i, k); | |
64 return ntot; | |
65 } | |
66 else | |
67 return 0; | |
68 } | |
69 | |
70 int XM(idle_process)(const dtensor *sz, block_kind k, int which_pe) | |
71 { | |
72 return (which_pe >= XM(num_blocks_total)(sz, k)); | |
73 } | |
74 | |
75 /* Given a non-idle process which_pe, computes the coordinate | |
76 vector coords[rnk] giving the coordinates of a block in the | |
77 matrix of blocks. k specifies whether we are talking about | |
78 the input or output data distribution. */ | |
79 void XM(block_coords)(const dtensor *sz, block_kind k, int which_pe, | |
80 INT *coords) | |
81 { | |
82 int i; | |
83 A(!XM(idle_process)(sz, k, which_pe) && FINITE_RNK(sz->rnk)); | |
84 for (i = sz->rnk - 1; i >= 0; --i) { | |
85 INT nb = num_blocks_kind(sz->dims + i, k); | |
86 coords[i] = which_pe % nb; | |
87 which_pe /= nb; | |
88 } | |
89 } | |
90 | |
91 INT XM(total_block)(const dtensor *sz, block_kind k, int which_pe) | |
92 { | |
93 if (XM(idle_process)(sz, k, which_pe)) | |
94 return 0; | |
95 else { | |
96 int i; | |
97 INT N = 1, *coords; | |
98 STACK_MALLOC(INT*, coords, sizeof(INT) * sz->rnk); | |
99 XM(block_coords)(sz, k, which_pe, coords); | |
100 for (i = 0; i < sz->rnk; ++i) | |
101 N *= XM(block)(sz->dims[i].n, sz->dims[i].b[k], coords[i]); | |
102 STACK_FREE(coords); | |
103 return N; | |
104 } | |
105 } | |
106 | |
107 /* returns whether sz is local for dims >= dim */ | |
108 int XM(is_local_after)(int dim, const dtensor *sz, block_kind k) | |
109 { | |
110 if (FINITE_RNK(sz->rnk)) | |
111 for (; dim < sz->rnk; ++dim) | |
112 if (XM(num_blocks)(sz->dims[dim].n, sz->dims[dim].b[k]) > 1) | |
113 return 0; | |
114 return 1; | |
115 } | |
116 | |
117 int XM(is_local)(const dtensor *sz, block_kind k) | |
118 { | |
119 return XM(is_local_after)(0, sz, k); | |
120 } | |
121 | |
122 /* Return whether sz is distributed for k according to a simple | |
123 1d block distribution in the first or second dimensions */ | |
124 int XM(is_block1d)(const dtensor *sz, block_kind k) | |
125 { | |
126 int i; | |
127 if (!FINITE_RNK(sz->rnk)) return 0; | |
128 for (i = 0; i < sz->rnk && num_blocks_kind(sz->dims + i, k) == 1; ++i) ; | |
129 return(i < sz->rnk && i < 2 && XM(is_local_after)(i + 1, sz, k)); | |
130 | |
131 } |