I want to create a communicator group for the processors along the diagonal in a grid. here is my attempt but it gives me an error message after running tho code. Why is this error message
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "mpi.h"
int main(int argc, char **argv)
{
int i,iproc, index;
int Numprocs, MyRank;
int New_numprocs, NewMyRank;
int *process_rank, Group_Diag;
int diag;
MPI_Group GroupWorld,new_group;
MPI_Comm Diag_Group , newComm;
int track =0;
/* ....MPI Initialisation....*/
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &MyRank);
MPI_Comm_size(MPI_COMM_WORLD, &Numprocs);
diag = sqrt(Numprocs);
if(diag * diag != Numprocs)
{
printf("number of processes should be a perfect square\n");
MPI_Finalize();
exit(-1);
}
process_rank = (int *)malloc(diag * sizeof(int));
for(int idx =0; idx < diag ; idx ++)
{
process_rank[idx] = track;
track = track + diag + 1;
printf("rank : %d , track %d\n " , MyRank , track);
}
MPI_Comm_group(MPI_COMM_WORLD , &GroupWorld);
MPI_Group_incl(GroupWorld, diag , process_rank , &new_group);
MPI_Comm_create(MPI_COMM_WORLD , new_group , &newComm);
if(MyRank % (diag+1) ==0)
{
MPI_Comm_rank(newComm , &NewMyRank);
MPI_Comm_size(newComm , &Numprocs);
printf("old rank : %d , new rank %d" , MyRank , NewMyRank);
}
MPI_Finalize();
return 0;
}
and this is the error message:
24 at [0x0000000000e97078], src/mpi/group/grouputil.c[74]
[1] 48 at [0x0000000000e984b8], src/mpi/group/grouputil.c[74]
[2] 24 at [0x0000000001c39078], src/mpi/group/grouputil.c[74]
[2] 48 at [0x0000000001c3a4b8], src/mpi/group/grouputil.c[74]
[0] 8 at [0x0000000000d377f8], src/util/procmap/local_proc.c[93]
[0] 8 at [0x0000000000d37748], src/util/procmap/local_proc.c[92]
[0] 32 at [0x0000000000d37678], src/mpid/ch3/src/mpid_vc.c[102]
[0] 24 at [0x0000000000d36078], src/mpi/group/grouputil.c[74]
[0] 48 at [0x0000000000d374b8], src/mpi/group/grouputil.c[74]
[0] 504 at [0x0000000000d35a78], src/mpi/comm/commutil.c[258]
[0] 504 at [0x0000000000d357d8], src/mpi/comm/commutil.c[258]
[0] 504 at [0x0000000000d35298], src/mpi/comm/commutil.c[258]
[3] 8 at [0x00000000012487f8], src/util/procmap/local_proc.c[93]
[3] 8 at [0x0000000001248748], src/util/procmap/local_proc.c[92]
[3] 32 at [0x0000000001248678], src/mpid/ch3/src/mpid_vc.c[102]
[3] 24 at [0x0000000001247078], src/mpi/group/grouputil.c[74]
[3] 48 at [0x00000000012484b8], src/mpi/group/grouputil.c[74]
[3] 504 at [0x0000000001246a78], src/mpi/comm/commutil.c[258]
[3] 504 at [0x0000000001246298], src/mpi/comm/commutil.c[258]
Why don't you simply use MPI_Comm_split?
int rank;
MPI_Comm newComm;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_split(MPI_COMM_WORLD, rank % (diag+1) ? MPI_UNDEFINED : 0, rank, &newComm);
if (newComm != MPI_COMM_NULL)
{
// Code for ranks on the main diagonal
}
else
{
// Code for off-diagonal ranks
}
MPI_Comm_free(&newComm);
The split operation groups ranks according to the "colour" specified as the second argument. A colour of MPI_UNDEFINED means that the rank doesn't want to participate in the split and MPI_COMM_NULL is returned instead of a new subcommunicator handle.
Related
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.
I newbie to mpi programming. I was trying to write matrix multiplication. Went through the post MPI Matrix Multiplication with scatter gather about matrix multiplication using scatter and gather routine.
I tried modifying the code available on above post as below...
#define N 4
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stddef.h>
#include "mpi.h"
void print_results(char *prompt, int a[N][N]);
int main(int argc, char *argv[])
{
int i, j, k, rank, size, tag = 99, blksz, sum = 0;
int a[N][N]={{1,2,3,4},{5,6,7,8},{9,1,2,3},{4,5,6,7,}};
int b[N][N]={{1,2,3,4},{5,6,7,8},{9,1,2,3},{4,5,6,7,}};
int c[N][N];
int aa[N],cc[N];
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
//scatter rows of first matrix to different processes
MPI_Scatter(a, N*N/size, MPI_INT, aa, N*N/size, MPI_INT,0,MPI_COMM_WORLD);
//broadcast second matrix to all processes
MPI_Bcast(b, N*N, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
//perform vector multiplication by all processes
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
sum = sum + aa[j] * b[i][j];
}
cc[i] = sum;
sum = 0;
}
MPI_Gather(cc, N*N/size, MPI_INT, c, N*N/size, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
print_results("C = ", c);
}
void print_results(char *prompt, int a[N][N])
{
int i, j;
printf ("\n\n%s\n", prompt);
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf(" %d", a[i][j]);
}
printf ("\n");
}
printf ("\n\n");
}
I ran above program as
$mpirun -np 4 ./a.out
For above program I am getting following incorrect output..
C =
0 0 -562242168 32766
1 0 4197933 0
-562242176 32766 0 0
4197856 0 4196672 0
C =
0 0 -1064802792 32765
1 0 4197933 0
-1064802800 32765 0 0
4197856 0 4196672 0
C =
30 70 29 60
70 174 89 148
29 89 95 74
60 148 74 126
C =
0 0 -1845552920 32765
1 0 4197933 0
-1845552928 32765 0 0
4197856 0 4196672 0
I have following queries
1. Why result matrix C is getting printed by all processes. It is
supposed to be printed by only main process.
2. Why incorrect result is being printed?
Corrections and help in this regard will be appreciated.
The result matrix c is getting printed by all processes because every process executes the function void print_results(char *prompt, int a[N][N]). Since you are gathering at the process having rank 0, add a statement if (rank == 0) before calling the print_results(...) function. Further, the result is incorrect because of a wrong loop logic in :
for (j = 0; j < N; j++)
{
sum = sum + aa[j] * b[i][j];
}
This should be :
for (j = 0; j < N; j++)
{
sum = sum + aa[j] * b[j][i];
}
Also there is no need to broadcast b as all processes already already have a copy of it and you can avoid MPI_Barrier(). The complete program then becomes :
#define N 4
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stddef.h>
#include "mpi.h"
void print_results(char *prompt, int a[N][N]);
int main(int argc, char *argv[])
{
int i, j, k, rank, size, tag = 99, blksz, sum = 0;
int a[N][N]={{1,2,3,4},{5,6,7,8},{9,1,2,3},{4,5,6,7,}};
int b[N][N]={{1,2,3,4},{5,6,7,8},{9,1,2,3},{4,5,6,7,}};
int c[N][N];
int aa[N],cc[N];
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
//scatter rows of first matrix to different processes
MPI_Scatter(a, N*N/size, MPI_INT, aa, N*N/size, MPI_INT,0,MPI_COMM_WORLD);
//broadcast second matrix to all processes
MPI_Bcast(b, N*N, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
//perform vector multiplication by all processes
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
sum = sum + aa[j] * b[j][i]; //MISTAKE_WAS_HERE
}
cc[i] = sum;
sum = 0;
}
MPI_Gather(cc, N*N/size, MPI_INT, c, N*N/size, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
if (rank == 0) //I_ADDED_THIS
print_results("C = ", c);
}
void print_results(char *prompt, int a[N][N])
{
int i, j;
printf ("\n\n%s\n", prompt);
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf(" %d", a[i][j]);
}
printf ("\n");
}
printf ("\n\n");
}
Then c =
C =
54 37 47 57
130 93 119 145
44 41 56 71
111 79 101 123
Call to mpi_finalize doesn't indicate that all the MPI processes are terminated like in OpenMP !
In most of mpi implementation, all the processes execute the instruction before the MPI_init and after MPI_Finalized.
A good practice is to do nothing before MPI_Init and after MPI_Finalized.
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;
}
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
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.