I want to create MPI communicators linking the process with rank 0 to every other process. Suppose n is the total number of processes. Then the process with rank 0 is supposed to have n-1 communicators while each of the other processes has one communicator. Is this possible, and, if it is, why can I not use the program below to achieve this?
Compiling the code below using the mpic++ compiler terminates without warnings and errors on my computer. But when I run the resulting program using 3 or more processes (mpiexec -n 3), it never terminates.
Likely I'm misunderstanding the concept of communicators in MPI. Maybe someone can help me understand why the program below gets stuck, and what is a better way to create those communicators? Thanks.
#include <iostream>
#include <vector>
#include <thread>
#include <chrono>
#include "mpi.h"
void FinalizeMPI();
void InitMPI(int argc, char** argv);
int main(int argc, char** argv) {
InitMPI(argc, argv);
int rank,comm_size;
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&comm_size);
if(comm_size<2) {
FinalizeMPI();
return 0;
}
MPI_Group GroupAll;
MPI_Comm_group(MPI_COMM_WORLD, &GroupAll);
if(rank==0) {
std::vector<MPI_Group> myGroups(comm_size-1);
std::vector<MPI_Comm> myComms(comm_size-1);
for(int k=1;k<comm_size;++k) {
int ranks[2]{0, k};
MPI_Group_incl(GroupAll, 2, ranks, &myGroups[k-1]);
int err = MPI_Comm_create(MPI_COMM_WORLD, myGroups[k-1], &myComms[k-1]);
std::cout << "Error: " << err << std::endl;
}
} else {
MPI_Group myGroup;
MPI_Comm myComm;
int ranks[2]{0,rank};
MPI_Group_incl(GroupAll, 2, ranks, &myGroup);
int err = MPI_Comm_create(MPI_COMM_WORLD, myGroup, &myComm);
std::cout << "Error: " << err << std::endl;
}
std::cout << "Communicators created: " << rank << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
FinalizeMPI();
return 0;
}
void FinalizeMPI() {
int flag;
MPI_Finalized(&flag);
if(!flag)
MPI_Finalize();
}
void InitMPI(int argc, char** argv) {
int flag;
MPI_Initialized(&flag);
if(!flag) {
int provided_Support;
MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided_Support);
if(provided_Support!=MPI_THREAD_MULTIPLE) {
exit(0);
}
}
}
MPI_Comm_create is a collective operation on the initial communicator (MPI_COMM_WORLD) - you must call it on all processes.
The simplest way to fix the issue is to use MPI_Comm_create_group just the way you do it. It is similar to MPI_Comm_create except that it is collective over the group.
Related
Using Poco-1.12.4-release and g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, The recommended example code for DatagramSocket Receive in this doc:
https://pocoproject.org/slides/200-Network.pdf
compiles with this error:
dgs.cpp: In function ‘int main(int, char**)’:
dgs.cpp:34:33: error: no matching function for call to ‘Poco::Net::DatagramSocket::DatagramSocket(Poco::Net::SocketAddress&)’
34 | Poco::Net::DatagramSocket dgs(sa);
What happened? Is there a fix for this example?
Thanks
The code is:
// DatagramSocket receive example
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/SocketAddress.h"
#include <iostream>
int main(int argc, char** argv)
{
Poco::Net::SocketAddress sa(Poco::Net::IPAddress(), 514);
Poco::Net::DatagramSocket dgs(sa);
char buffer[1024];
for (;;)
{
Poco::Net::SocketAddress sender;
int n = dgs.receiveFrom(buffer, sizeof(buffer)-1, sender);
buffer[n] = '\0';
std::cout << sender.toString() << ": " << buffer << std::endl;
}
return 0;
}
I tried this:
Poco::Net::SocketAddress sa(Poco::Net::IPAddress(), 514);
Poco::Net::DatagramSocket dgs(Poco::Net::SocketAddress::IPv4);
dgs.connect(sa);
It compiles, but is it correct?
I have some code that for testing purposes, I removed all sends and only have non-blocking receives. You can imagine my surprise when using MPI_Test the flags were indicating some of the requests were actually being completed. I have my code setup in a cartesian grid, with a small replica below, although this doesn't reproduce the error:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // for sleep
#include <mpi.h>
void test(int pos);
MPI_Comm comm_cart;
int main(int argc, char *argv[])
{
int i, j;
int rank, size;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
/* code for mpi cartesian gird topology */
int dim[1];
dim[0] = 2;
int periods[1];
periods[0] = 0;
int reorder = 1;
int coords[1];
MPI_Cart_create(MPI_COMM_WORLD, 1, dim, periods, 1, &comm_cart);
MPI_Cart_coords(comm_cart, rank, 2, coords);
test(coords[0]);
MPI_Finalize();
return (0);
}
void test(int pos)
{
float placeholder[4];
int other = (pos+1) % 2;
MPI_Request reqs[8];
int flags[4];
for(int iter = 0; iter < 20; iter++){
// Test requests from previous time cycle
for(int i=0;i<4;i++){
if(iter == 0) break;
MPI_Test(&reqs[0], &flags[0] , MPI_STATUS_IGNORE);
printf("Flag: %d\n", flags[0]);
}
MPI_Irecv(&placeholder[0], 1, MPI_FLOAT, other, 0, comm_cart, &reqs[0]);
}
}
Any help would be appreciated.
The issue is with MPI_Test and MPI_PROC_NULLs. Quite often when using MPI_Cart_shift, you end up with MPI_PROC_NULLs as if you're on the edge of the grid, a neighbouring cell simply doesn't exist in some directions.
I can't find any documentation for this anywhere, so I had to discover it myself, but when you do an MPI_Irecv with an MPI_PROC_NULL source, it will instantly complete and when tested using MPI_Test, the flag will return true for a completed request. Example code below:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
int t;
int flag;
MPI_Request req;
MPI_Irecv(&t, 1, MPI_INT, MPI_PROC_NULL, 0, MPI_COMM_WORLD, &req);
MPI_Test(&req, &flag, MPI_STATUS_IGNORE);
printf("Flag: %d\n", flag);
MPI_Finalize();
return (0);
}
Which returns the following when run:
Flag: 1
Flag: 1
My aim is to print abbcccdddd with an input of abcd. Its the first time I am using Gatherv.
int main(int argc, char *argv[])
{
MPI_Init(&argc,&argv);
int rank,size;
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
int n[100];
MPI_Status status;
int x,i=0,m;
int total[4];
char str[100],str1[100],a1[100],a[100];
if(rank==0){
scanf("%s",str);
}
MPI_Scatter(str,1,MPI_CHAR,a,1,MPI_CHAR,0,MPI_COMM_WORLD);
x=rank;
while(i<=rank){
a1[i]=a[0];
i++;
}
int disps[4];
int y=rank;
disps[rank]=0;
while(y!=0){
disps[rank]+=y;
y--;
}
total[rank]=rank+1;
printf("%s\n",a1 );
char k[100];
printf("%d %d\n",total[rank],disps[rank] );
MPI_Gatherv(a1,rank+1,MPI_CHAR,k,total,disps,MPI_CHAR,0,MPI_COMM_WORLD);
if(rank==0){
printf("Total %s\n",k);
}
MPI_Finalize();
/* code */
return 0;
}
After running the code , the printf values of total and disps are correct but the program throws up a segmentation fault
The root cause is both total and disps should be assembled on the root rank (rank 0 in your example).
They are currently "distributed" and hence not initialized on the root rank, which leads to an undefined behavior such as a crash.
When I run this code with one process, it works fine:
#include <iostream>
#include "mpi.h"
using namespace std;
int main(int argc, char* argv[])
{
MPI_Comm SubWorld;
MPI_Init(&argc, &argv);
int Rank;
MPI_Comm_rank(MPI_COMM_WORLD, &Rank);
if (Rank == 0)
MPI_Comm_split(MPI_COMM_WORLD, 1, Rank, &SubWorld);
cout << Rank << endl;
MPI_Finalize();
return 0;
}
Output: 0
But when I run it with more than one process, the output is "1" only!!.
This code works fine:
#include <iostream>
#include "mpi.h"
using namespace std;
int main(int argc, char* argv[])
{
MPI_Comm SubWorld;
MPI_Init(&argc, &argv);
int Rank;
MPI_Comm_rank(MPI_COMM_WORLD, &Rank);
MPI_Comm_split(MPI_COMM_WORLD, 1, Rank, &SubWorld);
cout << Rank << endl;
MPI_Finalize();
return 0;
}
Outputs two lines with "0" and "1" in some order.
So, the question is what the wrong in the first code when I run it with more than one process?
MPI_Comm_split() is a collective operation, and it must be invoked by all the MPI tasks of the communicator (MPI_COMM_WORLD here).
So what really happens in your first example running on multiple nodes is that MPI task 0 hangs in MPI_Comm_split()
http://creativemachines.cornell.edu/eureqa/
http://code.google.com/p/eureqa-api/
Is there a way of interfacing Eureqa with R?
(windows os)
Perhaps:
Rcpp package and:
The simplest possible complete C++ program using the Eureqa API:
#include eureqa/eureqa.h
#include iostream
int main(int argc, char *argv[])
{
// initialize data set and options
eureqa::data_set data("my_data.txt");
eureqa::search_options options("y = f(x)");
// connect to a eureqa server
eureqa::connection conn("127.0.0.1");
conn.send_data_set(data);
conn.send_options(options);
conn.start_search();
// display results
eureqa::search_progress progress;
eureqa::solution_frontier solutions;
while (conn.query_progress(progress))
{
solutions.add(progress.solution_);
std::cout << progress.summary() << std::endl;
std::cout << solutions.to_string() << std::endl;
}
return 0;
}