Reputation: 964
I am trying to find the global min and max values across all processors for a sort I am working on. I am trying to use MPI_Reduceall
int rank, nproc;
MPI_Comm_size(MPI_COMM_WORLD,&nproc);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
vector< vector<double> > buckets(nproc);
double local_min = *std::min_element(values_to_sort.begin(), values_to_sort.end());
double local_max = *std::max_element(values_to_sort.begin(), values_to_sort.end());
int min = 0;
int max = 0;
double global_min;
double global_max;
MPI_Allreduce(&local_min, &global_min, 1, MPI_2DOUBLE_PRECISION, MPI_MINLOC, MPI_COMM_WORLD);
MPI_Allreduce(&local_max, &global_max, 1, MPI_2DOUBLE_PRECISION, MPI_MAXLOC, MPI_COMM_WORLD);
cout << "local_min " << local_min << " local_max " << local_max << endl;
cout << "global_min " << global_min << " global_max " << global_max << endl;
My code is shown, and segfaults every time. This is in a simple function and is called with random doubles generated using:
int min = 0;
int max = 100;
vector<double> values_to_sort;
vector<double> sorted_values;
for(int i=0; i< 1000; i++)
{
values_to_sort.push_back( ((double) rand()*(max-min)/(double)RAND_MAX-min) );
}
If anyone knows why this seg faults, please let me know. I would really like to get the global max and min in a quick easy way.
Upvotes: 0
Views: 506
Reputation: 9519
Do you really need to use MPI_MINLOC
and MPI_MAXLOC
here? Because the way you stated your problem and the way you use the solution, MPI_MIN
and MPI_MAX
would do just fine:
double local_min = *std::min_element(values_to_sort.begin(), values_to_sort.end());
double local_max = *std::max_element(values_to_sort.begin(), values_to_sort.end());
double global_min;
double global_max;
MPI_Allreduce(&local_min, &global_min, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
MPI_Allreduce(&local_max, &global_max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
cout << "local_min " << local_min << " local_max " << local_max << endl;
cout << "global_min " << global_min << " global_max " << global_max << endl;
Now, if you really need the rank of the process owning the global min and global max, then you indeed need MPI_MINLOC
and MPI_MAXLOC
. However, you are supposed to use it like this:
struct double_int {
double val;
int rank;
} local_min, local_max, global_min, global_max;
local_min.val = *std::min_element(values_to_sort.begin(), values_to_sort.end());
local_max.val = *std::max_element(values_to_sort.begin(), values_to_sort.end());
local_min.rank = local_max.rank = rank;
MPI_Allreduce(&local_min, &global_min, 1, MPI_DOUBLE_INT, MPI_MINLOC, MPI_COMM_WORLD);
MPI_Allreduce(&local_max, &global_max, 1, MPI_DOUBLE_INT, MPI_MAXLOC, MPI_COMM_WORLD);
cout << "on process " << rank << " local_min " << local_min.val
<< " local_max " << local_max.val << endl;
cout << "global_min " << global_min.val << " owned by process " << global_min.rank << endl;
cout << "global_max " << global_max.val << " owned by process " << global_max.rank << endl;
Upvotes: 2
Reputation: 964
I did some reading and the MINLOC and MAXLOC operations requires that you use an array of some size > 1 to store the value and rank as a pair.
My updated code
int rank, nproc;
MPI_Comm_size(MPI_COMM_WORLD,&nproc);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
vector< vector<double> > buckets(nproc);
double local_min[2];
local_min[1] = rank;
local_min[0] = *std::min_element(values_to_sort.begin(), values_to_sort.end());
double local_max[2];
local_max[1] = rank;
local_max[0] = *std::max_element(values_to_sort.begin(), values_to_sort.end());
double global_min[2];
double global_max[2];
MPI_Allreduce(&local_min, &global_min, 1, MPI_2DOUBLE_PRECISION, MPI_MINLOC, MPI_COMM_WORLD);
MPI_Allreduce(&local_max, &global_max, 1, MPI_2DOUBLE_PRECISION, MPI_MAXLOC, MPI_COMM_WORLD);
cout << "local_min " << local_min[0] << " local_max " << local_max[0] << endl;
cout << "global_min " << global_min[0] << " global_max " << global_max[0] << endl;
Upvotes: 0