140 строки
3.8 KiB
C
140 строки
3.8 KiB
C
/*
|
|
* Copyright (c) 2009-2012 Oak Ridge National Laboratory. All rights reserved.
|
|
* Copyright (c) 2009-2012 Mellanox Technologies. All rights reserved.
|
|
* $COPYRIGHT$
|
|
*
|
|
* Additional copyrights may follow
|
|
*
|
|
* $HEADER$
|
|
*/
|
|
#include "ompi_config.h"
|
|
|
|
#include "bcol_ptpcoll.h"
|
|
#include "bcol_ptpcoll_utils.h"
|
|
|
|
/*
|
|
* Return closet power of K, for the number, and the number
|
|
*/
|
|
int pow_k_calc(int k, int number, int *out_number)
|
|
{
|
|
int power = 0;
|
|
int n = 1;
|
|
|
|
while (n < number) {
|
|
n *= k;
|
|
++power;
|
|
}
|
|
|
|
if (n > number) {
|
|
n /= k;
|
|
--power;
|
|
}
|
|
if (NULL != out_number) {
|
|
*out_number = n;
|
|
}
|
|
|
|
return power;
|
|
}
|
|
|
|
/*
|
|
* Communicator rank to group index conversion function for K-nomial tree.
|
|
* Complexity: (K-1) Log _base_K N
|
|
*
|
|
* Input:
|
|
* my_group_index - my process index in the group
|
|
* comm_source - the communicator rank of the source of data
|
|
* radix - radix of K-nomial tree
|
|
* group_size - the size of my group
|
|
* group_array[] - one to one map from group index to communicator rank
|
|
*
|
|
* Output:
|
|
* Group index for comm_source.
|
|
*/
|
|
|
|
int get_group_index_and_distance_for_binomial(int my_group_index, int comm_source,
|
|
int group_size, int *group_array, int *pow_distance)
|
|
{
|
|
int group_index;
|
|
int i;
|
|
*pow_distance = 0;
|
|
|
|
for (i = 1; i < group_size; i<<=1, (*pow_distance)++) {
|
|
group_index = my_group_index ^ i;
|
|
if (comm_source == group_array[group_index]) {
|
|
return group_index;
|
|
}
|
|
}
|
|
|
|
*pow_distance = -1;
|
|
return -1;
|
|
}
|
|
|
|
int get_group_index_and_distance_for_k_nomial(int my_group_index, int comm_source, int radix,
|
|
int group_size, int *group_array, int *pow_distance)
|
|
{
|
|
int group_index;
|
|
int offset = 1; /* offset equal to 1 (radix_power) */
|
|
int radix_power = 1; /* radix power 0 */
|
|
*pow_distance = 0;
|
|
|
|
/*
|
|
* Go trough range of possible offsets from my rank,
|
|
* for each offset we calculate k-nomial tree root.
|
|
*/
|
|
while(offset < group_size) {
|
|
/* K-nomial tree root calculation for the offset */
|
|
if (offset % (radix * radix_power)) {
|
|
group_index = my_group_index - offset;
|
|
/* wrap around if the group is negative */
|
|
if (group_index < 0) {
|
|
group_index += group_size;
|
|
}
|
|
PTPCOLL_VERBOSE(10, ("Checking %d", group_index));
|
|
if (comm_source == group_array[group_index]) {
|
|
return group_index;
|
|
}
|
|
offset += radix_power;
|
|
} else {
|
|
/* we done with the section of the tree, go to next one */
|
|
radix_power *= radix;
|
|
(*pow_distance)++;
|
|
}
|
|
}
|
|
|
|
/* No source was found, return -1 */
|
|
*pow_distance = -1;
|
|
return -1;
|
|
}
|
|
|
|
int get_group_index_for_k_nomial(int my_group_index, int comm_source, int radix, int group_size, int *group_array)
|
|
{
|
|
int group_index;
|
|
int radix_power = 1; /* radix power 0 */
|
|
int offset = 1; /* offset equal to 1 (radix_power) */
|
|
|
|
/*
|
|
* Go trough range of possible offsets from my rank,
|
|
* for each offset we calculate k-nomial tree root.
|
|
*/
|
|
while(offset < group_size) {
|
|
/* K-nomial tree root calculation for the offset */
|
|
if (offset % (radix * radix_power)) {
|
|
group_index = my_group_index - offset;
|
|
/* wrap around if the group is negative */
|
|
if (group_index < 0) {
|
|
group_index += group_size;
|
|
}
|
|
if (comm_source == group_array[group_index]) {
|
|
return group_index;
|
|
}
|
|
offset += radix_power;
|
|
} else {
|
|
/* we done with the section of the tree, go to next one */
|
|
radix_power *= radix;
|
|
}
|
|
}
|
|
|
|
/* No source was found, return -1 */
|
|
return -1;
|
|
}
|