introduction to mpi - iit kanpur · introduction to mpi preeti malakar ... [source: cray...

50
Introduction to MPI Preeti Malakar [email protected] An Introductory Course on High-Performance Computing in Science and Engineering 25 th February 2019 1

Upload: others

Post on 12-Jun-2020

27 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Introduction to MPI

Preeti Malakar

[email protected]

An Introductory Course on High-Performance Computing in Science and Engineering

25th February 2019

1

Page 2: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Parallel Programming Models

Libraries MPI, TBB, Pthread, OpenMP, …

New languages Haskell, X10, Chapel, …

Extensions Coarray Fortran, UPC, Cilk, OpenCL, …

• Shared memory

– OpenMP, Pthreads, …

• Distributed memory

– MPI, UPC, …

• Hybrid

– MPI + OpenMP

2

Page 3: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Hardware and Network Model

Memory

• Interconnected systems• Distributed memory• NO centralized server/master

3

host1 host2 host3 host4

Core

Persistent storage

Page 4: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Message Passing Interface (MPI)

• Standard for message passing in a distributed memory environment

• Efforts began in 1991 by Jack Dongarra, Tony Hey, and David W. Walker

• MPI Forum

– Version 1.0: 1994

– Version 2.0: 1997

– Version 3.0: 2012

4

Page 5: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI Implementations

• MPICH (ANL)

• MVAPICH (OSU)

• Intel MPI

• OpenMPI

5

Page 6: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI Processes

process process process process

Memory

6

host1 host2 host3 host4

Core

Persistent storage

Page 7: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI Internals

• Start and stop processes in a scalable way

• Setup communication channels for parallel processes

• Provide system-specific information to processes

Process Manager

7

• Schedule MPI jobs on a cluster/supercomputer

• Allocate required number of nodes– Two jobs generally do not run on the same core

• Enforce other policies (queuing etc.)

Job scheduler

Page 8: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Communication Channels

• Sockets for network I/O

• MPI handles communications, progress etc.

Reference: Design and Evaluation of Nemesis, a Scalable, Low-Latency, Message-Passing Communication Subsystem by Buntinas et al. 8

Page 9: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Message Passing Paradigm

• Message sends and receives

• Explicit communication

Communication types

• Blocking

• Non-blocking

9

Page 10: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Getting Started

Function names: MPI_*

Page 11: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Initialization and Finalization

MPI_Init

• gather information about the parallel job

• set up internal library state

• prepare for communication

MPI_Finalize

• cleanup

11

Page 12: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI_COMM_WORLD

12

Page 13: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Communication Scope

13

Communicator (communication handle)

• Defines the scope

• Specifies communication context

Process • Belongs to a group• Identified by a rank within a group

Identification• MPI_Comm_size – total number of processes in communicator• MPI_Comm_rank – rank in the communicator

Page 14: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI_COMM_WORLD

2

4

3

1

0

14

Process identified by rank/id

Page 15: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Getting Started

Rank of a process

Total number of processes

Page 16: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI Message

• Data and header/envelope

• Typically, MPI communications send/receive messages

16

Source: Origin of message

Destination: Receiver of message

Communicator

Tag (0:MPI_TAG_UB)

Message Envelope

Page 17: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI Communication Types

Point-to-point Collective

Page 18: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Point-to-point Communication

• MPI_Send

• MPI_Recv

SENDER

RECEIVER

int MPI_Send (const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)

int MPI_Recv (void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)

Tags should match

Blocking send and receive

Page 19: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI_Datatype

• MPI_BYTE

• MPI_CHAR

• MPI_INT

• MPI_FLOAT

• MPI_DOUBLE

19

Page 20: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Example 1

20

MPI_Comm_rank (MPI_COMM_WORLD, &myrank);

// Sender processif (myrank == 0) /* code for process 0 */{strcpy (message,"Hello, there");MPI_Send (message, strlen(message)+1, MPI_CHAR, 1, 99,

MPI_COMM_WORLD);}

// Receiver processelse if (myrank == 1) /* code for process 1 */{MPI_Recv (message, 20, MPI_CHAR, 0, 99, MPI_COMM_WORLD, &status);printf ("received :%s\n", message);

}

Message tag

Message tag

Page 21: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI_Status

• Source rank

• Message tag

• Message length

– MPI_Get_count

21

Page 22: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI_ANY_*

• MPI_ANY_SOURCE

– Receiver may specify wildcard value for source

• MPI_ANY_TAG

– Receiver may specify wildcard value for tag

22

Page 23: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Example 2

23

MPI_Comm_rank (MPI_COMM_WORLD, &myrank);

// Sender processif (myrank == 0) /* code for process 0 */{strcpy (message,"Hello, there");MPI_Send (message, strlen(message)+1, MPI_CHAR, 1, 99,

MPI_COMM_WORLD);}

// Receiver processelse if (myrank == 1) /* code for process 1 */{MPI_Recv (message, 20, MPI_CHAR, MPI_ANY_SOURCE, 99,

MPI_COMM_WORLD, &status);printf ("received :%s\n", message);

}

Page 24: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI_Send (Blocking)

• Does not return until buffer can be reused

• Message buffering

• Implementation-dependent

• Standard communication mode

SENDER

RECEIVER

24

Page 25: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Buffering

[Source: Cray presentation] 25

Page 26: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Safety

26

0 1

MPI_Send

MPI_Send

MPI_Recv

MPI_RecvSafe

MPI_Send

MPI_Recv

MPI_Send

MPI_RecvUnsafe

MPI_Send

MPI_Recv

MPI_Recv

MPI_SendSafe

MPI_Recv

MPI_Send

MPI_Recv

MPI_SendUnsafe

Page 27: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Message Protocols

• Short

– Message sent with envelope/header

• Eager

– Send completes without acknowledgement from destination

– Small messages – typically 128 KB (at least in MPICH)

– MPIR_CVAR_CH3_EAGER_MAX_MSG_SIZE (check mpivars)

• Rendezvous

– Requires an acknowledgement from a matching receive

– Large messages

27

Page 28: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Other Send Modes

• MPI_Bsend Buffered

– May complete before matching receive is posted

• MPI_Ssend Synchronous

– Completes only if a matching receive is posted

• MPI_Rsend Ready

– Started only if a matching receive is posted

28

Page 29: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Non-blocking Point-to-Point

• MPI_Isend (buf, count, datatype, dest, tag, comm, request)

• MPI_Irecv (buf, count, datatype, source, tag, comm, request)

• MPI_Wait (request, status)

29

0 1

MPI_Isend

MPI_Recv

MPI_Isend

MPI_RecvSafe

Page 30: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Computation Communication Overlap

30

0 1

MPI_Isend

MPI_Recv

MPI_Wait

compute

compute

compute

compute

compute

Time

Page 31: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Collective Communications

• Must be called by all processes that are part of the communicator

Types

• Synchronization (MPI_Barrier)

• Global communication (MPI_Bcast, MPI_Gather, …)

• Global reduction (MPI_Reduce, …)

31

Page 32: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Barrier

• Synchronization across all group members

• Collective call

• Blocks until all processes have entered the call

• MPI_Barrier (comm)

32

Page 33: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Broadcast

• Root process sends message to all processes

• Any process can be root process but has to be the same in all processes

• int MPI_Bcast (buffer, count, datatype, root, comm)

• Number of elements in buffer – count

• buffer – Input or output?

Q: Can you use point-to-point communication

for the same?

33

X X

X

X

X

X

X

X

X

Page 34: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Example 3

34

int rank, size, color;MPI_Status status;

MPI_Init (&argc, &argv);MPI_Comm_rank (MPI_COMM_WORLD, &rank);MPI_Comm_size (MPI_COMM_WORLD, &size);

color = rank + 2;int oldcolor = color;MPI_Bcast (&color, 1, MPI_INT, 0, MPI_COMM_WORLD);

printf ("%d: %d color changed to %d\n", rank, oldcolor, color);

Page 35: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Gather

• Gathers values from all processes to a root process

• int MPI_Gather (sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm)

• Arguments recv* not relevant on non-root processes

35

A0 A1 A2

A0

A1

A2

DATA

PR

OC

ESSE

S

Page 36: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Example 4

36

MPI_Comm_rank (MPI_COMM_WORLD, &rank);MPI_Comm_size (MPI_COMM_WORLD, &size);

color = rank + 2;

int colors[size];MPI_Gather (&color, 1, MPI_INT, colors, 1, MPI_INT, 0,

MPI_COMM_WORLD);

if (rank == 0)for (i=0; i<size; i++)printf ("color from %d = %d\n", i, colors[i]);

Page 37: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Scatter

• Scatters values to all processes from a root process

• int MPI_Scatter (sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm)

• Arguments send* not relevant on non-root processes

• Output parameter – recvbuf

37

A0 A1 A2

A0

A1

A2

DATA

PR

OC

ESSE

S

Page 38: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Allgather

• All processes gather values from all processes

• int MPI_Allgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm)

38

A0 A1 A2

A0 A1 A2

A0 A1 A2

A0

A1

A2

DATA

PR

OC

ESSE

S

Page 39: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Reduce

• MPI_Reduce (inbuf, outbuf, count, datatype, op, root, comm)

• Combines element in inbuf of each process

• Combined value in outbuf of root

• op: MIN, MAX, SUM, PROD, …

39

0 1 2 3 4 5 6 2 1 2 3 2 5 2 0 1 1 0 1 1 0

2 1 2 3 4 5 6 MAX at root

Page 40: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Allreduce

• MPI_Allreduce (inbuf, outbuf, count, datatype, op, comm)

• op: MIN, MAX, SUM, PROD, …

• Combines element in inbuf of each process

• Combined value in outbuf of each process

40

0 1 2 3 4 5 6 2 1 2 3 2 5 2 0 1 1 0 1 1 0

2 1 2 3 4 5 6

MAX

2 1 2 3 4 5 62 1 2 3 4 5 6

Page 41: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Sub-communicator

- Logical subset- Different contexts

41

Page 42: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI_COMM_SPLIT

MPI_Comm_split (MPI_Comm oldcomm, intcolor, int key, MPI_Comm *newcomm)

• Collective call

• Logically divides based on color

– Same color processes form a group

– Some processes may not be part of newcomm(MPI_UNDEFINED)

• Rank assignment based on key

42

Page 43: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Logical subsets of processes

1

6

3

2

8

12

510

11

15

14

7

1316

17

19

4

0

18

9

How do you assign one color to odd processes and another color to even processes ?color = rank % 2

0 02 14 2…

1 03 15 2…

43

Page 44: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

MPI ProgrammingHands-on

Page 45: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

How to run an MPI program on a cluster?

MPI process MPI process MPI process MPI process

45

MPI process MPI process MPI process MPI process

4 nodes, ppn=2

mpiexec –n <number of processes> -f <hostfile> ./exe

<hostfile>

host1:2host2:2host3:2…

Page 46: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

How to run an MPI program on a managed cluster/supercomputer?

MPI process MPI process MPI process MPI process

46

MPI process MPI process MPI process MPI process

4 nodes, ppn=2

Execution on HPC2010: qsub sub.sh

Page 47: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Practice Examples

• egN directory (N=1,2,3,4)

– egN.c

• Compile

– source /opt/software/intel/initpaths intel64

– make

• Execute

– qsub sub.sh

47

Page 48: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Your Code

• Each sub-directory (a1, a2, a3) has

– sub.sh [Required number of cores mentioned]

– Makefile

– .c

– Edit the .c [Look for “WRITE YOUR CODE HERE”]

48

Page 49: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Assignments

1. Even processes send their data to odd processes

2. Element-wise sum of distributed arrays

3. Sum of array elements of 2 large arrays– Make two groups of processes {0,2,4,6} and {1,3,5,7}

– The 0th process of each group should distribute its array to the other group members (equal division)

– All processes sum up their individual array chunks

49

Page 50: Introduction to MPI - IIT Kanpur · Introduction to MPI Preeti Malakar ... [Source: Cray presentation] 25. Safety 26 0 1 MPI_Send MPI_Send MPI_Recv MPI_Recv Safe MPI_Send MPI_Recv

Reference Material

• Marc Snir, Steve W. Otto, Steven Huss-Lederman, David W. Walker and Jack Dongarra, MPI - The Complete Reference, Second Edition, Volume 1, The MPI Core.

• William Gropp, Ewing Lusk, Anthony Skjellum, Using MPI : portable parallel programming with the message-passing interface, 3rd Ed., Cambridge MIT Press, 2014.

50