C++: Using MPI's gatherv to concatenate vectors of differing lengths - c++

so I'm trying to copy over vectors of different lengths between MPI processes in C++, namely taking vectors on all of the nodes and concatenating them into a new vector on node 0.
I have the following code, which does not return what I expected, driving me crazy, and causing trouble further down the line.
The code is this (abbreviated):
//previously summed all of numfrags to make _numFrag
//numfrags is a vector of the local sizes of _fragLoc
//_numFrag is the total of numfrags
MPI::COMM_WORLD.Barrier();
cout << _myid << "local numFrag = " << _fragLoc.size() << endl;
MPI::COMM_WORLD.Barrier();
for (unsigned i = 0; i < _fragLoc.size(); ++i) cout << "fragloc(" << i << ") = " << _fragLoc[i] << endl;
MPI::COMM_WORLD.Barrier();
vector<int> outVector (_numFrag);
int displ[_numprocs];
if (_myid == 0) {
double sum = 0;
for (int i = 0; i < _numprocs; ++i) {
displ[i] = sum;
cout << _myid << " : " << i << " : " << sum << endl;
sum += numfrags[i];
}
}
MPI::COMM_WORLD.Barrier(); MPI::COMM_WORLD.Gatherv(&_fragLoc[0], numfrags[_myid], MPI::INT, &outVector[0], &numfrags[0], &displ[0], MPI::INT,0);
MPI::COMM_WORLD.Barrier();
if (_myid == 0) {
cout << "X numFrag = " << _numFrag << endl;
for (unsigned i = 0; i < _numFrag; ++i) cout << "outVector(" << i << ") = " << outVector[i] << endl;
}
Giving a simple example, I have a four-node run. Here are the variable inputs as pseudocode:
int _numprocs = 4;
vector<int> numfrags = {0,1,0,1};
vector<int> _fragLoc <node 0> = {};
vector<int> _fragLoc <node 1> = {12};
vector<int> _fragLoc <node 2> = {};
vector<int> _fragLoc <node 3> = {37};
int _numFrag = 2;
The output is:
2local numFrag = 0
3local numFrag = 1
0local numFrag = 0
1local numFrag = 1
fragloc(0) = 12
fragloc(0) = 37
0 : 0 : 0
0 : 1 : 0
0 : 2 : 1
0 : 3 : 1
0: after stage 2
X numFrag = 2
outVector(0) = 0
outVector(1) = 0
But I expected the individual fragLoc's to be put together into outVector and this isn't happening. Any advice? I'll clean up the barriers when I'm done debugging.

As far as I can tell, the code above works as expected.
#include <iostream>
#include <mpi.h>
#include <vector>
using namespace std;
int main(int argc, char **argv) {
MPI::Init(argc, argv);
int _myid = MPI::COMM_WORLD.Get_rank();
int _numprocs = MPI::COMM_WORLD.Get_size();
vector<int> _fragLoc;
switch(_myid) {
case 0: break;
case 1: _fragLoc.push_back(12); break;
case 2: break;
case 3: _fragLoc.push_back(37); break;
}
int locNumFrag = _fragLoc.size();
cout << _myid << "local numFrag = " << locNumFrag << endl;
MPI::COMM_WORLD.Barrier(); // for printing
vector<int> numfrags(_numprocs);
MPI::COMM_WORLD.Allgather(&locNumFrag, 1, MPI::INT, &numfrags[0], 1, MPI::INT);
int _numFrag = 0;
for (int i=0; i<_numprocs; i++)
_numFrag += numfrags[i];
for (unsigned i = 0; i < _fragLoc.size(); ++i)
cout << "fragloc(" << i << ") = " << _fragLoc[i] << endl;
MPI::COMM_WORLD.Barrier(); // for printing
vector<int> outVector (_numFrag);
int displ[_numprocs];
if (_myid == 0) {
double sum = 0;
for (int i = 0; i < _numprocs; ++i) {
displ[i] = sum;
cout << _myid << " : " << i << " : " << sum << endl;
sum += numfrags[i];
}
}
MPI::COMM_WORLD.Gatherv(&_fragLoc[0], numfrags[_myid], MPI::INT, &outVector[0], &numfrags[0], &displ[0], MPI::INT,0);
if (_myid == 0) {
cout << "X numFrag = " << _numFrag << endl;
for (unsigned i = 0; i < _numFrag; ++i) cout << "outVector(" << i << ") = " << outVector[i] << endl;
}
MPI::Finalize();
return 0;
}
Running gives
$ mpirun -np 4 ./gatherv
0local numFrag = 0
1local numFrag = 1
fragloc(0) = 12
2local numFrag = 0
3local numFrag = 1
fragloc(0) = 37
0 : 0 : 0
0 : 1 : 0
0 : 2 : 1
0 : 3 : 1
X numFrag = 2
outVector(0) = 12
outVector(1) = 37

Related

Why is this ranged based for loop causing issues with subtraction?

I'm having an issue with a ranged based for loop causing my values to go negative, and I've resolved the issue with a regular for loop but want to understand why it messed up in the first place. You can see from the sample output below that the initial values exist correctly, but then when attempting to subtract from them, they get reset to a default initialized value of 0 I guess?
Broken code:
#include <iostream>
#include <vector>
#define IS_TRUE(x) { if (!(x)) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; }
int maximumScore(std::vector<int>& nums, std::vector<int>& multipliers) {
std::vector<int> multRank;
multRank.resize(multipliers.size());
std::cout << "multRank: ";
//ISSUE IS IN THE LOOP BELOW
for (int n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}
std::cout << std::endl;
for (auto i = 0; i < multipliers.size(); ++i) {
for (auto j = 0; j < multipliers.size(); ++j) {
int abs1 = std::abs(multipliers[i]);
int abs2 = std::abs(multipliers[j]);
if (abs1 > abs2) {
multRank[i] = multRank[i] - 1;
std::cout << multRank[i];
}
}
}
std::cout << std::endl << "multRank after: ";
for (int n : multRank) {
std::cout << " " << n;
}
std::cout << std::endl << std::endl;
return 0;
}
void test1()
{
std::vector<int> nums = { 1, 2, 3 };
std::vector<int> multipliers = { 3, 2, 1 };
int test = maximumScore(nums, multipliers);
IS_TRUE(test == 14);
}
int main()
{
std::cout << "Maximum Score from Performing Multiplication Operations\n";
test1();
}
Broken code output:
Maximum Score from Performing Multiplication Operations
multRank: 3 3 3
-1-2-1
multRank after: -2 -1 0
Repaired code:
#include <iostream>
#include <vector>
#define IS_TRUE(x) { if (!(x)) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; }
int maximumScore(std::vector<int>& nums, std::vector<int>& multipliers) {
std::vector<int> multRank;
multRank.resize(multipliers.size());
std::cout << "multRank: ";
//ISSUE WAS IN THE LOOP BELOW
for (auto i = 0; i < multipliers.size(); ++i) {
multRank[i] = multipliers.size();
std::cout << " " << multRank[i];
}
std::cout << std::endl;
for (auto i = 0; i < multipliers.size(); ++i) {
for (auto j = 0; j < multipliers.size(); ++j) {
int abs1 = std::abs(multipliers[i]);
int abs2 = std::abs(multipliers[j]);
if (abs1 > abs2) {
multRank[i]--;
std::cout << multRank[i];
}
}
}
std::cout << std::endl << "multRank after: ";
for (int n : multRank) {
std::cout << " " << n;
}
std::cout << std::endl << std::endl;
return 0;
}
void test1()
{
std::vector<int> nums = { 1, 2, 3 };
std::vector<int> multipliers = { 3, 2, 1 };
int test = maximumScore(nums, multipliers);
IS_TRUE(test == 14);
}
int main()
{
std::cout << "Calculate Rank\n";
test1();
}
Repaired code output:
Maximum Score from Performing Multiplication Operations
multRank: 3 3 3
212
multRank after: 1 2 3
The first range based for loop is not using references:
for (int n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}
In this loop, n is a copy of the data in multRank. If you want to be able to modify the data in multRank, you want n to be a reference:
for (int& n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}

terminate called after throwing an instance of 'std::out_of_range' in C++

I am new to C++ and learning data structures. In the below code I am getting an "out of range warning", and do not understand what I am doing wrong.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> numbers{100,-1,2,4,55,78,3};
int temp {};
int pass {};
pass = numbers.size();
for(int i {0} ;i<pass-1;i++){
for(int j {0} ; j<pass-1-i ; j++){
if(numbers.at(j) > numbers.at(j+1)){
temp = numbers.at(j);
numbers.at(j)=numbers.at(j+1);
numbers.at(j+1)=temp;
}
}
}
cout << numbers.at(0) << endl;
cout << numbers.at(1) << endl;
cout << numbers.at(2) << endl;
cout << numbers.at(3) << endl;
cout << numbers.at(4) << endl;
cout << numbers.at(5) << endl;
cout << numbers.at(6) << endl;
cout << numbers.at(7) << endl;
cout << numbers.at(8) << endl;
return 0;
}
It seems like you may not understand how std::vectors work.
You have only declared 7 elements in your vector which means you can only go up to the index 6. This is because std::vector's indices start at 0. This is true for std::array as well.
vector<int> numbers{100,-1,2,4,55,78,3};
However, in your code you have put these two statements:
cout << numbers.at(7) << endl;
cout << numbers.at(8) << endl;
which doesn't work because like I mentioned you can only go up to index 6.
You should also consider using a for loop like the comments mention above. It is more simple to use and is less work.
For example eith a for loop:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> numbers{ 100,-1,2,4,55,78,3 };
int temp{};
int pass{};
pass = numbers.size();
for (int i{ 0 }; i < pass - 1; i++) {
for (int j{ 0 }; j < pass - 1 - i; j++) {
if (numbers.at(j) > numbers.at(j + 1)) {
temp = numbers.at(j);
numbers.at(j) = numbers.at(j + 1);
numbers.at(j + 1) = temp;
}
}
}
std::cout << "v = { ";
for (int i = 0; i < numbers.size(); i++) {
std::cout << numbers.at(i) << ", ";
}
std::cout << "}; \n";
return 0;
}
Output:
v = { -1, 2, 3, 4, 55, 78, 100, };

Parsing HHMMSS come from NMEA

I have a trouble with NMEA data(gpzda). The problem is explained below.
NMEA Data : $GPZDA,011856.00,17,03,2018,,*61
My Parsing Code.
char hour[2] = { 0 };
for (int i=0; i < 2; i++) hour[i] = utctime[i];
info.tm_hour = atoi(hour);
char min[2] = { 0 };
for (int i=0; i < 2; i++) min[i] = utctime[i + 2];
info.tm_min = atoi(min);
char sec[2] = { 0 };
for (int i=0; i < 2; i++) sec[i] = utctime[i + 4];
info.tm_sec = atoi(sec);
cout << info.tm_year << " | " << info.tm_mon << " | " << info.tm_mday << " | " << info.tm_hour << " | " << info.tm_min << " | " << info.tm_sec << endl;
The code is well working, but some time the hour value is strange like a "126". I thought that "6" is add from another memory. How to parse this data to well work?
You should zero terminate your strings, so declare each one to be of size 3.
char hour[3] = { 0 };
and so on

segmentation fault for string function argument

I have a simple main code that gives me segmentation fault when calling a function. In the following code, I have two functions, the first one works correctly but the program doesn't enter the second one and gives me segmentation fault error. Is there any reason for that? I have made sure about the following:
The variables o and c are not out of bound.
cn is initialized correctly.
I have a read-only access to cm and argv. Plus it does not even enter the function evaluate
Here is the code:
void print_cm(vector<vector<int> > *cm, char* gtf);
void evaluate(vector<vector<int> > *cm, char* gtf);
int main(int argc, char** argv)
{
int o = 2; // It is initialized
int c = 4; // It is initialized
vector<vector<int> > cm; // It is initialized
if (argc>4)
print_cm(&cm, argv[o]);
if (argc>4)
{
cout << argv[c] << endl; // Works
// The following also works
for (int i=0; i<cm.size(); i++)
for (int j=0; j<cm[i].size(); j++)
cout << cm[i][j] << " ";
// The following causes segmentation fault;
evaluate(&cm, argv[c]);
}
return 0;
}
void evaluate(vector<vector<int> > *cm, char* gtf)
{
// Read-only access to cm and gtf
}
void print_cm(vector<vector<int> > *cm, char* gtf)
{
// Read-only access to cm and gtf
}
Here is the complete code:
#include "includes/Utility.h"
#include "includes/Graph.h"
void print_cm(vector<vector<int> > *cores, char* output);
void evaluate(vector<vector<int> > const *cm, char* gtf);
int main(int argc, char** argv)
{
int g = -1, c = -1, o = -1;
for (int i=1; i<argc-1; i++)
if (argv[i][0]=='-')
{
if (argv[i][1]=='g')
g = i + 1;
else if (argv[i][1]=='c')
c = i + 1;
else if (argv[i][1]=='k')
ki = i + 1;
else if (argv[i][1]=='s')
si = i + 1;
else if (argv[i][1]=='o')
o = i + 1;
}
Graph G;
if (c>0) G.read_input(argv[g], argv[c]);
else G.read_input(argv[g]);
if (ki > 0)
{
int k = atoi(argv[ki]);
cout << k << endl;
}
if (si > 0)
{
int s = atoi(argv[si]);
cout << s << endl;
}
// Find communities
vector<vector<int> > cores;
G.partitioning(&cores);
if (o>0)
print_cm(&cores, argv[o]);
if (c>0)
{
cout << "here" << endl;
for (size_t i=0; i<cores.size(); i++)
for (size_t j=0; j<cores[i].size(); j++)
if (cores.at(i).at(j)<0) cout << "here";
cout << "here" << endl;
evaluate(&cores, argv[c]);
}
}
return 0;
}
void print_cm(vector<vector<int> > *cores, char* output)
{
ofstream out;
out.open(output);
for(size_t i=0; i<(*cores).size(); i++)
{
for(size_t j=0; j<(*cores)[i].size(); j++)
out << (*cores)[i][j] << " ";
out << endl;
}
out.close();
return ;
}
void evaluate(vector<vector<int> > const *cm, char* gtf)
{
// we evaluate precision, recall, F1 and F2
vector<vector<int> > gt;
ifstream in;
char str[100000000];
in.open(gtf);
while(in.getline(str, 100000000))
{
stringstream s;
s << str;
int a;
gt.resize(gt.size()+1);
while (s >> a) gt[gt.size()-1].push_back(a);
}
in.close();
cout << "==================== Evaluation Results ====================" << endl;
int imax = 0;
for(size_t i=0; i<(*cm).size(); i++)
imax = max(imax, *max_element((*cm)[i].begin(), (*cm)[i].end()));
for(size_t i=0; i<gt.size(); i++)
imax = max(imax, *max_element(gt[i].begin(), gt[i].end()));
vector<bool> flag(imax, false);
vector<double> recall((*cm).size(), 0), precision((*cm).size(), 0), f1((*cm).size(), 0), f2((*cm).size(), 0);
int overlap;
double size = 0;
for(size_t i=0; i<(*cm).size(); i++)
{
// evaluate
size += (double) (*cm)[i].size();
for(size_t j=0; j<(*cm)[i].size(); j++)
flag[(*cm)[i][j]] = true;
double p, r, ff1, ff2;
for(size_t j=0; j<gt.size(); j++)
{
overlap = 0;
for(size_t k=0; k<gt[j].size(); k++)
if (flag[gt[j][k]]) overlap++;
p = (double) overlap / (double) (*cm)[i].size();
if (p > precision[i])
precision[i] = p;
r = (double) overlap / (double) gt[j].size();
if (r > recall[i])
recall[i] = r;
ff1 = (double) 2*(p*r)/(p+r);
if (ff1 > f1[i])
f1[i] = ff1;
ff2 = (double) 5*(p*r)/(4*p + r);
if (ff2 > f2[i])
f2[i] = ff2;
}
for(size_t j=0; j<(*cm)[i].size(); j++)
flag[(*cm)[i][j]] = false;
}
double Recall = 0, Precision = 0, F1 = 0, F2 = 0;
for(size_t i=0; i<(*cm).size(); i++)
{
Recall += recall[i];
Precision += precision[i];
F1 += f1[i];
F2 += f2[i];
}
cout << "+--------------+--------------+--------------+--------------+" << endl;
cout << "| " << setiosflags( ios::left ) << setw(10) << "Precision";
cout << " | " << setiosflags( ios::left ) << setw(10) << "Recall";
cout << " | " << setiosflags( ios::left ) << setw(10) << "F1-measure";
cout << " | " << setiosflags( ios::left ) << setw(10) << "F2-measure";
cout << " |" << endl;
cout << "| " << setiosflags( ios::left ) << setw(10) << Precision/(*cm).size() ;
cout << " | " << setiosflags( ios::left ) << setw(10) << Recall/(*cm).size();
cout << " | " << setiosflags( ios::left ) << setw(10) << F1/(*cm).size();
cout << " | " << setiosflags( ios::left ) << setw(10) << F2/(*cm).size();
cout << " |" << endl;
cout << "+--------------+--------------+--------------+--------------+" << endl;
cout << "Number of communities: " << (*cm).size() << endl;
cout << "Average community size: " << size/(*cm).size() << endl;
return ;
}
char str[100000000];
This is in your evaluate function. This are 100 million bytes, or about 95 MB that you're allocating on the stack.
Typical stack sizes are far less than that, around 1 MB.
So apart from possible other problems this is most likely causing a stack overflow.
When entering the function, the stack frame gets extended to be large enough to hold the local variables. As soon as the stack is used then (to write a default value) you're accessing invalid (non stack, thankfully protected) memory.

C++ char vector addition

This is a part of a program that I am writing to compute the addition of two integers as strings. (Writing my own bigInt class).
There appears to be a problem when I am adding the two integers together. Because they are both in vectors of char type, I had to add a '0' to each element of the vector before concatenating it into a string.
However, the results are still not what I am expecting:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string const Number = "1000";
string const Number2 = "1000";
vector<char> reverse;
vector<char> reverse2;
//cout << (rostrNumber[1] - '0') << endl;
cout << "Original Number: " << Number << endl;
reverse.clear();
for (int i = Number.size() - 1; i >= 0; i--)
{
reverse.push_back(Number[i]);
}
cout << "Reversed: " << endl;
cout << reverse[0] << reverse[1] << reverse[2] << reverse[3] << endl;
cout << endl << endl;
reverse2.clear();
{
for (int i = Number2.size() - 1; i >= 0; i--)
{
reverse2.push_back(Number[i]);
}
}
cout << "Adding these two integers" << endl;
vector<char> const rcvN1 = reverse;
vector<char> const rcvN2 = reverse2;
vector<char> Results;
Results.clear();
//Local copies
vector<char> vN1 = rcvN1;
vector<char> vN2 = rcvN2;
int iSize1 = vN1.size();
int iSize2 = vN2.size();
int i, iSize = iSize2;
int iC = 0, iR;
for (i = 0; i<iSize; i++)
{
iR = vN1[i] + vN2[i] + iC;
if (iR > 9)
{
iR -= 10;
iC = 1;
}
else
iC = 0;
Results.push_back(iR);
cout << Results[0] << endl;
}
if (iC > 0)
Results.push_back(iC);
string ostr;
vector<char>::const_reverse_iterator rIter = Results.rbegin();
for (; rIter != Results.rend(); rIter++)
ostr += *rIter +'0';
cout << "Results: " << ostr << endl;
system("PAUSE");
return 0;
}