mpi_gather structure - mpi

I am trying to do sort key-value pairs with qsort. Every proc reads in files with filenames as the proc ids. MPI_Gather sends all the read values to proc 0, which sorts the keys and stores the key-val pairs in a file called "Output". The gather however, does not seem to work. Any help is appreciated. Thanks!
I run the code as
mpirun -np 3 ./a.out
and my input files are:
File "0":
21 bbbb
2119 iiii
120 hhhh
File "1":
40 dddd
10 aaaa
100 gggg
File "2":
32 cccc
44 eeee
99 ffff
And the code is:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#define BUFSIZE 3
#define BUFLEN 255
struct keyval{
int key;
char val[BUFLEN];
};
typedef struct keyval keyval_s;
typedef int (*compareptr)(const void*, const void*);
int compare (keyval_s * a, keyval_s * b)
{
return ( a->key - b->key );
}
int main (int argc, char *argv[])
{
int values[BUFSIZE];
keyval_s kv[BUFSIZE], *recv;
int n, i=0, temp;
FILE *in, *out;
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
char filename[20];
char data[20];
if(rank ==0){
recv = (keyval_s *) malloc (size*BUFSIZE*sizeof(keyval_s));
}
sprintf(filename, "%d", rank);
in=fopen(filename,"r");
while(fscanf(in,"%d %s",&kv[i].key, kv[i].val) != EOF){
printf("Read key %d, data %s from file\n", kv[i].key, kv[i].val);
i++;
}
MPI_Gather(kv,BUFSIZE,MPI_BYTE,recv,BUFSIZE,MPI_BYTE,0,MPI_COMM_WORLD);
if(rank==0){
qsort ((void*)&kv, BUFSIZE, sizeof(keyval_s),(compareptr) compare);
out=fopen("Output","w");
for (n=0; n<BUFSIZE*size; n++)
fprintf (out,"%d %s\n",recv[n].key, recv[n].val);
free(recv);
fclose(out);
}
fclose(in);
return 0;
}

The size of the data in MPI_Gather is incorrect. It should be
MPI_Gather(kv,
sizeof(keyval_s)*BUFSIZE,
MPI_BYTE,
recv,
sizeof(keyval_s)*BUFSIZE,
MPI_BYTE,
0,
MPI_COMM_WORLD);
Note that the recvcount parameter in MPI_Gather is for a message from a single rank, not the total size of the gathered data.

Related

MPI Send and receive a pointer in MPI_Type_struct

I want to send a set of data with the MPI_Type_struct and one of them is a pointer to an array (because the matrices that I'm going to use are going to be very large and I need to do malloc). The problem I see is that all the data is passed correctly except the matrix. I know that it is possible to pass a matrix through the pointer since if I only send the pointer of the matrix, correct results are observed.
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
int size, rank;
int m,n;
m=n=2;
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
typedef struct estruct
{
float *array;
int sizeM, sizeK, sizeN, rank_or;
} ;
struct estruct kernel, server;
MPI_Datatype types[5] = {MPI_FLOAT, MPI_INT,MPI_INT,MPI_INT,MPI_INT};
MPI_Datatype newtype;
int lengths[5] = {n*m,1,1,1,1};
MPI_Aint displacements[5];
displacements[0] = (size_t) & (kernel.array[0]) - (size_t)&kernel;
displacements[1] = (size_t) & (kernel.sizeM) - (size_t)&kernel;
displacements[2] = (size_t) & (kernel.sizeK) - (size_t)&kernel;
displacements[3] = (size_t) & (kernel.sizeN) - (size_t)&kernel;
displacements[4] = (size_t) & (kernel.rank_or) - (size_t)&kernel;
MPI_Type_struct(5, lengths, displacements, types, &newtype);
MPI_Type_commit(&newtype);
if (rank == 0)
{
kernel.array = (float *)malloc(m * n * sizeof(float));
for(int i = 0; i < m*n; i++) kernel.array[i] = i;
kernel.sizeM = 5;
kernel.sizeK = 5;
kernel.sizeN = 5;
kernel.rank_or = 5;
MPI_Send(&kernel, 1, newtype, 1, 0, MPI_COMM_WORLD);
}
else
{
server.array = (float *)malloc(m * n * sizeof(float));
MPI_Recv(&server, 1, newtype, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("%i \n", server.sizeM);
printf("%i \n", server.sizeK);
printf("%i \n", server.sizeN);
printf("%i \n", server.rank_or);
for(int i = 0; i < m*n; i++) printf("%f\n",server.array[i]);
}
MPI_Finalize();
}
Assuming that only two processes are executed,I expect that process with rank = 1 receive and display the correct elements of the matrix on the screen (the other elements are well received), but the actual output is:
5
5
5
5
0.065004
0.000000
0.000000
0.000000
===================================================================================
= BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
= PID 26206 RUNNING AT pmul
= EXIT CODE: 11
= CLEANING UP REMAINING PROCESSES
= YOU CAN IGNORE THE BELOW CLEANUP MESSAGES
===================================================================================
YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11)
This typically refers to a problem with your application.
Please see the FAQ page for debugging suggestions
I hope someone can help me.

Read input integer from external file for MPI

How could I read external input file for mpi? I need to read one integer from external file (zadanie4_vstup.txt), to compute simple factorial. I have tried to substitute the second argument in MPI_Init() with address of int variable (n), but it looks it is nonsense.
Thank you.
#include <stdio.h>
#include <mpi.h>
int main(int argc, char ** argv)
{
FILE *fr, *fw;
fr = fopen("zadanie4_vstup.txt", "r");
fw = fopen("zadanie4_vystup.txt", "w");
int nproc, me;
int fakt=1, i, buff, n;
MPI_Status stat;
fscanf(fr, "%d", &n);
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &me);
#pragma omp parallel for private(i) reduction(*:fakt)
for(i=me*n/nproc+1; i<=(me+1)*n/nproc; i++) {
fakt *= i;
}
if(nproc > 1) {
if(me == 0) {
for(i=1; i<nproc; i++) {
MPI_Recv(&buff, 1, MPI_INT, i, 0, MPI_COMM_WORLD, &stat);
fakt*=buff;
}
} else {
MPI_Send(&fakt, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
}
}
if(me == 0) {
fprintf(fw, "%d! = %d\n", n, fakt);
}
fclose(fr);
fclose(fw);
MPI_Finalize();
}
here is a version of your program that reads n on the command line.
note i simplified the communications by using MPI_Reduce()
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char *argv[]) {
int nproc, me;
int fakt=1, res, i, buff, n;
MPI_Status stat;
MPI_Init(&argc, &argv);
n = atoi(argv[1]);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &me);
#pragma omp parallel for private(i) reduction(*:fakt)
for(i=me*n/nproc+1; i<=(me+1)*n/nproc; i++) {
fakt *= i;
}
MPI_Reduce(&fakt, &res, 1, MPI_INT, MPI_PROD, 0, MPI_COMM_WORLD);
if(me == 0) {
printf("%d! = %d\n", n, res);
}
MPI_Finalize();
return 0;
}
for example
$ mpirun -np 4 ./fakt 6
6! = 720

Redirection operators are not working in unix?

I am running a program and it is printing all the printf statements on console.
But when I try to redirect them to any file using '>',the file gets created but there in no output of the program in the file.
Please help
When I run the below code in console:
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
double time_diff(struct timeval x , struct timeval y);
struct timeval initial;
long sno=0;
void *process1 (void *sleepTimeForP1);
void *process2 (void *sleepTimeForP2);
pthread_mutex_t lock;
int main()
{
gettimeofday(&initial , NULL);
pthread_t trd1,trd2;
int thread1,thread2;
int var1;
int var2;
int *sleepTimeForP1;
int *sleepTimeForP2;
var1=rand()%9+1;
sleepTimeForP1=&var1;
var2=rand()%9+1;
sleepTimeForP2=&var2;
printf("S No.\tThread Number\tItem\tTime(usec)\n");
thread1=pthread_create(&trd1,NULL,process1,(void *)sleepTimeForP1);
thread2=pthread_create(&trd2,NULL,process2,(void *)sleepTimeForP2);
pthread_join(trd1, NULL);
pthread_join(trd2, NULL);
printf("pthread1 = %d\n",thread1);
printf("pthread2 = %d\n",thread2);
return 0;
}
double time_diff(struct timeval x , struct timeval y)
{
double x_ms , y_ms , diff;
x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
diff = (double)y_ms - (double)x_ms;
return diff;
}
void *process1 (void *sleepTimeForP1)
{
int *tsleepTimeForP1 = (int *)sleepTimeForP1;
struct timeval end;
while(1)
{
pthread_mutex_lock(&lock);
sno++;
gettimeofday(&end , NULL);
printf("%ld\t1\t\t1.1\t%.0lf\n",sno,time_diff(initial, end));
sno++;
gettimeofday(&end , NULL);
printf("%ld\t1\t\t1.2\t%.0lf\n",sno,time_diff(initial, end));
pthread_mutex_unlock(&lock);
sleep(1);
}
}
void *process2 (void *sleepTimeForP2)
{
int *tsleepTimeForP2 = (int *)sleepTimeForP2;
struct timeval end;
while(1)
{
pthread_mutex_lock(&lock);
sno++;
gettimeofday(&end , NULL);
printf("%ld\t2\t\t2.1\t%.0lf\n",sno,time_diff(initial, end));
sno++;
gettimeofday(&end , NULL);
printf("%ld\t2\t\t2.2\t%.0lf\n",sno,time_diff(initial, end));
pthread_mutex_unlock(&lock);
sleep(1);
}
}
It give me the below output:
S No. Thread Number Item Time(usec)
1 1 1.1 320
2 1 1.2 438
3 2 2.1 506
4 2 2.2 586
5 1 1.1 1000592
6 1 1.2 1000629
7 2 2.1 1000714
8 2 2.2 1000740
9 1 1.1 2000820
10 1 1.2 2000927
11 2 2.1 2000998
12 2 2.2 2001099
13 1 1.1 3001165
14 1 1.2 3001285
15 2 2.1 3001355
16 2 2.2 3001441
17 1 1.1 4001518
18 1 1.2 4001635
19 2 2.1 4001706
20 2 2.2 4001798
21 1 1.1 5001776
But when I do ./a.out > b.txt
I don't get any output on the console as well as in the file
When it is detected that the output is not directed to a terminal, the buffering is set to block buffering behind the scenes.
If you have waited long enough (probably for 4096 bytes of output to be generated), then the whole output would appear in bulk.
To solve this, you can either use fflush(stdout); after every printf(); or force the buffering mode explicitly to line buffering at the beginning with setlinebuf(stdout);.
Check out the manpage of setlinebuf() for further info.
I will be giving some pointers. Read the Linux Programming Book, to understand what is really happening.
I have added an fflush(stdout) after the relevant printf() statements of your code, i.e. line 32,65,85.
Once this is done, you will get the desired output. Now try to understand that why this kind of behavior occurs and why an explicit fflush() is required? I believe there should be some effort from the Question poster to understand the problem and to post a Minimal Complete Verifiable Example
Full Code:
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
double time_diff(struct timeval x , struct timeval y);
struct timeval initial;
long sno=0;
void *process1 (void *sleepTimeForP1);
void *process2 (void *sleepTimeForP2);
pthread_mutex_t lock;
int main()
{
gettimeofday(&initial , NULL);
pthread_t trd1,trd2;
int thread1,thread2;
int var1;
int var2;
int *sleepTimeForP1;
int *sleepTimeForP2;
var1=rand()%9+1;
sleepTimeForP1=&var1;
var2=rand()%9+1;
sleepTimeForP2=&var2;
printf("S No...\tThread Number\tItem\tTime(usec)\n");
fflush(stdout);
thread1=pthread_create(&trd1,NULL,process1,(void *)sleepTimeForP1);
thread2=pthread_create(&trd2,NULL,process2,(void *)sleepTimeForP2);
pthread_join(trd1, NULL);
pthread_join(trd2, NULL);
printf("pthread1 = %d\n",thread1);
printf("pthread2 = %d\n",thread2);
return 0;
}
double time_diff(struct timeval x , struct timeval y)
{
double x_ms , y_ms , diff;
x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
diff = (double)y_ms - (double)x_ms;
return diff;
}
void *process1 (void *sleepTimeForP1)
{
int *tsleepTimeForP1 = (int *)sleepTimeForP1;
struct timeval end;
while(1)
{
pthread_mutex_lock(&lock);
sno++;
gettimeofday(&end , NULL);
printf("%ld\t1\t\t1.1\t%.0lf\n",sno,time_diff(initial, end));
sno++;
gettimeofday(&end , NULL);
printf("%ld\t1\t\t1.2\t%.0lf\n",sno,time_diff(initial, end));
fflush(stdout);
pthread_mutex_unlock(&lock);
sleep(1);
}
}
void *process2 (void *sleepTimeForP2)
{
int *tsleepTimeForP2 = (int *)sleepTimeForP2;
struct timeval end;
while(1)
{
pthread_mutex_lock(&lock);
sno++;
gettimeofday(&end , NULL);
printf("%ld\t2\t\t2.1\t%.0lf\n",sno,time_diff(initial, end));
sno++;
gettimeofday(&end , NULL);
printf("%ld\t2\t\t2.2\t%.0lf\n",sno,time_diff(initial, end));
fflush(stdout);
pthread_mutex_unlock(&lock);
sleep(1);
}
}

Open MPI's MPI_reduce not combining array sums

I am very new to Open MPI. I have made a small program that computes the sum of an array, by splitting array into pieces equal to the number of processes. The problem in my program is that each process is computing right sum of its share of the array, but the individually computed sums are not summed by MPI_reduce function. I tried my best to solve and also consulted the Open MPI manual, but there is still something that I might be missing. I would be grateful for any kind of guidance. Below is the program I made:
#include "mpi.h"
#include <stdio.h>
int main(int argc, char *argv[])
{
int n, rank, nrofProcs, i;
int sum, ans;
// 0,1,2, 3,4,5, 6,7,8, 9
int myarr[] = {1,5,9, 2,8,3, 7,4,6, 10};
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nrofProcs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
n = 10;
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
sum = 0.0;
int remaining = n % nrofProcs;
int lower =rank*(n/nrofProcs);
int upper = (lower+(n/nrofProcs))-1;
for (i = lower; i <= upper; i++)
{
sum = sum + myarr[i];
}
if(rank==nrofProcs-1)
{
while(i<=remaining)
{
sum = sum + myarr[i];
i++;
}
}
/* (PROBLEM IS HERE, IT IS NOT COMBINING "sums") */
MPI_Reduce(&sum, &ans, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
// if (rank == 0)
printf( "rank: %d, Sum ans: %d\n", rank, sum);
/* shut down MPI */
MPI_Finalize();
return 0;
}
Output:
rank: 2, Sum ans: 17
rank: 1, Sum ans: 13
rank: 0, Sum ans: 15
(Output should be rank: 0, Sum ans: 55)
Sorry, I made some mistakes, that I corrected after running parallel debugging on my program. Here I am sharing code to split an array of length N on M processes, where N and M can have any value:
/*
An MPI program split an array of length N on M processes, where N and M can have any value
*/
#include <math.h>
#include "mpi.h"
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char *argv[])
{
int n, rank, nrofProcs, i;
int sum, ans;
// 0,1,2, 3,4,5, 6,7,8, 9, 10
int myarr[] = {1,5,9, 2,8,3, 7,4,6,11,10};
vector<int> myvec (myarr, myarr + sizeof(myarr) / sizeof(int) );
n = myvec.size(); // number of items in array
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nrofProcs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
sum = 0.0;
int remaining = n % nrofProcs;
int lower =rank*(n/nrofProcs);
int upper = (lower+(n/nrofProcs))-1;
for (i = lower; i <= upper; i++)
{
sum = sum + myvec[i];
}
if(rank==nrofProcs-1)
{
int ctr=0;
while(ctr<remaining)
{
sum = sum + myvec[i];
ctr++;
i++;
}
}
/* combine everyone's calculations */
MPI_Reduce(&sum, &ans, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
if (rank == 0)
cout << "rank: " <<rank << " Sum ans: " << ans<< endl;
/* shut down MPI */
MPI_Finalize();
return 0;
}

difficulty with MPI_Gather function

I have a value on local array (named lvotes) for each of the processors (assume 3 processors), and first element of each is storing a value, i.e.:
P0 : 4
P1 : 6
p2 : 7
Now, using MPI_Gather, I want gather them all in P0, so It will look like :
P0 : 4, 6, 7
I used gather this way:
MPI_Gather(lvotes, P, MPI_INT, lvotes, 1, MPI_INT, 0, MPI_COMM_WORLD);
But I get problems. It's my first time coding in MPI. I could use any suggestion.
Thanks
This is a common issue with people using the gather/scatter collectives for the first time; in both the send and receive counts you specify the count of items to send to or receive from each process. So although it's true that you'll be, in total, getting (say) P items, if P is the number of processors, that's not what you specify to the gather operation; you specify you are sending a count of 1, and receiving a count of 1 (from each process). Like so:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <mpi.h>
int main ( int argc, char **argv ) {
int rank;
int size;
int lvotes;
int *gvotes;
MPI_Init ( &argc, &argv );
MPI_Comm_rank ( MPI_COMM_WORLD, &rank );
MPI_Comm_size ( MPI_COMM_WORLD, &size );
if (rank == 0)
gvotes = malloc(size * sizeof(int) );
/* everyone sets their first lvotes element */
lvotes = rank+4;
/* Gather to process 0 */
MPI_Gather(&lvotes, 1, MPI_INT, /* send 1 int from lvotes.. */
gvotes, 1, MPI_INT, /* gather 1 int each process into lvotes */
0, MPI_COMM_WORLD); /* ... to root process 0 */
printf("P%d: %d\n", rank, lvotes);
if (rank == 0) {
printf("P%d: Gathered ", rank);
for (int i=0; i<size; i++)
printf("%d ", gvotes[i]);
printf("\n");
}
if (rank == 0)
free(gvotes);
MPI_Finalize();
return 0;
}
Running gives
$ mpirun -np 3 ./gather
P1: 5
P2: 6
P0: 4
P0: Gathered 4 5 6

Resources