/*
* Copyright (c) 2003, 2007-8 Matteo Frigo
* Copyright (c) 2003, 2007-8 Massachusetts Institute of Technology
* Copyright (c) 2010-2013 Michael Pippig
*
* This file is part of PFFT.
*
* PFFT is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PFFT is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PFFT. If not, see .
*
*/
#include "pfft.h"
#include "ipfft.h"
#include
static INT default_block_size(INT global_array_size, int num_procs);
void PX(local_block_size_and_offset)(
INT global_array_size, INT global_block_size, int which_block,
INT *local_block_size, INT *local_block_start)
{
/* Block index runs from blockStart <= index < blockEnd */
*local_block_start = PX(local_block_offset)(global_array_size, global_block_size, which_block);
*local_block_size = PX(local_block_size)(global_array_size, global_block_size, which_block);
}
INT PX(local_block_size_shifted)(
INT global_array_size, INT global_block_size, int shift, MPI_Comm comm_cart_1d
)
{
int num_procs, coord;
MPI_Comm_size(comm_cart_1d, &num_procs);
PX(get_mpi_cart_coord_1d)(comm_cart_1d, &coord);
return PX(local_block_size)(global_array_size, global_block_size, PX(pos_mod)(coord+shift, num_procs));
}
INT PX(local_block_offset)(INT global_array_size, INT global_block_size, int which_block)
{
/* For a given globalBlockSize and arraySize, compute the localBlockSize
* and the localBlockOffset on the given process. */
INT blocks = PX(num_blocks)(global_array_size, global_block_size);
return (which_block >= blocks) ? 0 : which_block * global_block_size;
}
INT PX(local_block_size)(INT global_array_size, INT global_block_size, int which_block)
{
INT blocks = PX(num_blocks)(global_array_size, global_block_size);
if (which_block >= blocks)
return 0;
else
return ((which_block == blocks - 1)
? (global_array_size - which_block * global_block_size) : global_block_size);
}
INT PX(global_block_size)(INT global_array_size, INT user_block_size, int num_procs)
{
/* calculate default globalBlockSize if userBlockSize equals PFFT_DEFAULT_BLOCK */
return (user_block_size == PFFT_DEFAULT_BLOCK) ?
default_block_size(global_array_size, num_procs) : user_block_size;
}
INT PX(num_blocks)(INT global_array_size, INT global_block_size)
{
return (global_array_size + global_block_size - 1) / global_block_size;
}
static INT default_block_size(INT global_array_size, int num_procs)
{
/* Pick a default block size for dividing an array of size arrayLength among
* numProcs processes. Divide as equally as possible, while minimizing
* the maximum block size among the processes as well as the number of
* processes with nonzero blocks. */
return ((global_array_size + num_procs - 1) / num_procs);
}