~ubuntu-branches/ubuntu/utopic/fftw3/utopic

« back to all changes in this revision

Viewing changes to mpi/block.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2011-12-14 13:21:22 UTC
  • mfrom: (3.1.5 sid)
  • Revision ID: package-import@ubuntu.com-20111214132122-l4avyl2kkr7vq5aj
Tags: 3.3-1ubuntu1
* Merge with Debian; remaining changes:
  - Revert the ARM workaround.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 n_blocks = XM(num_blocks)(n, block);
 
49
     if (which_block >= n_blocks)
 
50
          return 0;
 
51
     else
 
52
          return ((which_block == n_blocks - 1)
 
53
                  ? (n - which_block * block) : block);
 
54
}
 
55
 
 
56
static INT num_blocks_kind(const ddim *dim, block_kind k)
 
57
{
 
58
     return XM(num_blocks)(dim->n, dim->b[k]);
 
59
}
 
60
 
 
61
INT XM(num_blocks_total)(const dtensor *sz, block_kind k)
 
62
{
 
63
     if (FINITE_RNK(sz->rnk)) {
 
64
          int i;
 
65
          INT ntot = 1;
 
66
          for (i = 0; i < sz->rnk; ++i)
 
67
               ntot *= num_blocks_kind(sz->dims + i, k);
 
68
          return ntot;
 
69
     }
 
70
     else
 
71
          return 0;
 
72
}
 
73
 
 
74
int XM(idle_process)(const dtensor *sz, block_kind k, int which_pe)
 
75
{
 
76
     return (which_pe >= XM(num_blocks_total)(sz, k));
 
77
}
 
78
 
 
79
/* Given a non-idle process which_pe, computes the coordinate
 
80
   vector coords[rnk] giving the coordinates of a block in the
 
81
   matrix of blocks.  k specifies whether we are talking about
 
82
   the input or output data distribution. */
 
83
void XM(block_coords)(const dtensor *sz, block_kind k, int which_pe, 
 
84
                     INT *coords)
 
85
{
 
86
     int i;
 
87
     A(!XM(idle_process)(sz, k, which_pe) && FINITE_RNK(sz->rnk));
 
88
     for (i = sz->rnk - 1; i >= 0; --i) {
 
89
          INT nb = num_blocks_kind(sz->dims + i, k);
 
90
          coords[i] = which_pe % nb;
 
91
          which_pe /= nb;
 
92
     }
 
93
}
 
94
 
 
95
INT XM(total_block)(const dtensor *sz, block_kind k, int which_pe)
 
96
{
 
97
     if (XM(idle_process)(sz, k, which_pe))
 
98
          return 0;
 
99
     else {
 
100
          int i;
 
101
          INT N = 1, *coords;
 
102
          STACK_MALLOC(INT*, coords, sizeof(INT) * sz->rnk);
 
103
          XM(block_coords)(sz, k, which_pe, coords);
 
104
          for (i = 0; i < sz->rnk; ++i)
 
105
               N *= XM(block)(sz->dims[i].n, sz->dims[i].b[k], coords[i]);
 
106
          STACK_FREE(coords);
 
107
          return N;
 
108
     }
 
109
}
 
110
 
 
111
/* returns whether sz is local for dims >= dim */
 
112
int XM(is_local_after)(int dim, const dtensor *sz, block_kind k)
 
113
{
 
114
     if (FINITE_RNK(sz->rnk))
 
115
          for (; dim < sz->rnk; ++dim)
 
116
               if (XM(num_blocks)(sz->dims[dim].n, sz->dims[dim].b[k]) > 1)
 
117
                    return 0;
 
118
     return 1;
 
119
}
 
120
 
 
121
int XM(is_local)(const dtensor *sz, block_kind k)
 
122
{
 
123
     return XM(is_local_after)(0, sz, k);
 
124
}
 
125
 
 
126
/* Return whether sz is distributed for k according to a simple
 
127
   1d block distribution in the first or second dimensions */
 
128
int XM(is_block1d)(const dtensor *sz, block_kind k)
 
129
{
 
130
     int i;
 
131
     if (!FINITE_RNK(sz->rnk)) return 0;
 
132
     for (i = 0; i < sz->rnk && num_blocks_kind(sz->dims + i, k) == 1; ++i) ;
 
133
     return(i < sz->rnk && i < 2 && XM(is_local_after)(i + 1, sz, k));
 
134
 
 
135
}