MPIIO write integer based on C++ - c++

I want to write the integer b in the output file. I try to provide the address of a, but it only outputs the first several chars, there is not number after the chars.
Here is my code:
#include <cmath>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
int main(int argc, char *argv[])
{
int rank;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPIO_Request request;
MPI_Status status;
MPI_Offset offset = 0;
MPI_File fh;
std::string str1 = "output";
const char *na = str1.c_str();
std::string str2 = "#!TDV112";
const char *version = str2.c_str();
MPI_File_open(MPI_COMM_WORLD, na, MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
if (rank == 0)
{
MPI_File_seek(fh, offset, MPI_SEEK_SET);
// header !version number
MPI_File_write(fh, version, 8, MPI_CHAR, &status);
// INTEGER 1
int a = 1;
MPI_File_write(fh, &a, 1, MPI_INT, &status);
}
return 0;
}

Related

MPI_SEND - send structure as vector

Considering this structure:
struct Book {
int id;
string title;
};
And this vector:
vector<Book> books;
How can I use MPI_Send in order to send the elements of vector books?
I have tried to find a way to do this the entire day, but no results.
Method 1
One way to do this is to set the title to a constant length. You can then build an MPI data type around your struct, like so:
#include "mpi.h"
#include <iostream>
#include <string>
#include <vector>
const int MAX_TITLE_LENGTH = 256;
struct Book {
int id;
char title[MAX_TITLE_LENGTH];
};
int main(int argc, char *argv[]){
MPI_Init(&argc, &argv);
std::vector<Book> books(343);
MPI_Datatype BookType;
MPI_Datatype type[2] = { MPI_INTEGER, MPI_CHAR };
int blocklen[2] = { 1, MAX_TITLE_LENGTH };
MPI_Aint disp[2];
disp[0] = 0;
disp[1] = sizeof(int);
MPI_Type_create_struct(2, blocklen, disp, type, &BookType);
MPI_Type_commit(&BookType);
int myrank;
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if (myrank == 0) {
books[3].id = 4;
MPI_Send(books.data(), 343, BookType, 1, 123, MPI_COMM_WORLD);
} else if (myrank == 1) {
MPI_Status status;
MPI_Recv(books.data(), 343, BookType, 0, 123, MPI_COMM_WORLD, &status);
std::cout<<books[3].id<<std::endl;
}
MPI_Finalize();
return 0;
}
Method 2
MPI is best used for quickly exchange numbers across grids of known size. But it can also work as a handy communication layer. To do so, we can use the Cereal library to serialize arbitrary C++ objects and then send the serialized representations using MPI, as follows. This is slower than using MPI as designed because there are more intermediate copies, but provides the flexibility of using the full flexibility of C++.
#include "mpi.h"
#include <cereal/types/vector.hpp>
#include <cereal/types/string.hpp>
#include <cereal/archives/binary.hpp>
#include <sstream>
#include <string>
struct Book {
int id;
std::string title;
template <class Archive>
void serialize( Archive & ar ) { ar(id,title); }
};
template<class T>
int MPI_Send(const T &data, int dest, int tag, MPI_Comm comm){
std::stringstream ss;
{ //Needed for RAII in Cereal
cereal::BinaryOutputArchive archive( ss );
archive( data );
}
const auto serialized = ss.str();
return MPI_Send(serialized.data(), serialized.size(), MPI_CHAR, dest, tag, MPI_COMM_WORLD);
}
template<class T>
int MPI_Recv(T &data, int source, int tag, MPI_Comm comm, MPI_Status *status){
//Get number of bytes in incoming message
MPI_Probe(source, tag, MPI_COMM_WORLD, status);
int num_incoming;
MPI_Get_count(status, MPI_CHAR, &num_incoming);
//Allocate a buffer of appropriate size
std::vector<char> incoming(num_incoming);
//Receive the data
auto ret = MPI_Recv(incoming.data(), num_incoming, MPI_CHAR, source, tag, MPI_COMM_WORLD, status);
std::stringstream ss;
ss.write(incoming.data(), num_incoming);
//Unpack the data
{
cereal::BinaryInputArchive archive(ss);
archive(data);
}
return ret;
}
int main(int argc, char **argv){
MPI_Init(&argc, &argv);
std::vector<Book> books(343);
int myrank;
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if (myrank == 0) {
books[3].id = 4;
books[3].title = "Hello, world!";
MPI_Send(books, 1, 123, MPI_COMM_WORLD);
} else if (myrank == 1){
MPI_Status status;
MPI_Recv(books, 0, 123, MPI_COMM_WORLD, &status);
std::cout<<books[3].id<<" "<<books[3].title<<std::endl;
}
MPI_Finalize();
return 0;
}
With title being a char[N] array of fixed size N, you could've created a new datatype and use it in MPI_Send. Unfortunately, this approach won't work with std::string as a data member. But you can send std::vector<Book> element-by-element.
For example:
std::vector<Book> books;
// ...
const unsigned long long size = books.size();
MPI_Send(&size, 1, MPI_UNSIGNED_LONG_LONG, ...);
for (const auto& book : books) {
MPI_Send(&book.id, 1, MPI_INT, ...);
const unsigned long long len = book.title.length();
MPI_Send(&len, 1, MPI_UNSIGNED_LONG_LONG, ...);
MPI_Send(book.title.data(), len, MPI_CHAR, ...);
}
and
std::vector<Book> books;
unsigned long long size;
MPI_Recv(&size, 1, MPI_UNSIGNED_LONG_LONG, ...);
books.resize(size);
for (auto& book : books) {
MPI_Recv(&book.id, 1, MPI_INT, ...);
unsigned long long len;
MPI_Recv(&len, 1, MPI_UNSIGNED_LONG_LONG, ...);
std::vector<char> str(len);
MPI_Recv(str.data(), len, MPI_CHAR, ...);
book.title.assign(str.begin(), str.end());
}
// ...

Trim an audio file that is labelled with a timestamp c++

So i have a program that records snippets of audio on a microphone array, it then timestamps the end time of the file. My problem is that the process of the program starting the recording takes a random amount of time to start and so the audio is a random length. I want a way to read the size of the file (kilobytes) then trim the file by a certain number of kilobytes so that the recordings are always the same length.
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <chrono>
#include <thread>
#include<signal.h>
#include<unistd.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include "zlib.h"
long long int rem;
long long int ms1;
long long int unixtime;
using namespace std;
const char* Filenames;
int main(void) {
int system(const char *command);
int x;
struct timeval tp1;
rem = 5;
while (rem != 0) {
gettimeofday(&tp1, NULL);
ms1 = tp1.tv_sec * 1000ll + tp1.tv_usec / 1000ll;
rem = ms1 % 10000;
}
for (x=0; x<3; x++){
pid_t pid=fork();
if (pid==0){
execl("/home/pi/odas/bin/odaslive", "/home/pi/odas/bin/odaslive", "-vc", "/home/pi/odas/config/odaslive/matrix_creator.cfg", (char *)NULL);
exit(127);
} else {
std::this_thread::sleep_for(std::chrono::milliseconds(15000));
kill(pid, SIGINT);
}
gettimeofday(&tp1, NULL);
unixtime = tp1.tv_sec + tp1.tv_usec / 1000000ll;
std::string name1 = "/home/pi/matrix_creator_explore/postfiltered/postfiltered1_";
std::string name2 = ".raw";
std::string result1;
result1 = name1 + std::to_string(unixtime) + name2;
const char *cstr = result1.c_str();
rename ("/home/pi/matrix_creator_explore/postfiltered.raw", cstr);
std::string name3 = "/home/pi/matrix_creator_explore/tracked/tracked1_";
std::string name4 = ".raw";
std::string result2;
result2 = name3 + std::to_string(unixtime) + name4;
const char *cstr1 = result2.c_str();
rename ("/home/pi/matrix_creator_explore/tracked.raw", cstr1);
struct stat buf;
stat( cstr,&buf);
printf ("\n %i \n", buf.st_size);
}
}

MPI causes breakpoint

I've made an application that counts number of characters using MS MPI, but it causes 4 breakpoints at:
MPI_File_get_size, MPI_File_set_view, MPI_File_read and again at MPI_File_get_size(fh, &size).
Do you know what may cause them? Full code below:
#include "stdafx.h"
#include "mpi.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stack>
using namespace std;
int main(int argc, char *argv[])
{
int numprocs, rank, buffer[100];
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Status status;
MPI_File fh;
MPI_Offset size;
int char_number;
const char plik[10] = "file.txt";
MPI_File_open(MPI_COMM_WORLD, plik, MPI_MODE_RDONLY, MPI_INFO_NULL, &fh);
MPI_File_get_size(fh, &size);
MPI_File_set_view(fh, rank*(size / numprocs), MPI_CHAR, MPI_CHAR, "native", MPI_INFO_NULL);
MPI_File_read(fh, &buffer[100], 1, MPI_CHAR, &status);
char_number = MPI_File_get_size(fh, &size);
MPI_File_close(&fh);
if (rank == 0) {
for (int i = 0; i < numprocs; i++) {
MPI_Recv(&char_number, i, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
}
}
else {
MPI_Send(&char_number, 0, MPI_INT, 0, 3, MPI_COMM_WORLD);
}
MPI_Finalize();
return 0;
}
EDIT: Got rid of breakpoints, but not receiving any output now:
#include "stdafx.h"
#include "mpi.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stack>
using namespace std;
int main(int argc, char *argv[])
{
int numprocs, rank;
char buffer[100] = { 0 };
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Status status;
MPI_File fh;
MPI_Offset size;
int char_number;
const char plik[10] = "file.txt";
MPI_File_open(MPI_COMM_WORLD, plik, MPI_MODE_RDONLY, MPI_INFO_NULL, &fh);
MPI_File_get_size(fh, &size);
MPI_File_set_view(fh, rank*(size / numprocs), MPI_CHAR, MPI_CHAR, "native", MPI_INFO_NULL);
MPI_File_read(fh, buffer, (size/numprocs), MPI_CHAR, &status);
char_number = MPI_File_get_size(fh, &size);
MPI_File_close(&fh);
if (rank == 0) {
for (int i = 0; i < numprocs; i++) {
MPI_Recv(&char_number, i, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
}
cout << "There is: " << char_number << " characters in file.txt";
}
else {
MPI_Send(&char_number, 0, MPI_INT, 0, 3, MPI_COMM_WORLD);
}
MPI_Finalize();
return 0;
}
It might be your breakpoints are still on the list:
I deleted a breakpoint, but I continue to hit it when I start
debugging again
If you deleted a breakpoint while debugging, in some
cases you may hit the breakpoint again the next time you start
debugging. To stop hitting this breakpoint, make sure all the
instances of the breakpoint are removed from the Breakpoints window.
Source: https://msdn.microsoft.com/en-us/library/5557y8b4.aspx
I remember similar situation in the past with some executables. Removing breakpoint from the source code was not enough.
It also might be that you are trying to access non-existing file.
It also might be that your code is not quite OK.
#include "mpi.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stack>
using namespace std;
int main(int argc, char *argv[])
{
int numprocs, rank;
// buffer will keep input data
char buffer[100] = { 0 };
// initialization of MPI world
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Status status;
MPI_File fh;
MPI_Offset size;
int char_number;
// name of the file with data
const char plik[10] = "file.txt";
MPI_File_open(MPI_COMM_WORLD, plik, MPI_MODE_RDONLY, MPI_INFO_NULL, &fh);
MPI_File_get_size(fh, &size);
// we have to be careful here
// in this sample we have strong assumption that size of data
// divides without the reminder by number of processors!
MPI_File_set_view(fh, rank*(size / numprocs), MPI_CHAR, MPI_CHAR, "native", MPI_INFO_NULL);
MPI_File_read(fh, buffer, (size/numprocs), MPI_CHAR, &status);
char_number = MPI_File_get_size(fh, &size);
MPI_File_close(&fh);
printf("My rank: %d - my data: %s\n", rank, buffer);
if (rank == 0) {
for (int i = 1; i < numprocs; i++) {
MPI_Recv(&buffer[i*(size / numprocs)], (size/numprocs), MPI_CHAR, i, 0, MPI_COMM_WORLD, &status);
}
printf("I have collected data: %s\n",buffer);
}
else {
MPI_Send(&buffer[0], rank*(size / numprocs), MPI_CHAR, 0, 0, MPI_COMM_WORLD);
}
MPI_Finalize();
return 0;
}
For input file
> cat file.txt
abcdefgh
works as expected:
> mpirun -np 2 ./simple2
My rank: 0 - my data: abcd
I have collected data: abcdefgh
My rank: 1 - my data: efgh
Question is, whether this is what you are looking for.

How to use MPI_Irecv?

From OpenMPI docs: C++ syntax
Request Comm::Irecv(void* buf, int count, const Datatype&
datatype, int source, int tag) const
So I imagine I do something like:
MPI::Request req;
req = MPI_Irecv(&ballChallenges[i], 2, MPI_INT, i, TAG_AT_BALL, MPI_COMM_WORLD);
But it complains:
error: too few arguments to function ‘int MPI_Irecv(void*, int, MPI_Datatype, int, int, MPI_Comm, ompi_request_t**)’
Seems like I am missing ompi_request_t**, but its not documented? Tried
MPI_Irecv(&ballChallenges[i], 2, MPI_INT, i, TAG_AT_BALL, MPI_COMM_WORLD, &req);
But fails with
error: cannot convert ‘MPI::Request*’ to ‘ompi_request_t**’ for argument ‘7’ to ‘int MPI_Irecv(void*, int, MPI_Datatype, int, int, MPI_Comm, ompi_request_t**)’
So whats with the ompi_request_t part?
This works (C):
#include <stdio.h>
#include <string.h>
#include <mpi.h>
int main(int argc, char **argv) {
int rank;
const char *msg="Hello!";
const int len=strlen(msg)+1;
char buf[len];
MPI_Request isreq, irreq;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
MPI_Isend((void*)msg, len, MPI_CHAR, 0, 0, MPI_COMM_WORLD, &isreq);
MPI_Irecv(buf, len, MPI_CHAR, 0, 0, MPI_COMM_WORLD, &irreq);
MPI_Cancel(&irreq);
MPI_Cancel(&isreq);
}
MPI_Finalize();
return 0;
}
Or this works (C++)
#include <cstring>
#include <mpi.h>
using namespace MPI;
int main(int argc, char **argv) {
const char *msg="Hello!";
const int len=strlen(msg)+1;
char *buf = new char[len];
Init(argc, argv);
int rank = COMM_WORLD.Get_rank();
if (rank == 0) {
Request isreq = COMM_WORLD.Isend(msg, len, MPI_CHAR, 0, 0);
Request irreq = COMM_WORLD.Irecv(buf, len, MPI_CHAR, 0, 0);
isreq.Cancel();
irreq.Cancel();
}
Finalize();
return 0;
}

In memory Binary Search Vs. Disk based Binary Search

In this program, I am reading "key.pc.db" file and printing its mid value.
#include <fstream>
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
using namespace std;
int main( int argc, char *argv[] )
{
ifstream fp;
int mval;
int sizek;
struct stat filek;
int min, max, mid;
if(stat("key.pc.db", &filek) ==0 )
sizek=filek.st_size;
sizek=sizek/sizeof(int);
min=0;
max=sizek-1;
mid=(min+max)/2;
printf("mid %d ",mid);
fp.open( "key.pc.db", ios::in | ios::binary );
fp.seekg(mid, ios::beg);
fp.read( (char *) &mval, (int) sizeof( int ) );
printf("%d mval ", mval);
getch();
return 1;
}
In this program also I am reading the same file but I am storing the value of the file in an array and then printing the mid value. The mid index for both the program shows the same but the value comes out to be different. Why so?
#include <fstream>
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
using namespace std;
int main( int argc, char *argv[] )
{
ifstream fp;
int index;
int sizek;
int kval;
struct stat filek;
int min, max, mid;
int i=0;
if(stat("key.pc.db", &filek) ==0 )
sizek=filek.st_size;
sizek=sizek/sizeof(int);
int k[sizek];
fp.open( "key.pc.db", ios::in | ios::binary );
fp.read( (char *) &kval, (int) sizeof( int ) );
while( !fp.eof() )
{
k[i++]=kval;
fp.read( (char *) &kval, (int) sizeof( int ) );
}
min=0;
max=sizek-1;
mid=(min+max)/2;
printf(" index %d ", mid);
printf(" kmid %d ", k[mid]);
getch();
return 1;
}
You're seeking to the wrong point in the file in the first case. You should be seeking to mid*sizeof(int) rather than mid.