# Chapter 5 (Basic MPI)
> Program got 3 important element
> 1) Communication - Within the communicator only processes inside communicator can communicate with each other
> 2) Process - Can be identified by rank
> 3) Message
## Code
### Find out important element
#### Initialize MPI
```cpp
int mpi;
mpi = MPI_init(&argc, &argv); //important to init first
```
#### Terminate MPI
```cpp
int mpi;
mpi = MPI_init(&argc, &argv); //important to init first
mpi = MPI_Finalize(); //once tak pakai, terminate it (optional)
```
#### Total number of processes
```cpp
int mpi, numProcesses;
mpi = MPI_init(&argc, &argv); //important to init first
mpi = MPI_Comm_size(MPI_COMM_WORLD, &numProcesses); //find total number of processes in a communication
printf("Total number of process is: %d\n", numProcesses);
```
```bash
┌──(aan㉿aan)-[~/HPPC]
└─$ mpirun -np 1 helloworld
Total number of process is: 1
```
```bash
┌──(aan㉿aan)-[~/HPPC]
└─$ mpirun -np 2 helloworld
Total number of process is: 2
Total number of process is: 2
```
#### Exact rank (something like id) of a process
```cpp
int mpi, rank;
mpi = MPI_Init(&argc, &argv); //important to init first
mpi = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
printf("Coming from rank/process %d\n", rank);
```
```bash
┌──(aan㉿aan)-[~/HPPC]
└─$ mpirun -np 1 helloworld
Coming from rank/process 0
```
```bash
┌──(aan㉿aan)-[~/HPPC]
└─$ mpirun -np 2 helloworld
Coming from rank/process 0
Coming from rank/process 1
```
# Chapter 6 (Sending & Receiving Messages)
Messages sent must be using MPI Datatypes
| MPI Datatype | C/C++ Datatype |
| -------- | -------- |
| MPI_CHAR | Char |
| MPI_INT | INT |
| MPI_FLOAT | Float |
| MPI_DOUBLE | Double |
Asynchronous
>Sender send without knowing bila receiver dapat the message
Synchronous
> 1. You send you know when the receiver will receive the message
> 2. The receiver also know when the sender send a message
Blocking
> Process is blocked until the operation has completed
Non Blocking
> Just proceed without waiting for the communication
#### MPI_Send() & MPI_Recv()
MPI_Send(data address, size of data, data type, rank/id of receiver, tag (can be anything, but must tally with MPI_Recv() method)
MPI_Recv(data address, size of data, data type, sender rank/id, tag(can be anything but must be tally with MPI_Send() method)
```cpp
#include <stdio.h>
#include <mpi.h>
int main(int argc, char** argv){
MPI_Init(&argc, &argv);
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int size;
MPI_Comm_size(MPI_COMM_WORLD, &size);
int data;
if(rank == 0){
data = -1;
MPI_Send(&data, 1, MPI_INT, 1, 100, MPI_COMM_WORLD);
}else if (rank == 1){
MPI_Recv(&data, 1, MPI_INT, 0, 100, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("Process %d received %d from Process 0", rank, data);
}
MPI_Finalize();
}
```
```bash
┌──(aan㉿aan)-[~/HPPC]
└─$ mpirun -np 2 helloworld
Process 1 received -1 from Process 0
```
#### Wildcarding
So that you can make the receiver process receive data from any process, with any tag
Example Scenario

```cpp
#include <stdio.h>
#include <mpi.h>
int main(int argc, char** argv){
MPI_Init(&argc, &argv);
MPI_Status status;
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int size;
MPI_Comm_size(MPI_COMM_WORLD, &size);
int data, number = 0;
int target_rank = 3;
if(rank < 3){
data = 10;
printf("Process %d is sending %d to process 4\n", rank, data);
MPI_Send(&data, 1, MPI_INT, 3, 10, MPI_COMM_WORLD );
}else if(rank == 3){
for(int i = 0; i < 3; i++){
MPI_Recv(&data, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
printf("Received %d from %d with the tag of %d\n", data, status.MPI_SOURCE, status.MPI_TAG);
}
}
MPI_Finalize();
}
```
```bash
┌──(aan㉿aan)-[~/HPPC]
└─$ mpirun -np 4 helloworld3
Process 0 is sending 10 to process 4
Process 2 is sending 10 to process 4
Process 1 is sending 10 to process 4
Received 10 from 2 with the tag of 10
Received 10 from 1 with the tag of 10
Received 10 from 0 with the tag of 10
```
#### Time Execution
> Datatype must be double
```cpp
#include <stdio.h>
#include <mpi.h>
#include <unistd.h>
int main(int argc, char** argv) {
double startTime, endTime;
int rank;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
startTime = MPI_Wtime();
sleep(5 * rank);
endTime = MPI_Wtime();
printf("Sleeping of process %d times taken %.2f\n", rank, endTime - startTime);
fflush(stdout);
MPI_Finalize();
return 0;
}
```
```bash
┌──(aan㉿aan)-[~/HPPC]
└─$ mpirun -np 4 meow
Sleeping of process 0 times taken 0.00
Sleeping of process 1 times taken 5.00
Sleeping of process 2 times taken 10.00
Sleeping of process 3 times taken 15.00
```
Damn the rest im too lazy to read and code.