pax_global_header 0000666 0000000 0000000 00000000064 13315401410 0014502 g ustar 00root root 0000000 0000000 52 comment=78f7914fff02d47d135676e251bd21117743f2b8
MPI-78f7914fff02d47d135676e251bd21117743f2b8/ 0000775 0000000 0000000 00000000000 13315401410 0016644 5 ustar 00root root 0000000 0000000 MPI-78f7914fff02d47d135676e251bd21117743f2b8/README.md 0000664 0000000 0000000 00000001351 13315401410 0020123 0 ustar 00root root 0000000 0000000 # Parallel programming with MPI
This repository contains various exercises and examples on parallel programming with message passing interface (MPI).
A working MPI installation is needed, please see individual exercise/example for detailed build instructions.
## How to contribute
Any contributions (new exercises and examples, bug fixes, improvements etc.) are
warmly welcome. In order to contribute, please follow the standard
Gitlab workflow:
1. Fork the project into your personal space
2. Create a feature branch
3. Work on your contributions
4. Push the commit(s) to your fork
5. Submit a merge request to the master branch
As a quality assurance, the merge request is reviewed by PRACE staff before it is accepted into main branch.
MPI-78f7914fff02d47d135676e251bd21117743f2b8/hello-world/ 0000775 0000000 0000000 00000000000 13315401410 0021074 5 ustar 00root root 0000000 0000000 MPI-78f7914fff02d47d135676e251bd21117743f2b8/hello-world/LICENSE.txt 0000664 0000000 0000000 00000001051 13315401410 0022714 0 ustar 00root root 0000000 0000000
Copyright (C) 2018 CSC - IT Center for Science Ltd.
Licensed under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Code is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
Copy of the GNU General Public License can be obtained from
.
MPI-78f7914fff02d47d135676e251bd21117743f2b8/hello-world/README.md 0000664 0000000 0000000 00000000676 13315401410 0022364 0 ustar 00root root 0000000 0000000 ## Parallel Hello World
a) Write a simple parallel program that prints out something
(e.g. “Hello world!”) from multiple processes. Include the MPI headers
(C), use the MPI module (Fortran), or import mpi4py (Python) and
call appropriate initialization and finalization routines.
b) Modify the program so that each process prints out also its rank
and so that the process with rank 0 prints out the total number of MPI
processes as well.
MPI-78f7914fff02d47d135676e251bd21117743f2b8/hello-world/solution/ 0000775 0000000 0000000 00000000000 13315401410 0022750 5 ustar 00root root 0000000 0000000 MPI-78f7914fff02d47d135676e251bd21117743f2b8/hello-world/solution/hello.F90 0000664 0000000 0000000 00000000536 13315401410 0024337 0 ustar 00root root 0000000 0000000 program hello
use mpi
implicit none
integer :: rc, myid, ntasks
call MPI_INIT(rc)
call MPI_COMM_SIZE(MPI_COMM_WORLD, ntasks, rc)
call MPI_COMM_RANK(MPI_COMM_WORLD, myid, rc)
if(myid == 0) then
write(*,*) 'In total there are ',ntasks, 'tasks'
endif
write(*,*) 'Hello from ',myid
call MPI_FINALIZE(rc)
end program hello
MPI-78f7914fff02d47d135676e251bd21117743f2b8/hello-world/solution/hello.c 0000664 0000000 0000000 00000000605 13315401410 0024220 0 ustar 00root root 0000000 0000000 #include
#include
#include
int main(int argc, char *argv[])
{
int i, myid, ntasks;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &ntasks);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
if (myid == 0) {
printf("In total there are %i tasks\n", ntasks);
}
printf("Hello from %i\n", myid);
MPI_Finalize();
return 0;
}
MPI-78f7914fff02d47d135676e251bd21117743f2b8/hello-world/solution/hello.py 0000664 0000000 0000000 00000000344 13315401410 0024426 0 ustar 00root root 0000000 0000000 from __future__ import print_function
from mpi4py import MPI
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
if rank == 0:
print("In total there are {0} tasks".format(size))
print("Hello from", rank)
MPI-78f7914fff02d47d135676e251bd21117743f2b8/message-exchange/ 0000775 0000000 0000000 00000000000 13315401410 0022050 5 ustar 00root root 0000000 0000000 MPI-78f7914fff02d47d135676e251bd21117743f2b8/message-exchange/LICENSE.txt 0000664 0000000 0000000 00000001051 13315401410 0023670 0 ustar 00root root 0000000 0000000
Copyright (C) 2018 CSC - IT Center for Science Ltd.
Licensed under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Code is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
Copy of the GNU General Public License can be obtained from
.
MPI-78f7914fff02d47d135676e251bd21117743f2b8/message-exchange/README.md 0000664 0000000 0000000 00000001317 13315401410 0023331 0 ustar 00root root 0000000 0000000 ## Simple message exchange
a) Write a simple program where two processes send and receive a
message to/from each other using `MPI_Send` and `MPI_Recv`. The message
content is an integer array, where each element is initialized to the
rank of the process. After receiving a message, each process should
print out the rank of the process and the first element in the
received array. You may start from scratch or use as a starting point
the skeleton code found in [exchange.c](exchange.c),
[exchange.F90](exchange.F90) or [exchange.py](exchange.py)
b) Increase the message size to 100,000, recompile and run. It is very likely
that the program will dead lock, try to figure out reason for this, and
how to resolve it.
MPI-78f7914fff02d47d135676e251bd21117743f2b8/message-exchange/exchange.F90 0000664 0000000 0000000 00000001306 13315401410 0024112 0 ustar 00root root 0000000 0000000 program exchange
use mpi
implicit none
integer, parameter :: size = 100
integer :: rc, myid, ntasks, count
integer :: status(MPI_STATUS_SIZE)
integer :: message(size)
integer :: receiveBuffer(size)
call mpi_init(rc)
call mpi_comm_rank(MPI_COMM_WORLD, myid, rc)
call mpi_comm_size(MPI_COMM_WORLD, ntasks, rc)
message = myid
! TODO: Implement sending and receiving as defined in the assignment
if ( myid == 0 ) then
write(*,'(A10,I3,A10,I3)') 'Rank: ', myid, &
' received ', receiveBuffer(1)
else if (myid == 1) then
write(*,'(A10,I3,A10,I3)') 'Rank: ', myid, &
' received ', receiveBuffer(1)
end if
call mpi_finalize(rc)
end program exchange
MPI-78f7914fff02d47d135676e251bd21117743f2b8/message-exchange/exchange.c 0000664 0000000 0000000 00000001550 13315401410 0023777 0 ustar 00root root 0000000 0000000 #include
#include
#include
int main(int argc, char *argv[])
{
int i, myid, ntasks;
int size = 100;
int *message;
int *receiveBuffer;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &ntasks);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
/* Allocate message */
message = malloc(sizeof(int) * size);
receiveBuffer = malloc(sizeof(int) * size);
/* Initialize message */
for (i = 0; i < size; i++) {
message[i] = myid;
}
/* TODO: */
/* Send and receive messages as defined in exercise */
if (myid == 0) {
printf("Rank %i received %i\n", myid, receiveBuffer[0]);
} else if (myid == 1) {
printf("Rank %i received %i\n", myid, receiveBuffer[0]);
}
free(message);
free(receiveBuffer);
MPI_Finalize();
return 0;
}
MPI-78f7914fff02d47d135676e251bd21117743f2b8/message-exchange/exchange.py 0000664 0000000 0000000 00000001207 13315401410 0024204 0 ustar 00root root 0000000 0000000 from __future__ import print_function
from mpi4py import MPI
import numpy
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
# Simple message exchange using numpy arrays
n = 100000
data = numpy.zeros(n, int) + rank
buff = numpy.empty(n, int)
# TODO:
# Send and receive messages as defined in exercise
if rank == 0:
elif rank == 1:
print("Rank {0} received an array filled with {1}s.".format(rank, buff[0]))
# Simple message exchange of Python objects
meta = {'rank': rank}
# TODO:
# Send and receive messages as defined in exercise
if rank == 0:
elif rank == 1:
print("Rank {0} received a message from rank {1}.".format(rank, msg['rank']))
MPI-78f7914fff02d47d135676e251bd21117743f2b8/message-exchange/solution/ 0000775 0000000 0000000 00000000000 13315401410 0023724 5 ustar 00root root 0000000 0000000 MPI-78f7914fff02d47d135676e251bd21117743f2b8/message-exchange/solution/exchange.F90 0000664 0000000 0000000 00000002332 13315401410 0025766 0 ustar 00root root 0000000 0000000 program exchange
use mpi
implicit none
integer, parameter :: size = 100000
integer :: rc, myid, ntasks, count
integer :: status(MPI_STATUS_SIZE)
integer :: message(size)
integer :: receiveBuffer(size)
call mpi_init(rc)
call mpi_comm_rank(MPI_COMM_WORLD, myid, rc)
call mpi_comm_size(MPI_COMM_WORLD, ntasks, rc)
message = myid
! Send and receive as defined in the assignment
if ( myid == 0 ) then
call mpi_send(message, size, MPI_INTEGER, 1, &
1, MPI_COMM_WORLD, rc)
call mpi_recv(receiveBuffer, size, MPI_INTEGER, 1, &
2, MPI_COMM_WORLD, status, rc)
write(*,'(A10,I3,A10,I3)') 'Rank: ', myid, &
' received ', receiveBuffer(1)
else if (myid == 1) then
! One MPI tasks needs to start with send and the other one with
! receive, otherwise the program dead locks with large message
! sizes in most MPI implementations
call mpi_recv(receiveBuffer, size, MPI_INTEGER, 0, &
1, MPI_COMM_WORLD, status, rc)
call mpi_send(message, size, MPI_INTEGER, 0, &
2, MPI_COMM_WORLD, rc)
write(*,'(A10,I3,A10,I3)') 'Rank: ', myid, &
' received ', receiveBuffer(1)
end if
call mpi_finalize(rc)
end program exchange
MPI-78f7914fff02d47d135676e251bd21117743f2b8/message-exchange/solution/exchange.c 0000664 0000000 0000000 00000002556 13315401410 0025662 0 ustar 00root root 0000000 0000000 #include
#include
#include
int main(int argc, char *argv[])
{
int i, myid, ntasks;
int size = 100000;
int *message;
int *receiveBuffer;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &ntasks);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
/* Allocate message */
message = malloc(sizeof(int) * size);
receiveBuffer = malloc(sizeof(int) * size);
/* Initialize message */
for (i = 0; i < size; i++) {
message[i] = myid;
}
/* Send and receive messages as defined in exercise */
if (myid == 0) {
MPI_Send(message, size, MPI_INT, 1, 1, MPI_COMM_WORLD);
MPI_Recv(receiveBuffer, size, MPI_INT, 1, 2, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
printf("Rank %i received %i\n", myid, receiveBuffer[0]);
} else if (myid == 1) {
/* One MPI tasks needs to start with send and the other one with
* receive, otherwise the program dead locks with large message
* sizes in most MPI implementations */
MPI_Recv(receiveBuffer, size, MPI_INT, 0, 1, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
MPI_Send(message, size, MPI_INT, 0, 2, MPI_COMM_WORLD);
printf("Rank %i received %i\n", myid, receiveBuffer[0]);
}
free(message);
free(receiveBuffer);
MPI_Finalize();
return 0;
}
MPI-78f7914fff02d47d135676e251bd21117743f2b8/message-exchange/solution/exchange.py 0000664 0000000 0000000 00000001620 13315401410 0026057 0 ustar 00root root 0000000 0000000 from __future__ import print_function
from mpi4py import MPI
import numpy
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
# Simple message exchange
meta = {'rank': rank}
if rank == 0:
comm.send(meta, dest=1)
msg = comm.recv(source=1)
elif rank == 1:
msg = comm.recv(source=0)
comm.send(meta, dest=0)
print("Rank {0} received a message from rank {1}.".format(rank, msg['rank']))
# Simple message exchange using numpy arrays
n = 100000
data = numpy.zeros(n, int) + rank
buff = numpy.empty(n, int)
if rank == 0:
comm.Send(data, dest=1)
comm.Recv(buff, source=1)
elif rank == 1:
# One MPI tasks needs to start with send and the other one with
# receive, otherwise the program dead locks with large message
# sizes in most MPI implementations
comm.Recv(buff, source=0)
comm.Send(data, dest=0)
print("Rank {0} received an array filled with {1}s.".format(rank, buff[0]))