I am trying to do some MPI parallel work. I am able to run this on any number of processors. The issue is that each processor will take one job, execute it and send it back then the program is done. I want to be able to send a processor another job when it has finished. Im not sure how to implement this. Basically I am trying to send each core 10 jobs.
if (myRank == 0) {
int numCores = MPI::COMM_WORLD.Get_size();
for (int rank = 1; rank < numCores; rank++) {
MPI::COMM_WORLD.Send(&yarray[0], imax, MPI::DOUBLE, rank, 0);
MPI::COMM_WORLD.Send(&tarray[0], imax, MPI::DOUBLE, rank, 0);
MPI::COMM_WORLD.Recv(&ans, imax, MPI::DOUBLE, MPI::ANY_SOURCE, MPI_ANY_TAG, mystatus);
answers[counter] = ans;
counter++;
}
}
else
{
MPI::COMM_WORLD.Recv(&yarray1, imax, MPI::DOUBLE, MPI::ANY_SOURCE, MPI_ANY_TAG, mystatus);
MPI::COMM_WORLD.Recv(&tarray1, imax, MPI::DOUBLE, MPI::ANY_SOURCE, MPI_ANY_TAG, mystatus);
double floor = 0.5, ceiling = 3.5, range = (ceiling - floor);
double rnd = floor + double((range * rand()) / (RAND_MAX + 1.0));
yarray [0] = rnd;
yarray1 [0] = rnd;
double temp = 0;
for (int k = 0; k < imax; k++) {
tarray1[k+1] = tarray1[k] + h;
yarray1[k+1] = yarray1[k] + h * (2 * yarray1[k] - 2 * tarray1[k] * tarray1[k] - 3);
}
temp = yarray1[int(imax)];
//cout << "Rank = " << myRank << " Solution = " << temp << endl;
MPI::COMM_WORLD.Send(&temp, 1, MPI::DOUBLE, 0, 0);
}
Update: within in myrank == 0
while(counter != jobs){
MPI::COMM_WORLD.Recv(&ans, imax, MPI::DOUBLE, MPI::ANY_SOURCE, MPI_ANY_TAG, mystatus);
answers[counter] = ans;
counter++;
}
You need to have some sort of feedback from rank 0 to the other ranks. After the other ranks return their work to rank 0, they should receive a new message back that tells them either their next job or that there is no more work to be completed. The ranks should continue looping until there is no more work to be done.
Related
I need generate an array in each process and in these processes find the minimum value of its generated part.I do not understand how to divide the generation into parts and find the minimum value in these parts.
int rank, num_procs;
double result;
int length = 10e6;
double *arr = new double[length];
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int load = length / num_procs;
auto min = DBL_MAX, max = DBL_MIN;
for (int i = rank * load; i < (rank + 1) * load; ++i) {
arr[i] = (pow(2 * i, 1 / 3) + 6) / abs(i * cos(i));
if (arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i];
}
}
result = min * max;
cout << result << endl;
MPI_Send(&result, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
if (rank == 0) {
MPI_Recv(&result, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
result *= result;
cout << result << endl;
}
One naive way to do is divide your load (perform the number generation) equally. Say (load=length/num_procs). So each process will generate load numbers. Basically rank 0 will generates values from i=0 to i=load, while rank 1 will generate values from i=load to i=2*load and so on. Basically, each rank will loop from i=rank*load to i=(rank+1)*load. Assumption: length/num_procs is divisible. Otherwise you have to distribute the remaining load.
load=length / num_procs;
for (int i = rank*load; i < (rank+1)*load; ++i) {
arr[i] = (pow(2 * i, 1/3) + 6) / abs(i * cos(i));
}
I have a 3d array (like a cube) and I want to send its surfaces as 2d array. I defined three datatype for xy, yz and xz planes and send them. But I keep getting the following error:
[Munny:8034] *** An error occurred in MPI_Send
[Munny:8034] *** on communicator MPI_COMM_WORLD
[Munny:8034] *** MPI_ERR_TYPE: invalid datatype
[Munny:8034] *** MPI_ERRORS_ARE_FATAL (your MPI job will now abort)
--------------------------------------------------------------------------
mpiexec has exited due to process rank 0 with PID 8034 on
node Munny exiting without calling "finalize". This may
have caused other processes in the application to be
terminated by signals sent by mpiexec (as reported here).
--------------------------------------------------------------------------
[Munny:08033] 1 more process has sent help message help-mpi-errors.txt / mpi_errors_are_fatal
[Munny:08033] Set MCA parameter "orte_base_help_aggregate" to 0 to see all help / error messages
This is the simplified version of my code:
int main(int argc, char *argv[]) {
MPI_Init(NULL, NULL);
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
int prev = 0;
int curr = 1;
global_err = 10E4;
N = atof(argv[1]);
s = cbrt(world_size); // world_size is always cube
cube_edge_size = (N + 1 / s) + 2; // +2 is for ghost points
double**** arr = new double***[2];
for (int i = 0; i < 2; ++i) {
arr[i] = new double**[cube_edge_size];
for (int j = 0; j < cube_edge_size; ++j){
arr[i][j] = new double*[cube_edge_size];
for (int k = 0; k < cube_edge_size; ++k)
arr[i][j][k] = new double[cube_edge_size];
}
}
MPI_Datatype MPI_xy_plane;
MPI_Datatype MPI_yz_plane;
MPI_Datatype MPI_xz_plane;
MPI_Type_vector(cube_edge_size, cube_edge_size,cube_edge_size*cube_edge_size, MPI_DOUBLE, &MPI_xz_plane) ;
//other definitions ...
MPI_Request req[12];
MPI_Status stats[12];
while (global_err > 10E-4) {
double local_err = 0;
prev = 1 - prev;
curr = 1 - prev;
// send values to other processors - non blocking
if(world_rank % s != 0){
// not on the left surface of the cube
MPI_Isend(&arr[curr][0][1][0], 1, MPI_xz_plane, world_rank - 1, 2, MPI_COMM_WORLD, &req[2]);
}
//... other sends
// get values from other processors - blocking
if(world_rank % s != s-1){
// not on the right surface of the cube
MPI_Irecv(&arr[prev][0][0][0], 1, MPI_xz_plane, world_rank + 1, 2, MPI_COMM_WORLD, &req[8]);
}
// ... other receives
MPI_Waitall(12,req,stats);
for (int i = 1; i < cube_edge_size-1; i++) {
for (int j = 1; i < cube_edge_size-1; i++) {
for (int k = 1; i < cube_edge_size-1; i++) {
// calculate new values
arr[curr][i][j][k] = arr[prev][i][j][k] + k * 0.2;//do some other calculation
// calculate error
local_err += abs(arr[curr][i][j][k] - arr[prev][i][j][k]);
}
}
}
MPI_Allreduce(&local_err, &global_err, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
}
MPI_Finalize();
return 0;
}
Since arr is 4d I am not sure if this is true. I need to store current and previous values. I tried the same code by changing arr to 3d but I got the same error message.
I need assistance to resolve an error in the following code:
#include <iostream>
#include <mpi.h>
using namespace std;
//matrix in two dimension in memory!!
int main(int argc, char** argv)
{
const int WIDTH = 100;
const int HEIGHT = 100;
int id, P;
double tempValue = 0;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &P);
MPI_Comm_rank(MPI_COMM_WORLD, &id);
double A[WIDTH][HEIGHT];
double x[HEIGHT], b[WIDTH];
int upperBound, lowerBound = 0;
// Master controls worksharing..
if (id == 0)
{
// Init A & x
for (int i = 0; i < WIDTH; i++)
for (int j = 0; j < HEIGHT; j++)
A[i][j] = 1;
for (int j = 0; j < HEIGHT; j++)
x[j] = 2;
// Send to each node its portion of A to be processed
int portionSize = WIDTH / P;
for (int i = 0; i < P; i++)
{
lowerBound = i * portionSize;
upperBound = (i + 1) * portionSize;
// let the last node process the remainder
if (i == (P - 1))
upperBound += (HEIGHT - portionSize * P);
if (i > 0)// Do not send to master node!!
{
// Send to node i the lower & upper bounds the A portion
//and complete vector x
MPI_Send(&lowerBound, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
MPI_Send(&upperBound, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
MPI_Send(&A[lowerBound][0], (upperBound - lowerBound) * HEIGHT,
MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
MPI_Send(&x[0], HEIGHT, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
}
}
// master perform part of the job...
for (int i = 0; i < portionSize; i++)
{
tempValue = 0;
for (int j = 0; j < HEIGHT; j++)
tempValue += A[i][j] * x[j];
b[i] = tempValue;
}
//Get the results in order, each node would send their boundaries and data part
for (int i = 1; i < P; i++)
{
MPI_Recv(&lowerBound, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
MPI_Recv(&upperBound, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
MPI_Recv(&P[lowerBound], (upperBound - lowerBound), MPI_DOUBLE, i, 0,
MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
}
// Print the first 2 values to check..
cout << "b[0]=" << b[0] << " b[Width-1]=" << b[WIDTH - 1] << endl;
}
else // the rest of the workers do their parts
{
//Receive the inputs
MPI_Recv(&lowerBound, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
MPI_Recv(&upperBound, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
MPI_Recv(&A[lowerBound][0], (upperBound - lowerBound) * WIDTH, MPI_DOUBLE, 0, 0,
MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
MPI_Recv(&x, HEIGHT, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
cout << "Node:" << id << " Received from:" << lowerBound << " to " << upperBound - 1
<< endl;
double* result = new double[upperBound - lowerBound];
//Do the job
for (int i = lowerBound, resultCounter = 0; i < upperBound; i++, resultCounter++)
{
tempValue = 0;
for (int j = 0; j < HEIGHT; j++)
tempValue += A[i][j] * x[j];
result[resultCounter] = tempValue;
}
//send the results
MPI_Send(&lowerBound, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
MPI_Send(&upperBound, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
MPI_Send(&result[0], upperBound - lowerBound, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
delete[] result;
}
MPI_Finalize();
return 0;
}
When I compile the code in Microsoft Visual Studio 2019, I get this error message:
Error (active) E0142 expression must have pointer-to-object type ConsoleApplication9 C:\Users\m_swe\Desktop\Assignments\Assignments\PrjP2P\MatMPI\MatMPI\Source.cpp 59
Error C2109 subscript requires array or pointer type ConsoleApplication9 C:\Users\m_swe\Desktop\Assignments\Assignments\PrjP2P\MatMPI\MatMPI\Source.cpp 59
I think the problem is on line: 59
MPI_Recv(&P[lowerBound], (upperBound - lowerBound), MPI_DOUBLE, i, 0,
MPI_Recv takes in a pointer to a buffer (the first argument) where you are going to receive and store the incoming data. In this case it could be in some variable which you can define inside the for loop, as:
int receivedValues[ WIDTH * HEIGHT ];
for (int i = 1; i < P; i++)
{
MPI_Recv(&lowerBound, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
MPI_Recv(&upperBound, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
MPI_Recv(&receivedValues[0], (upperBound - lowerBound), MPI_DOUBLE, i, 0,
MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
// do your computation here with receivedValues
}
}
I am trying to build game of life MPI version. However, when I send out true, I received false, since there is no MPI_BOOL, I used MPI_C_BOOL. The code snippet is below.
vector<bool> send_data_top;
vector<bool> recv_data_top(n);
vector<bool> send_data_down;
vector<bool> recv_data_down(n);
request = new MPI_Request[4];
for (int j = 0; j < n; j++) {
send_data_top.push_back(neigh_grid[n + j + 3]);
send_data_down.push_back(neigh_grid[last_row_index * (n + 2) + j + 1]);
cout << "send data: " << send_data_down[j] << endl;
cout << "send data top: " << send_data_top[j] << endl;
}
MPI_Isend(&send_data_top[0], n, MPI_C_BOOL, id - 1, 0, MPI_COMM_WORLD, &request[0]);
MPI_Isend(&send_data_down[0], n, MPI_C_BOOL, 0, 0, MPI_COMM_WORLD, &request[1]);
MPI_Irecv(&recv_data_top[0], n, MPI_C_BOOL, id - 1, 0, MPI_COMM_WORLD, &request[2]);
MPI_Irecv(&recv_data_down[0], n, MPI_C_BOOL, 0, 0, MPI_COMM_WORLD, &request[3]);
MPI_Waitall(4, request, MPI_STATUS_IGNORE);
delete[] request;
//assign receive values to neigh_grid
for (int j = 0; j < n; j++) {
neigh_grid[j + 1] = recv_data_top[j];
neigh_grid[(last_row_index + 1) * (n + 2) + j + 1] = recv_data_down[j];
cout << recv_data_top[j] << endl;
cout << recv_data_down[j] << endl;
}
The output is
send data: 1
send data top: 1
0
0
I have tried changing the type to MPI_CXX_BOOL and MPI_INT but none of them work and I cannot find a similar situation online. Can anyone figure out what caused this?
I'm new in MPI and I want to do make a problem where I have 2 array A and B with 15 elements and I have 16 processes and and each process represent an element in the arrays (I don't use process zero). The array A have stored input data an positions 8...15, where this positions reprezent the leaves of a tree and in the first step I make a compression in array, where the leaves send the number to the parent and parent receives from all sons and add the numbers and send to father. And the array A si done at process 1 where is the sum of all elements in the array. And in the second step I make prefix calculations where I start from process 0 and finish at leaves.
And to calculate the array B all the other processes need to wait the process 1 to finish the work and for that I using a MPI_Barrier but I have a error when I exec the code.
int m = 3;
int n = (int)pow(2, m);
int *A = (int*)malloc(2 * n * sizeof(int));
int *B = (int*)malloc(2 * n * sizeof(int));
int id;
MPI_Status status;
A[8] = 4; A[9] = 8; A[10] = 5; A[11] = 2;
A[12] = 10; A[13] = 6; A[14] = 9; A[15] = 11;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &id);
if (id == 1)
{
int nr;
int suma = 0;
MPI_Recv(&nr, 1, MPI_INT, 2 * id, 99, MPI_COMM_WORLD, &status);
suma += nr;
MPI_Recv(&nr, 1, MPI_INT, 2 * id + 1, 99, MPI_COMM_WORLD, &status);
suma += nr;
A[id] = suma;
printf("A[%d]=%d\n", id, A[id]);
B[id] = A[id];
printf("B[%d]=%d\n", id, B[id]);
MPI_Barrier(MPI_COMM_WORLD);
}
else
{
if (id != 0)
{
if(id >= 8)
{
MPI_Send(&A[id], 1, MPI_INT, id / 2, 99, MPI_COMM_WORLD);
printf("%d a trimis %d catre %d\n", id, A[id], id / 2);
MPI_Barrier(MPI_COMM_WORLD);
}
else
{
int nr;
int suma = 0;
MPI_Recv(&nr, 1, MPI_INT, 2 * id, 99, MPI_COMM_WORLD, &status);
suma += nr;
MPI_Recv(&nr, 1, MPI_INT, 2 * id + 1, 99, MPI_COMM_WORLD, &status);
suma += nr;
A[id] = suma;
MPI_Send(&A[id], 1, MPI_INT, id / 2, 99, MPI_COMM_WORLD);
printf("%d a trimis %d catre %d\n", id, A[id], id / 2);
MPI_Barrier(MPI_COMM_WORLD);
}
if (id % 2 == 1)
{
B[id] = B[(id - 1) / 2];
printf("B[%d]=%d\n", id, B[id]);
}
else
{
B[id] = B[id / 2] - A[id + 1];
printf("B[%d]=%d\n", id, B[id]);
}
}
MPI_Finalize();
free(A);
return 0;
And I receive the next error:
[15]fatal error Fatal error in MPI_Barrier:Other MPI error,
error stack: MPI_Barrier(MPI_COMM_WORLD) failed failed to
attach to a bootstrap queue - 5064:344
How can I do to make the program work?
MPI_Barrier() is a collective operation, and it will completes once invoked by all the MPI tasks from the communicator.
If i read correctly your code, task 0 does not invoke MPI_Barrier(MPI_COMM_WORLD), so your program will deadlock unless some mechanism in the MPI library aborts it.