Skip to content
from __future__ import print_function
from mpi4py import MPI
import numpy
from sys import stdout
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
assert size == 4, 'Number of MPI tasks has to be 4.'
data = numpy.arange(8) + rank*8
if rank == 0:
print('Broadcast:')
# Simple broadcast
comm.Bcast(data, root=0)
print(' Task {0}: {1}'.format(rank, data))
from __future__ import print_function
from mpi4py import MPI
import numpy
from sys import stdout
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
assert size == 4, 'Number of MPI tasks has to be 4.'
data = numpy.arange(8) + rank*8
buff = numpy.zeros(8, int)
buff[:] = -1
# ... wait for every rank to finish ...
stdout.flush()
comm.barrier()
if rank == 0:
print('')
print('-' * 32)
print('')
print('Data vectors:')
print(' Task {0}: {1}'.format(rank, data))
stdout.flush()
comm.barrier()
if rank == 0:
print('')
print('Gatherv:')
# Gatherv
counts = (1, 1, 2, 4)
offsets = (0, 1, 2, 4)
comm.Gatherv([data, counts[rank], MPI.LONG], [buff, counts, offsets, MPI.LONG],
root=0)
print(' Task {0}: {1}'.format(rank, buff))
from __future__ import print_function
from mpi4py import MPI
import numpy
from sys import stdout
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
assert size == 4, 'Number of MPI tasks has to be 4.'
data = numpy.arange(8) + rank*8
buff = numpy.zeros(8, int)
buff[:] = -1
# ... wait for every rank to finish ...
stdout.flush()
comm.barrier()
if rank == 0:
print('')
print('-' * 32)
print('')
print('Data vectors:')
print(' Task {0}: {1}'.format(rank, data))
stdout.flush()
comm.barrier()
if rank == 0:
print('')
print('Scatter:')
# Scatter one vector
comm.Scatter(data, buff[:2], root=0)
print(' Task {0}: {1}'.format(rank, buff))
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
<http://www.gnu.org/licenses/>.
## Using custom datatypes
Write a program that sends the highlighted elements of a 2D array
using user defined datatypes from one MPI task to another. Note the
different assignments for C and Fortran, and remember that C stores
arrays in a row-major order and Fortran in a column-major order. You can
start from skeleton codes in [C](./c), [Fortran](./fortran) or
[Python](./python). For Python use the C-patterns in a) and b) (`Note`: no
Python solutions are provided for c) and d) )
a)
![](img/vector.png)
b)
![](img/indexed.png)
c) Write a program that sends an array of structures (derived types in
Fortran) between two tasks. Implement a user-defined datatype that can
be used for sending the structured data and verify that the
communication is performed successfully. Check the size and true
extent of your type. A skeleton code is provided in
[c/struct_type.c](c/struct_type.c) or
[fortran/struct_type.F90](fortran/struct_type.F90).
d) Implement the sending of structured data also by sending just a
stream of bytes (type `MPI_BYTE`). Verify correctness and compare the
performance of these two approaches.
#include <stdio.h>
#include <mpi.h>
int main(int argc, char **argv)
{
int rank;
int array[8][8];
//TODO: Declare a variable storing the MPI datatype
int i, j;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// Initialize arrays
if (rank == 0) {
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
array[i][j] = (i + 1) * 10 + j + 1;
}
}
} else {
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
array[i][j] = 0;
}
}
}
if (rank == 0) {
printf("Data in rank 0\n");
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
printf("%3d", array[i][j]);
}
printf("\n");
}
}
//TODO: Create datatype that describes one column. Use MPI_Type_vector.
//TODO: Send first column of matrix form rank 0 to rank 1
//TODO: free datatype
// Print out the result on rank 1
// The application is correct if the first column has the values of rank 0
if (rank == 1) {
printf("Received data\n");
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
printf("%3d", array[i][j]);
}
printf("\n");
}
}
MPI_Finalize();
return 0;
}
#include <stdio.h>
#include <mpi.h>
int main(int argc, char **argv)
{
int rank;
int array[8][8];
MPI_Datatype columntype;
int i, j;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// Initialize arrays
if (rank == 0) {
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
array[i][j] = (i + 1) * 10 + j + 1;
}
}
} else {
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
array[i][j] = 0;
}
}
}
if (rank == 0) {
printf("Data in rank 0\n");
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
printf("%3d", array[i][j]);
}
printf("\n");
}
}
//TODO: Create datatype that describes one column. Use MPI_Type_vector.
// Create datatype
MPI_Type_vector(8, 1, 8, MPI_INT, &columntype);
MPI_Type_commit(&columntype);
// Send first column of matrix
if (rank == 0) {
MPI_Send(&array[0][1], 1, columntype, 1, 1, MPI_COMM_WORLD);
} else if (rank == 1) {
MPI_Recv(&array[0][1], 1, columntype, 0, 1, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
}
// Print out the result
if (rank == 1) {
printf("Received data\n");
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
printf("%3d", array[i][j]);
}
printf("\n");
}
}
MPI_Type_free(&columntype);
MPI_Finalize();
return 0;
}
#include <stdio.h>
#include <mpi.h>
int main(int argc, char **argv)
{
int rank;
int array[8][8];
MPI_Datatype indexedtype;
int displs[4];
int counts[4];
int i, j;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// Initialize arrays
if (rank == 0) {
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
array[i][j] = (i + 1) * 10 + j + 1;
}
}
} else {
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
array[i][j] = 0;
}
}
}
if (rank == 0) {
printf("Data in rank 0\n");
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
printf("%3d", array[i][j]);
}
printf("\n");
}
}
// Create datatype
for (i = 0; i < 4; i++) {
counts[i] = i + 1;
displs[i] = i + 2 * i * 8;
}
MPI_Type_indexed(4, counts, displs, MPI_INT, &indexedtype);
MPI_Type_commit(&indexedtype);
// Send first indexed of matrix
if (rank == 0) {
MPI_Send(array, 1, indexedtype, 1, 1, MPI_COMM_WORLD);
} else if (rank == 1) {
MPI_Recv(array, 1, indexedtype, 0, 1, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
}
// Print out the result on rank 1
// The application is correct if the first column has the values of rank 0
if (rank == 1) {
printf("Received data\n");
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
printf("%3d", array[i][j]);
}
printf("\n");
}
}
MPI_Type_free(&indexedtype);
MPI_Finalize();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
int main(int argc, char *argv[])
{
int n = 1000, cnt = 3, reps = 10000;
particle particles[n];
int i, j, myid, ntasks, blocklen[cnt];
MPI_Datatype particletype, temptype, types[cnt];
MPI_Aint disp[cnt], dist[2], lb, extent;
double t1, t2;
typedef struct {
float coords[3];
int charge;
char label[2];
} particle;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
/* fill in some values for the particles */
if (myid == 0) {
for (i = 0; i < 1000; i++) {
for (j = 0; j < 3; j++) {
particles[i].coords[j] = (float)rand() / (float)RAND_MAX * 10.0;
}
particles[i].charge = 54;
strcpy(particles[i].label, "Xe");
}
}
/* TODO: define the datatype for the struct particle */
types[0] = MPI_FLOAT;
types[1] = MPI_INT;
types[2] = MPI_CHAR;
blocklen[0] = 3;
blocklen[1] = 1;
blocklen[2] = 2;
MPI_Get_address(&particles[0].coords, &disp[0]);
MPI_Get_address(&particles[0].charge, &disp[1]);
MPI_Get_address(&particles[0].label, &disp[2]);
disp[2] -= disp[0];
disp[1] -= disp[0];
disp[0] = 0;
MPI_Type_create_struct(cnt, blocklen, disp, types, &particletype);
MPI_Type_commit(&particletype);
/* TODO: check extent (not really necessary on most platforms) */
MPI_Type_get_extent(particletype, &lb, &extent);
MPI_Get_address(&particles[0], &dist[0]);
MPI_Get_address(&particles[1], &dist[1]);
if (extent != (dist[1] - dist[0])) {
temptype = particletype;
lb = 0;
extent = disp[1] - disp[0];
MPI_Type_create_resized(temptype, lb, extent, &particletype);
MPI_Type_commit(&particletype);
MPI_Type_free(&temptype);
}
/* communicate using the created particletype */
t1 = MPI_Wtime();
if (myid == 0) {
for (i = 0; i < reps; i++) {
MPI_Send(particles, n, particletype, 1, i, MPI_COMM_WORLD);
}
} else if (myid == 1) {
for (i = 0; i < reps; i++) {
MPI_Recv(particles, n, particletype, 0, i, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
}
}
t2 = MPI_Wtime();
printf("Time: %i, %e \n", myid, (t2 - t1) / (double)reps);
printf("Check: %i: %s %f %f %f \n", myid, particles[n - 1].label,
particles[n - 1].coords[0], particles[n - 1].coords[1],
particles[n - 1].coords[2]);
MPI_Type_free(&particletype);
MPI_Finalize();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
int main(int argc, char *argv[])
{
int n = 1000, cnt = 3, reps = 10000;
particle particles[n];
int i, j, myid, ntasks;
MPI_Aint lb0, lb1, extent;
double t1, t2;
typedef struct {
float coords[3];
int charge;
char label[2];
} particle;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
/* fill in some values for the particles */
if (myid == 0) {
for (i = 0; i < 1000; i++) {
for (j = 0; j < 3; j++) {
particles[i].coords[j] = (float)rand() / (float)RAND_MAX * 10.0;
}
particles[i].charge = 54;
strcpy(particles[i].label, "Xe");
}
}
/* TODO: determine the true extent of one particle struct */
MPI_Get_address(&particles[0], &lb0);
MPI_Get_address(&particles[1], &lb1);
extent = lb1 - lb0;
/* TODO: send and receive using the MPI_BYTE datatype */
t1 = MPI_Wtime();
if (myid == 0) {
for (i = 0; i < reps; i++) {
MPI_Send(particles, n * extent, MPI_BYTE, 1, i, MPI_COMM_WORLD);
}
} else if (myid == 1) {
for (i = 0; i < reps; i++) {
MPI_Recv(particles, n * extent, MPI_BYTE, 0, i, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
}
}
t2 = MPI_Wtime();
printf("Time: %i, %e \n", myid, (t2 - t1) / (double)reps);
printf("Check: %i: %s %f %f %f \n", myid, particles[n - 1].label,
particles[n - 1].coords[0], particles[n - 1].coords[1],
particles[n - 1].coords[2]);
MPI_Finalize();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
int main(int argc, char *argv[])
{
int n = 1000, cnt = 3, reps = 10000;
particle particles[n];
int i, j, myid, ntasks, blocklen[cnt];
MPI_Datatype particletype, temptype;
MPI_Aint disp[cnt], dist[2], lb, extent;
double t1, t2;
typedef struct {
float coords[3];
int charge;
char label[2];
} particle;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
/* fill in some values for the particles */
if (myid == 0) {
for (i = 0; i < 1000; i++) {
for (j = 0; j < 3; j++) {
particles[i].coords[j] = (float)rand() / (float)RAND_MAX * 10.0;
}
particles[i].charge = 54;
strcpy(particles[i].label, "Xe");
}
}
/* TODO (c): define the datatype for the struct particle using MPI_Type_create_struct
You can use MPI_Get_address to compute offsets.
*/
/* TODO (c): check extent (not really necessary on most platforms) That is,
* check that extent is identical to the distance between two consequtive
* structs in an array
* Tip, use MPI_Type_get_extent and MPI_Get_address
*/
if (extent != (dist[1] - dist[0])) {
/*TODO (c), resize particle type to correct extent */
}
/* communicate using the created particletype */
t1 = MPI_Wtime();
if (myid == 0) {
for (i = 0; i < reps; i++) {
MPI_Send(particles, n, particletype, 1, i, MPI_COMM_WORLD);
}
} else if (myid == 1) {
for (i = 0; i < reps; i++) {
MPI_Recv(particles, n, particletype, 0, i, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
}
}
t2 = MPI_Wtime();
printf("Time: %i, %e \n", myid, (t2 - t1) / (double)reps);
printf("Check: %i: %s %f %f %f \n", myid, particles[n - 1].label,
particles[n - 1].coords[0], particles[n - 1].coords[1],
particles[n - 1].coords[2]);
//TODO: Free datatype
MPI_Finalize();
return 0;
}
program datatype1
use mpi
implicit none
integer, dimension(8,8) :: array
integer :: rank, ierr
!TODO: declare variable for datatype
integer :: i, j
call mpi_init(ierr)
call mpi_comm_rank(MPI_COMM_WORLD, rank ,ierr)
! initialize arrays
if (rank == 0) then
do i=1,8
do j=1,8
array(i,j) = i*10 + j
end do
end do
else
array(:,:) = 0
end if
if (rank == 0) then
write(*,*) 'Data in rank 0'
do i=1,8
write(*,'(8I3)') array(i, :)
end do
end if
!TODO: create datatype describing one row, use mpi_type_vector
!TODO: send first row of matrix from rank 0 to 1
! Print out the result
if (rank == 1) then
write(*,*) 'Received data'
do i=1,8
write(*,'(8I3)') array(i, :)
end do
end if
!TODO free datatype
call mpi_finalize(ierr)
end program datatype1
program datatype1
use mpi
implicit none
integer, dimension(8,8) :: array
integer :: rank, ierr
integer :: rowtype
integer :: i, j
call mpi_init(ierr)
call mpi_comm_rank(MPI_COMM_WORLD, rank ,ierr)
! initialize arrays
if (rank == 0) then
do i=1,8
do j=1,8
array(i,j) = i*10 + j
end do
end do
else
array(:,:) = 0
end if
if (rank == 0) then
write(*,*) 'Data in rank 0'
do i=1,8
write(*,'(8I3)') array(i, :)
end do
end if
! create datatype
call mpi_type_vector(8, 1, 8, MPI_INTEGER, rowtype, ierr)
call mpi_type_commit(rowtype, ierr)
! send first row of matrix
if (rank == 0) then
call mpi_send(array(2, 1), 1, rowtype, 1, 1, MPI_COMM_WORLD, ierr)
else if (rank == 1) then
call mpi_recv(array(2, 1), 1, rowtype, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE, &
ierr)
end if
! Print out the result
if (rank == 1) then
write(*,*) 'Received data'
do i=1,8
write(*,'(8I3)') array(i, :)
end do
end if
call mpi_type_free(rowtype, ierr)
call mpi_finalize(ierr)
end program datatype1
program datatype1
use mpi
implicit none
integer, dimension(8,8) :: array
integer :: rank, ierr
integer :: indexedtype
integer, dimension(4) :: counts, displs
integer :: i, j
call mpi_init(ierr)
call mpi_comm_rank(MPI_COMM_WORLD, rank ,ierr)
! initialize arrays
if (rank == 0) then
do i=1,8
do j=1,8
array(i,j) = i*10 + j
end do
end do
else
array(:,:) = 0
end if
if (rank == 0) then
write(*,*) 'Data in rank 0'
do i=1,8
write(*,'(8I3)') array(i, :)
end do
end if
do i=1,4
counts(i) = i
displs(i) = i - 1 + 2 * (i - 1) * 8
end do
! create datatype
call mpi_type_indexed(4, counts, displs, MPI_INTEGER, indexedtype, ierr)
call mpi_type_commit(indexedtype, ierr)
! send first indexed of matrix
if (rank == 0) then
call mpi_send(array, 1, indexedtype, 1, 1, MPI_COMM_WORLD, ierr)
else if (rank == 1) then
call mpi_recv(array, 1, indexedtype, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE, &
ierr)
end if
! Print out the result
if (rank == 1) then
write(*,*) 'Received data'
do i=1,8
write(*,'(8I3)') array(i, :)
end do
end if
call mpi_type_free(indexedtype, ierr)
call mpi_finalize(ierr)
end program datatype1
program datatype_struct
use mpi
implicit none
type particle
real :: coords(3)
integer :: charge
character(len=2) :: label
end type particle
integer, parameter :: n = 1000
integer :: i, ierror, myid, ntasks, tag
type(particle) :: particles(n)
integer, parameter :: cnt=3
integer:: particle_mpi_type, temp_type
integer:: types(cnt),blocklen(cnt)
integer(KIND=MPI_ADDRESS_KIND) :: disp(cnt)
integer(KIND=MPI_ADDRESS_KIND) :: lb, extent
real(8) :: t1,t2
call MPI_INIT(ierror)
call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierror)
call MPI_COMM_SIZE(MPI_COMM_WORLD, ntasks, ierror)
! insert some data for the particle struct
if(myid == 0) then
do i = 1, n
call random_number(particles(i)%coords)
particles(i)%charge = 54
particles(i)%label = 'Xe'
end do
end if
! TODO: define the datatype for type particle
types=(/ MPI_REAL, MPI_INTEGER, MPI_CHARACTER /)
blocklen=(/ 3,1,2 /)
call MPI_GET_ADDRESS(particles(1)%coords, disp(1), ierror)
call MPI_GET_ADDRESS(particles(1)%charge, disp(2), ierror)
call MPI_GET_ADDRESS(particles(1)%label, disp(3), ierror)
do i = cnt, 1, -1
disp(i)=disp(i)-disp(1)
end do
call MPI_TYPE_CREATE_STRUCT(cnt, blocklen, &
disp,types, particle_mpi_type,ierror)
call MPI_TYPE_COMMIT(particle_mpi_type, ierror)
! TODO: Check extent.
! (Not really neccessary on most systems.)
call MPI_TYPE_GET_EXTENT(particle_mpi_type,lb,extent,ierror)
call MPI_GET_ADDRESS(particles(1),disp(1),ierror)
call MPI_GET_ADDRESS(particles(2),disp(2),ierror)
! TODO: resize the particle_mpi_type
if(extent /= disp(2)-disp(1)) then
temp_type=particle_mpi_type
lb=0
extent=disp(2)-disp(1)
call MPI_TYPE_CREATE_RESIZED(temp_type,lb,extent,particle_mpi_type,ierror)
call MPI_TYPE_COMMIT(particle_mpi_type,ierror)
call MPI_TYPE_free(temp_type,ierror)
end if
t1=MPI_WTIME()
if(myid == 0) then
do i=1,1000
call MPI_SEND(particles, n, particle_mpi_type, 1, i, &
MPI_COMM_WORLD,ierror)
end do
else if(myid == 1) then
do i=1, 1000
call MPI_RECV(particles, n, particle_mpi_type, 0, i, &
MPI_COMM_WORLD, MPI_STATUS_IGNORE, ierror)
end do
end if
t2=MPI_WTIME()
write(*,*) "Time: ", myid, (t2-t1) / 1000d0
write(*,*) "Check:", myid, particles(n)%coords(1)
call MPI_TYPE_free(particle_mpi_type, ierror)
call MPI_FINALIZE(ierror)
end program datatype_struct
program datatype_struct
use mpi
implicit none
type particle
real :: coords(3)
integer :: charge
character(len=2) :: label
end type particle
integer, parameter :: n = 1000
integer :: i, ierror, myid, ntasks, tag
type(particle) :: particles(n)
integer, parameter :: cnt=3
integer:: particle_mpi_type, temp_type
integer:: types(cnt),blocklen(cnt)
integer(KIND=MPI_ADDRESS_KIND) :: disp(cnt)
integer(KIND=MPI_ADDRESS_KIND) :: lb1, lb2, extent
real(8) :: t1,t2
call MPI_INIT(ierror)
call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierror)
call MPI_COMM_SIZE(MPI_COMM_WORLD, ntasks, ierror)
! insert some data for the particle struct
if(myid == 0) then
do i = 1, n
call random_number(particles(i)%coords)
particles(i)%charge = 54
particles(i)%label = 'Xe'
end do
end if
! TODO: Determine the true extent of one particle struct
call MPI_GET_ADDRESS(particles(1),lb1,ierror)
call MPI_GET_ADDRESS(particles(2),lb2,ierror)
extent = lb2 - lb1
t1=MPI_WTIME()
! TODO: send and receive using the MPI_BYTE datatype
if(myid == 0) then
do i=1,1000
call MPI_SEND(particles, n*extent, MPI_BYTE, 1, i, &
MPI_COMM_WORLD,ierror)
end do
else if(myid == 1) then
do i=1, 1000
call MPI_RECV(particles, n*extent, MPI_BYTE, 0, i, &
MPI_COMM_WORLD, MPI_STATUS_IGNORE, ierror)
end do
end if
t2=MPI_WTIME()
write(*,*) "Time: ", myid, (t2-t1) / 1000d0
write(*,*) "Check:", myid, particles(n)%coords(1)
call MPI_FINALIZE(ierror)
end program datatype_struct
program datatype_struct
use mpi
implicit none
type particle
real :: coords(3)
integer :: charge
character(len=2) :: label
end type particle
integer, parameter :: n = 1000
integer :: i, ierror, myid, ntasks, tag
type(particle) :: particles(n)
integer, parameter :: cnt=3
integer:: particle_mpi_type, temp_type
integer:: types(cnt),blocklen(cnt)
integer(KIND=MPI_ADDRESS_KIND) :: disp(cnt)
integer(KIND=MPI_ADDRESS_KIND) :: lb, extent
real(8) :: t1,t2
call MPI_INIT(ierror)
call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierror)
call MPI_COMM_SIZE(MPI_COMM_WORLD, ntasks, ierror)
! insert some data for the particle struct
if(myid == 0) then
do i = 1, n
call random_number(particles(i)%coords)
particles(i)%charge = 54
particles(i)%label = 'Xe'
end do
end if
! TODO: define the datatype for type particle
! TODO: Check extent.
! (Not really neccessary on most systems.)
! TODO: resize the particle_mpi_type if needed
if(extent /= disp(2)-disp(1)) then
! TODO: resize the particle_mpi_type if needed
end if
t1=MPI_WTIME()
if(myid == 0) then
do i=1,1000
call MPI_SEND(particles, n, particle_mpi_type, 1, i, &
MPI_COMM_WORLD,ierror)
end do
else if(myid == 1) then
do i=1, 1000
call MPI_RECV(particles, n, particle_mpi_type, 0, i, &
MPI_COMM_WORLD, MPI_STATUS_IGNORE, ierror)
end do
end if
t2=MPI_WTIME()
write(*,*) "Time: ", myid, (t2-t1) / 1000d0
write(*,*) "Check:", myid, particles(n)%coords(1)
call MPI_TYPE_free(particle_mpi_type, ierror)
call MPI_FINALIZE(ierror)
end program datatype_struct
from __future__ import print_function
from mpi4py import MPI
import numpy as np
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
if size != 2:
raise RuntimeError("Please run with two MPI tasks")
data = np.zeros((8,8), int)
if rank == 0:
for i in range(8):
data[i,:] = np.arange(1, 9) + (i+1) * 10
if rank == 0:
print("Original data:")
print(data)
# TODO Create the custom datatype
# Note: Python integers are 64 bits
# TODO: communicate with the datatype
# Note: mpi4py requires that the input and output buffers are contiguous
# in memory. Thus, in order to send/receive from second column we need
# to create a contiguous view starting from the second element in memory
# which can be accomplished by flattening the array into 1d with ravel
if rank == 1:
print("Received data:")
print(data)