You are on page 1of 30

C bn lp trnh song song MPI cho C/C++

ng Nguyn Phng
dnphuong1984@gmail.com
Ngy 23 thng 11 nm 2013
Mc lc
1 M u 2
2 MPI 3
2.1 Gii thiu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Ci t MPICH2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.3 Bin dch v thc thi chng trnh vi MPICH2 . . . . . . . . . . . . . . . . . . . 4
3 Cu trc c bn ca mt chng trnh MPI 5
3.1 Cu trc chng trnh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.2 Cc khi nim c bn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.3 V d Hello world . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.4 V d truyn thng ip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4 Cc lnh MPI 13
4.1 Cc lnh qun l mi trng MPI . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.2 Cc kiu d liu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4.3 Cc c ch truyn thng ip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.4 Cc lnh truyn thng ip blocking . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.5 Cc lnh truyn thng ip non-blocking . . . . . . . . . . . . . . . . . . . . . . . 19
4.6 Cc lnh truyn thng tp th . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5 Mt s v d 23
5.1 V d tnh s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.2 V d nhn ma trn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Ti liu tham kho 29
1
ng Nguyn Phng Ti liu ni b NMTP
1 M u
Thng thng hin nay, hu ht cc chng trnh tnh ton u c thit k chy trn mt
li (single core), l cch tnh ton tun t (serial computation). c th chy c chng
trnh mt cch hiu qu trn cc h thng my tnh (cluster) hoc cc cpu a li (multi-core),
chng ta cn phi tin hnh song song ha chng trnh . u im ca vic tnh ton song
song (parallel computation) chnh l kh nng x l nhiu tc v cng mt lc. Vic lp trnh
song song c th c thc hin thng qua vic s dng cc hm th vin (vd: mpi.h) hoc cc
c tnh c tch hp trong cc chng trnh bin dch song song d liu, chng hn nh
OpenMP trong cc trnh bin dch fortran F90, F95.
Cng vic lp trnh song song bao gm vic thit k, lp trnh cc chng trnh my tnh song
song sao cho n chy c trn cc h thng my tnh song song. Hay c ngha l song song
ho cc chng trnh tun t nhm gii quyt mt vn ln hoc lm gim thi gian thc thi
hoc c hai. Lp trnh song song tp trung vo vic phn chia bi ton tng th ra thnh cc
cng vic con nh hn ri nh v cc cng vic n tng b x l (processor) v ng b
cc cng vic nhn c kt qu cui cng. Nguyn tc quan trng nht y chnh l tnh
ng thi hoc x l nhiu tc v (task) hay tin trnh (process) cng mt lc. Do , trc khi
lp trnh song song ta cn phi bit c rng bi ton c th c song song ho hay khng
(c th da trn d liu hay chc nng ca bi ton). C hai hng chnh trong vic tip cn
lp trnh song song:
Song song ho ngm nh (implicit parallelism): b bin dch hay mt vi chng trnh
khc t ng phn chia cng vic n cc b x l.
Song song ho bng tay (explicit parallelism): ngi lp trnh phi t phn chia chng
trnh ca mnh n c th c thc thi song song.
Ngoi ra trong lp trnh song song, ngi lp trnh cng cn phi tnh n yu t cn bng ti
(load balancing) trong h thng. Phi lm cho cc b x l thc hin s cng vic nh nhau,
nu c mt b x l c ti qu ln th cn phi di chuyn cng vic n b x l c ti nh hn.
Mt m hnh lp trnh song song l mt tp hp cc k thut phn mm th hin cc gii
thut song song v a vo ng dng trong h thng song song. M hnh ny bao gm cc ng
dng, ngn ng, b bin dch, th vin, h thng truyn thng v vo/ra song song. Trong thc
t, cha c mt my tnh song song no cng nh cch phn chia cng vic cho cc b x l
no c th p dng hiu qu cho mi bi ton. Do , ngi lp trnh phi la chn chnh xc
mt m hnh song song hoc pha trn gia cc m hnh vi nhau pht trin cc ng dng
song song trn mt h thng c th.
Hin nay c rt nhiu m hnh lp trnh song song nh m hnh a lung (multi-threads), truyn
thng ip (message passing), song song d liu (data parallel ), lai (hybrid),... Cc loi m hnh
ny c phn chia da theo hai tiu ch l tng tc gia cc tin trnh (process interaction)
v cch thc x l bi ton (problem decomposition). Theo tiu ch th nht, chng ta c 2 loi
m hnh song song ch yu l m hnh dng b nh chia s (shared memory) hoc truyn thng
ip (message passing). Theo tiu ch th hai, chng ta cng c hai loi m hnh l song song
ha tc v (task parallelism) v song song ha d liu (data parallelism).
Vi m hnh b nh chia s, tt c cc x l u truy cp mt d liu chung thng qua
mt vng nh dng chung.
Vi m hnh truyn thng ip th mi x l u c ring mt b nh cc b ca n, cc
x l trao i d liu vi nhau thng qua hai phng thc gi v nhn thng ip.
Song song tc v l phng thc phn chia cc tc v khc nhau n cc nt tnh ton
khac nhau, d liu c s dng bi cc tc v c th hon ton ging nhau.
2
ng Nguyn Phng Ti liu ni b NMTP
Song song d liu l phng thc phn phi d liu ti cc nt tnh ton khc nhau
c x l ng thi, cc tc v ti cc nt tnh ton c th hon ton ging nhau.
M hnh truyn thng ip l mt trong nhng m hnh c s dng rng ri nht trong
tnh ton song song hin nay. N thng c p dng cho cc h thng phn tn (distributed
system). Cc c trng ca m hnh ny l:
Cc lung (thread) s dng vng nh cc b ring ca chng trong sut qu trnh tnh
ton.
Nhiu lung c th cng s dng mt ti nguyn vt l.
Cc lung trao i d liu bng cch gi nhn cc thng ip
Vic truyn d liu thng yu cu thao tc iu phi thc hin bi mi lung. V d,
mt thao tc gi mt lung th phi ng vi mt thao tc nhn lung khc.
Ti liu ny c xy dng vi mc ch cung cp cc kin thc c bn bc u nhm tm
hiu kh nng vit mt chng trnh song song bng ngn ng lp trnh C/C++ theo c ch
trao i thng ip s dng cc th vin theo chun MPI. Mc ch l nhm ti vic thc thi
cc chng trnh C/C++ trn my tnh a li hoc h thng cm my tnh (computer cluster)
gip nng cao hiu nng tnh ton. Trong ti liu ny, th vin MPICH2 c s dng bin
dch cc chng trnh C/C++ trn h iu hnh Linux.
2 MPI
2.1 Gii thiu
M hnh truyn thng ip l mt trong nhng m hnh lu i nht v c ng dng rng
ri nht trong lp trnh song song. Hai b cng c ph bin nht cho lp trnh song song theo
m hnh ny l PVM (Parallel Virtual Machine) v MPI (Message Passing Interface). Cc b
cng c ny cung cp cc hm dng cho vic trao i thng tin gia cc tin trnh tnh ton
trong h thng my tnh song song.
MPI (Message Passing Interface) l mt chun m t cc c im v c php ca mt th vin
lp trnh song song, c a ra vo nm 1994 bi MPIF (Message Passing Interface Forum),
v c nng cp ln chun MPI-2 t nm 2001. C rt nhiu cc th vin da trn chun MPI
ny chng hn nh MPICH, OpenMPI hay LAM/MPI.
MPICH2 l mt th vin min ph bao gm cc hm theo chun MPI dng cho lp trnh song
song theo phng thc truyn thng ip, c thit k cho nhiu ngn ng lp trnh khc nhau
(C++, Fortran, Python,. . . ) v c th s dng trn nhiu loi h iu hnh (Windows, Linux,
MacOS,. . . ).
2.2 Ci t MPICH2
Gi MPICH2 c th c ci t trn tt c cc my tnh thng qua lnh sau
$ sudo aptget install mpich2
Sau khi ci t thnh cng MPICH2, ta cn phi cu hnh trc khi chy song song. Trong
trng hp phin bn c s dng l 1.2.x tr v trc th trnh qun l thc thi mc nh s
l MPD, cn t 1.3.x tr v sau th trnh qun l s l Hydra. Cch thc cu hnh dnh cho 2
trnh qun l s nh sau:
3
ng Nguyn Phng Ti liu ni b NMTP
MPD To 2 file mpd.hosts v .mpd.conf trong th mc ch (vd: /home/phuong). Trong ,
file mpd.hosts s cha tn ca cc my con trong h thng, v d nh
master
node1
node2
node3
Cn i vi file .mpd.conf, ta cn phi thit lp quyn truy cp cho file ny thng qua lnh
$ chmod 600 . mpd . conf
Sau m file v thm dng sau vo trong file
secretword=random_text_here
khi ng MPD, g lnh sau trn my ch
$ mpdboot n <N>
vi N l s my c trong h thng.
Hydra tng t nh vi MPD nhng n gin hn, ta ch cn to duy nht 1 file c tn hosts
ti th mc /home/phuong cha tn ca tt c cc my con trong h thng
master
node1
node2
node3
2.3 Bin dch v thc thi chng trnh vi MPICH2
Bin dch bin dch mt chng trnh ng dng vi MPICH2, ta c th s dng mt trong
cc trnh bin dch sau
Ngn ng Trnh bin dch
C mpicc
C++ mpicxx, mpic++, mpiCC
Fortran mpif77, mpif90, mpifort
V d nh ta mun bin dch mt chng trnh ng dng vit bng ngn ng C/C++, ta c th
g lnh sau
mpicc o helloworld helloworld . c
Trong , helloworld.c l file cha m ngun ca chng trnh, ty chnh -o cho ta xc nh
trc tn ca file ng dng c bin dch ra, trong trng hp ny l file helloworld.
Thc thi Trong trng hp phin bn MPICH2 s dng trnh qun l MPD, trc khi thc
thi chng trnh ta cn gi MPD qua lnh mpdboot nh cp n trn hoc
mpd &
Chng trnh c bin dch bng MPI c th c thc thi bng cch s dng lnh
mpirun -np <N> <tenchuongtrinh>
hoc
mpiexec -n <N> <tenchuongtrinh>
4
ng Nguyn Phng Ti liu ni b NMTP
Trong N l s tc v song song cn chy v tenchuongtrinh l tn ca chng trnh ng
dng cn thc thi.
V d:
$ mpd &
$ mpirun np 8 helloworld
3 Cu trc c bn ca mt chng trnh MPI
3.1 Cu trc chng trnh
Cu trc c bn ca mt chng trnh MPI nh sau:
Khai bo cc header, bin, prototype,...
Bt u chng trnh
. . .
<on code tun t>
. . .
Khi ng mi trng MPI
. . .
<on code cn thc hin song song>
. . .
Kt thc mi trng MPI
. . .
<on code tun t>
. . .
Kt thc chng trnh
3.2 Cc khi nim c bn
Mt chng trnh song song MPI thng cha nhiu hn mt tc v (task) hay cn gi l tin
trnh (process) thc thi. Mi tc v (tin trnh) c phn bit vi nhau bi ch s tc v (c
gi l rank hay task ID). Ch s ny l mt s nguyn t 0 n (N1) vi N l tng s tc v
MPI tham gia chy chng trnh. i vi cc chng trnh chy theo c ch master/slave th
trong h thng thng c mt tc v ch (master) iu khin cc tc v khc c gi l tc
v con (slave), tc v ch ny thng c ch s l 0 cn cc tc v con c ch s t 1 n (N1).
Tp hp ca cc tc v MPI cng chy mt chng trnh c gi l mt nhm (group). V
tp hp ca cc tc v trong cng mt nhm m c th trao i thng tin vi nhau c gi
l mt communicator. Khi bt u chng trnh, communicator m bao gm tt c cc tc v
thc thi c mc nh l MPI_COMM_WORLD.
Cc tc v trong MPI trao i vi nhau thng qua vic gi/nhn cc thng ip (message). Mi
thng ip u cha hai thnh phn bao gm d liu (data) v header, mi header bao gm:
Ch s ca tc v gi
Ch s ca tc v nhn
Nhn (tag) ca thng ip
Ch s ca communicator
5
ng Nguyn Phng Ti liu ni b NMTP
3.3 V d Hello world
bc u lm quen vi vic vit mt chng trnh MPI, ta s bt u vi mt v d n
gin, l vit chng trnh Hello world bng ngn ng C. Cc bc thc hin nh sau:
Bc u tin, ta s to mt file c tn hello.c v m file ny bng cc chng trnh son
tho vn bn dng text (vd: gedit, emacs, vim,...)
Khai bo tn chng trnh v thm header MPI
#include <stdio . h>
#i nc l ude <mpi . h>
int main ( int argc , char argv )
{
}
Cn lu rng header MPI (mpi.h) cn phi c thm vo trong file c th gi c
cc lnh MPI.
Khai bo mi trng MPI
#include <stdio . h>
#include <mpi . h>
int main ( int argc , char argv )
{
MPI_Init (&argc , &argv ) ;
}
Lnh MPI_Init khi to mi trng MPI thc hin tc v song song, lnh ny s tr
v mt gi tr nguyn trong qu trnh khi to mi trng.
Gi lnh qun l s tc v song song
#include <stdio . h>
#include <mpi . h>
int main ( int argc , char argv )
{
i nt nt as ks ;
MPI_Init (&argc , &argv ) ;
MPI_Comm_size (MPI_COMM_WORLD, &nt as ks ) ;
}
Lnh MPI_Comm_size tr v gi tr s lng tc v song song vo trong bin ntasks.
Tham s MPI_COMM_WORLD l tham s ch communicator ton cc, c gi tr l mt hng
s nguyn.
Gi lnh xc nh ch s ca tc v
#include <stdio . h>
#include <mpi . h>
int main ( int argc , char argv )
{
int ntasks , mytask ;
MPI_Init (&argc , &argv ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &ntasks ) ;
6
ng Nguyn Phng Ti liu ni b NMTP
MPI_Comm_rank (MPI_COMM_WORLD, &mytask ) ;
}
Lnh MPI_Comm_rank tr v ch s (rank) ca tc v vo trong bin mytask, ch s ny c
gi tr t 0 n ntasks-1, v c s dng nhn bit tc v khi iu khin gi/nhn
thng tin.
Thc hin lnh xut ra mn hnh
#include <stdio . h>
#include <mpi . h>
int main ( int argc , char argv )
{
int ntasks , mytask ;
MPI_Init (&argc , &argv ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &ntasks ) ;
MPI_Comm_rank ( MPI_COMM_WORLD , &mytask ) ;
pr i nt f ( " Hel l o worl d from t ask %d of %d \n" , mytask , nt as ks ) ;
}
Kt thc mi trng MPI
#include <stdio . h>
#include <mpi . h>
int main ( int argc , char argv )
{
int ntasks , mytask ;
MPI_Init (&argc , &argv ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &ntasks ) ;
MPI_Comm_rank ( MPI_COMM_WORLD , &mytask ) ;
printf ( "Hello world from task %d of %d \n" , mytask , ntasks ) ;
MPI_Finalize ( ) ;
r et ur n 0;
}
Lnh MPI_Finalize ng mi trng MPI, tuy nhin cc tc v chy song song ang c
thc thi vn c tip tc. Tt c cc lnh MPI c gi sau MPI_Finalize u khng
c hiu lc v b bo li.
Ngoi ra, ta cng c th vit li chng trnh Hello world ny theo ngn ng C++, ta s to
mt file mi hello.cc c ni dung nh sau
#include <iostream>
#include <mpi . h>
int main ( int argc , char argv )
{
int ntasks , mytask ;
MPI : : Init ( argc , argv ) ;
ntasks = MPI : : COMM_WORLD . Get_size ( ) ;
mytask = MPI : : COMM_WORLD . Get_rank ( ) ;
std : : cout << "Hello world from task " << mytask << " of " << ntasks <<
std : : endl ;
MPI : : Finalize ( ) ;
return 0;
7
ng Nguyn Phng Ti liu ni b NMTP
}
Lu rng cch thc s dng lnh MPI trong C v C++ khc nhau hai im chnh sau y:
Cc hm trong C++ c s dng vi khng gian tn (namespace) MPI.
Cc tham s (argument) c s dng trong cc hm C++ l tham chiu (reference) thay
v l con tr (pointer) nh trong cc hm C. V d nh cc tham s argc v argv ca
hm MPI_Init trong C c s dng vi du & pha trc, cn trong C++ th khng.
3.4 V d truyn thng ip
Trong v d Hello world ta lm quen vi 4 lnh c bn ca MPI. Trong thc t, rt nhiu
chng trnh song song MPI c th c xy dng ch vi 6 lnh c bn, ngoi 4 lnh va k
trn ta cn s dng thm hai lnh na l MPI_Send gi thng ip v MPI_Recv nhn
thng ip gia cc tc v vi nhau. Cu trc ca hai lnh ny trong C nh sau:
MPI_Send (&buffer,count,datatype,destination,tag,communicator)
MPI_Recv (&buffer,count,datatype,source,tag,communicator,&status)
Trong
buffer mng d liu cn chuyn/nhn
count s phn t trong mng
datatype kiu d liu (vd: MPI_INT, MPI_FLOAT,...)
destination ch s ca tc v ch (bn trong communicator)
source ch s ca tc v ngun (bn trong communicator)
tag nhn ca thng ip (dng s nguyn)
communicator tp hp cc tc v
status trng thi ca thng ip
ierror m s li
c th hiu r hn v cch s dng hai lnh ny, ta s xem v d vng lp (fixed_loop) sau.
Trong v d ny, MPI_Send c s dng gi i s vng lp hon thnh t mi tc v con
(c ch s t 1 n N1) n tc v ch (ch s l 0). Lnh MPI_Recv c gi N1 ln tc
v ch nhn N1 thng tin c gi t N1 tc v con.
Cc bc khai bo u tin cng tng t nh trong v d Hello world
#include <stdio . h>
#include <mpi . h>
int main ( int argc , char argv )
{
int i , rank , ntasks , count , start , stop , nloops , total_nloops ;
MPI_Init(&argc , &argv ) ;
MPI_Comm_rank ( MPI_COMM_WORLD , &rank ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &ntasks ) ;
}
Gi s chng ta mun thc hin vng lp 1000 ln, do s ln lp ca mi tc v s bng
1000/ntasks vi ntasks l tng s tc v. Chng ta s s dng ch s ca mi tc v nh
du phn khc lp ca mi tc v
8
ng Nguyn Phng Ti liu ni b NMTP
#include <stdio . h>
#include <mpi . h>
int main ( int argc , char argv )
{
int i , rank , ntasks , count , start , stop , nloops , total_nloops ;
MPI_Init(&argc , &argv ) ;
MPI_Comm_rank ( MPI_COMM_WORLD , &rank ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &ntasks ) ;
count = 1000 / nt as ks ;
s t a r t = rank count ;
stop = s t a r t + count ;
nl oops = 0;
f or ( i=s t a r t ; i <stop ; ++i ) {
++nl oops ;
}
pr i nt f (" Task %d perf ormed %d i t e r a t i o n s of the l oop . \ n" ,
rank , nl oops ) ;
}
Trong count l s ln lp ca mi tc v, cc tc v c ch s rank s thc hin ln lp th
rank*count n ln lp th rank*count+count-1. Bin nloops s m s ln thc hin vng
lp ca tc v c ch s rank v xut ra mn hnh.
Trong trng hp tc v ang thc hin khng phi l tc v ch (rank khc 0), tc v ny s
gi kt qu nloops cho tc v ch.
#include <stdio . h>
#include <mpi . h>
int main ( int argc , char argv )
{
int i , rank , ntasks , count , start , stop , nloops , total_nloops ;
MPI_Init(&argc , &argv ) ;
MPI_Comm_rank ( MPI_COMM_WORLD , &rank ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &ntasks ) ;
count = 1000 / ntasks ;
start = rank count ;
stop = start + count ;
nloops = 0;
for ( i=start ; i<stop ; ++i) {
++nloops ;
}
printf (" Task %d performed %d iterations of the loop . \ n" ,
rank , nloops ) ;
i f ( rank != 0) {
MPI_Send( &nl oops , 1 , MPI_INT, 0 , 0 , MPI_COMM_WORLD ) ;
9
ng Nguyn Phng Ti liu ni b NMTP
}
}
Trong trng hp tc v ny l tc v ch, n s nhn gi tr nloops t cc tc v con gi v
cng dn li
#include <stdio . h>
#include <mpi . h>
int main ( int argc , char argv )
{
int i , rank , ntasks , count , start , stop , nloops , total_nloops ;
MPI_Init(&argc , &argv ) ;
MPI_Comm_rank ( MPI_COMM_WORLD , &rank ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &ntasks ) ;
count = 1000 / ntasks ;
start = rank count ;
stop = start + count ;
nloops = 0;
for ( i=start ; i<stop ; ++i) {
++nloops ;
}
printf (" Task %d performed %d iterations of the loop . \ n" ,
rank , nloops ) ;
if ( rank != 0) {
MPI_Send ( &nloops , 1 , MPI_INT , 0 , 0 , MPI_COMM_WORLD ) ;
} e l s e {
t ot al _nl oops = nl oops ;
f or ( i =1; i <nt as ks ; ++i ) {
MPI_Recv( &nl oops , 1 , MPI_INT, i , 0 , MPI_COMM_WORLD, 0 ) ;
t ot al _nl oops += nl oops ;
}
}
}
Tc v ch s chy tip s 1000 vng lp trong trng hp c d ra mt s vng lp sau
khi chia 1000 cho tng s tc v.
#include <stdio . h>
#include <mpi . h>
int main ( int argc , char argv )
{
int i , rank , ntasks , count , start , stop , nloops , total_nloops ;
MPI_Init(&argc , &argv ) ;
MPI_Comm_rank ( MPI_COMM_WORLD , &rank ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &ntasks ) ;
count = 1000 / ntasks ;
start = rank count ;
10
ng Nguyn Phng Ti liu ni b NMTP
stop = start + count ;
nloops = 0;
for ( i=start ; i<stop ; ++i) {
++nloops ;
}
printf (" Task %d performed %d iterations of the loop . \ n" ,
rank , nloops ) ;
if ( rank != 0) {
MPI_Send ( &nloops , 1 , MPI_INT , 0 , 0 , MPI_COMM_WORLD ) ;
} else {
total_nloops = nloops ;
for ( i=1; i<ntasks ; ++i) {
MPI_Recv ( &nloops , 1 , MPI_INT , i , 0 , MPI_COMM_WORLD , 0 ) ;
total_nloops += nloops ;
}
nl oops = 0;
f or ( i=t ot al _nl oops ; i <1000; ++i ) {
++nl oops ;
}
}
}
Cui cng l xut ra kt qu v kt thc mi trng MPI, cng nh kt thc chng trnh.
#include <stdio . h>
#include <mpi . h>
int main ( int argc , char argv )
{
int i , rank , ntasks , count , start , stop , nloops , total_nloops ;
MPI_Init(&argc , &argv ) ;
MPI_Comm_rank ( MPI_COMM_WORLD , &rank ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &ntasks ) ;
count = 1000 / ntasks ;
start = rank count ;
stop = start + count ;
nloops = 0;
for ( i=start ; i<stop ; ++i) {
++nloops ;
}
printf (" Task %d performed %d iterations of the loop . \ n" ,
rank , nloops ) ;
if ( rank != 0) {
MPI_Send ( &nloops , 1 , MPI_INT , 0 , 0 , MPI_COMM_WORLD ) ;
} else {
total_nloops = nloops ;
for ( i=1; i<ntasks ; ++i) {
MPI_Recv ( &nloops , 1 , MPI_INT , i , 0 , MPI_COMM_WORLD , 0 ) ;
total_nloops += nloops ;
11
ng Nguyn Phng Ti liu ni b NMTP
}
nloops = 0;
for ( i=total_nloops ; i<1000; ++i) {
++nloops ;
}
pr i nt f (" Task 0 perf ormed the remai ni ng %d i t e r a t i o n s of the l oop
\n" , nl oops ) ;
}
MPI_Finalize ( ) ;
r et ur n 0;
}
Chng trnh vng lp cng c th c vit li theo ngn ng C++ nh sau
#include <iostream>
#include <mpi . h>
int main ( int argc , char argv )
{
MPI : : Init ( argc , argv ) ;
int rank = MPI : : COMM_WORLD . Get_rank ( ) ;
int ntasks = MPI : : COMM_WORLD . Get_size ( ) ;
int count = 1000 / ntasks ;
int start = rank count ;
int stop = start + count ;
int nloops = 0;
for ( int i=start ; i<stop ; ++i) {
++nloops ;
}
std : : cout << "Task " << rank << " performed " << nloops
<< " iterations of the loop . \ n ";
if ( rank != 0) {
MPI : : COMM_WORLD . Send ( &nloops , 1 , MPI_INT , 0 , 0 ) ;
} else {
int total_nloops = nloops ;
for ( int i=1; i<ntasks ; ++i) {
MPI : : COMM_WORLD . Recv ( &nloops , 1 , MPI_INT , i , 0 ) ;
total_nloops += nloops ;
}
nloops = 0;
for ( int i=total_nloops ; i<1000; ++i) {
++nloops ;
}
std : : cout << "Task 0 performed the remaining " << nloops
<< " iterations of the loop\n ";
}
MPI : : Finalize ( ) ;
return 0;
}
12
ng Nguyn Phng Ti liu ni b NMTP
4 Cc lnh MPI
4.1 Cc lnh qun l mi trng MPI
Cc lnh ny c nhim v thit lp mi trng cho cc lnh thc thi MPI, truy vn ch s ca
tc v, cc th vin MPI,...
MPI_Init khi ng mi trng MPI
MPI_Init (&argc,&argv)
Init (argc,argv)
MPI_Comm_size tr v tng s tc v MPI ang c thc hin trong communicator
(chng hn nh trong MPI_COMM_WORLD)
MPI_Comm_size (comm,&size)
Comm::Get_size()
MPI_Comm_rank tr v ch s ca tc v (rank). Ban u mi tc v s c gn cho
mt s nguyn t 0 n (N1) vi N l tng s tc v trong communicator MPI_COMM_WORLD.
MPI_Comm_rank (comm,&rank)
Comm::Get_rank()
MPI_Abort kt thc tt c cc tin trnh MPI
MPI_Abort (comm,errorcode)
Comm::Abort(errorcode)
MPI_Get_processor_name tr v tn ca b x l
MPI_Get_processor_name (&name,&resultlength)
Get_processor_name(&name,resultlen)
MPI_Initialized tr v gi tr 1 nu MPI_Init() c gi, 0 trong trng hp ngc li
MPI_Initialized (&flag)
Initialized (&flag)
MPI_Wtime tr v thi gian chy (tnh theo giy) ca b x l
MPI_Wtime ()
Wtime ()
MPI_Wtick tr v phn gii thi gian (tnh theo giy) ca MPI_Wtime()
MPI_Wtick ()
Wtick ()
MPI_Finalize kt thc mi trng MPI
MPI_Finalize ()
Finalize ()
V d:
13
ng Nguyn Phng Ti liu ni b NMTP
#include <stdio . h>
#include <mpi . h>
4 i nt main ( i nt argc , char argv )
{
i nt numtasks , rank , len , rc ;
char hostname [ MPI_MAX_PROCESSOR_NAME ] ;
9 rc = MPI_Init(&argc,&argv ) ;
i f ( rc != MPI_SUCCESS ) {
printf ( " Error s t a r t i ng MPI program . Termi nati ng . \ n" ) ;
MPI_Abort ( MPI_COMM_WORLD , rc) ;
}
14
MPI_Comm_size ( MPI_COMM_WORLD ,&numtasks ) ;
MPI_Comm_rank ( MPI_COMM_WORLD ,&rank ) ;
MPI_Get_processor_name ( hostname , &len ) ;
printf ( "Number of t as ks= %d My rank= %d Running on %s \n" , numtasks ,
rank , hostname ) ;
19
/ do some work /
MPI_Finalize ( ) ;
}
4.2 Cc kiu d liu
Mt s kiu d liu c bn ca MPI c lit k trong bng sau
Tn Kiu d liu
MPI_CHAR signed character
MPI_WCHAR wide character
MPI_SHORT signed short
MPI_INT signed int
MPI_LONG signed long
MPI_LONG_LONG signed long long
MPI_UNSIGNED_CHAR unsigned character
MPI_UNSIGNED_SHORT unsigned short
MPI_UNSIGNED unsigned int
MPI_UNSIGNED_LONG unsigned long
MPI_FLOAT float
MPI_DOUBLE double
MPI_LONG_DOUBLE long double
Tn Kiu d liu
MPI_C_COMPLEX float_Complex
MPI_C_DOUBLE_COMPLEX double_Complex
MPI_C_BOOL bool
MPI_INT8_T int8_t
MPI_INT16_T int16_t
MPI_INT32_T int32_t
MPI_INT64_T int64_t
MPI_UINT8_T uint8_t
MPI_UINT16_T uint16_t
MPI_UINT32_T uint32_t
MPI_UINT64_T uint64_t
MPI_BYTE byte
MPI_PACKED data packed
Ngoi ra ngi dng cn c th t to ra cc cu trc d liu ring cho mnh da trn cc kiu
d liu c bn ny. Cc kiu d liu c cu trc do ngi dng t nh ngha c gi l derived
data types. Cc lnh nh ngha cu trc d liu mi bao gm:
MPI_Type_contiguous to ra kiu d liu mi bng cch lp count ln kiu d liu c.
MPI_Type_contiguous (count,oldtype,&newtype)
Datatype::Create_contiguous(count)
14
ng Nguyn Phng Ti liu ni b NMTP
MPI_Type_vector tng t nh contigous nhng c cc phn on (stride) c nh, kiu
d liu mi c hnh thnh bng cch lp mt dy cc khi (block) ca kiu d liu c c kch
thc bng nhau ti cc v tr c tnh tun hon.
MPI_Type_vector (count,blocklength,stride,oldtype,&newtype)
Datatype::Create_vector(count,blocklength,stride)
MPI_Type_indexed kiu d liu mi c hnh thnh bng cch to mt dy cc khi ca
kiu d liu c, mi khi c th cha s lng cc bn sao kiu d liu c khc nhau.
MPI_Type_indexed (count,blocklens[],offsets[],oldtype,&newtype)
Datatype::Create_hindexed(count,blocklens[],offsets[])
MPI_Type_struct tng t nh trn nhng mi khi c th c to thnh bi cc kiu
d liu c khc nhau.
MPI_Type_struct (count,blocklens[],offsets[],oldtypes,&newtype)
Datatype::Create_struct(count, blocklens[],offsets[],oldtypes[])
Hnh 1 trnh by mt s v d cho cc cch to cu trc d liu mi. Trong trng hp truyn
cc cu trc d liu khng cng kiu, ta c th s dng cc lnh MPI_Packed v MPI_Unpacked
ng gi d liu trc khi gi.
Hnh 1: V d cc cch to cu trc d liu mi
MPI_Type_extent tr v kch thc (tnh theo byte) ca kiu d liu
MPI_Type_extent (datatype,&extent)
Datatype::Get_extent(lb,extent)
MPI_Type_commit a kiu d liu mi nh ngha vo trong h thng
MPI_Type_commit (&datatype)
Datatype::Commit()
15
ng Nguyn Phng Ti liu ni b NMTP
MPI_Type_free b kiu d liu
MPI_Type_free (&datatype)
Datatype::Free()
V d: to kiu d liu vector
#include <stdio . h>
2 #include <mpi . h>
#define SIZE 4
i nt main ( i nt argc , char argv )
{
7 i nt numtasks , rank , source=0, dest , tag=1, i ;
f l o a t a [ SIZE ] [ SIZE ] =
{1. 0 , 2. 0 , 3. 0 , 4. 0 ,
5. 0 , 6. 0 , 7. 0 , 8. 0 ,
9. 0 , 10. 0 , 11. 0 , 12. 0 ,
12 13. 0 , 14. 0 , 15. 0 , 16. 0};
f l o a t b [ SIZE ] ;
MPI_Status stat ;
MPI_Datatype columntype ;
17
MPI_Init(&argc,&argv ) ;
MPI_Comm_rank ( MPI_COMM_WORLD , &rank ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &numtasks ) ;
22 MPI_Type_vector ( SIZE , 1 , SIZE , MPI_FLOAT , &columntype ) ;
MPI_Type_commit(&columntype ) ;
i f ( numtasks == SIZE ) {
i f ( rank == 0) {
27 f or ( i=0; i<numtasks ; i++)
MPI_Send(&a [ 0 ] [ i ] , 1 , columntype , i , tag , MPI_COMM_WORLD ) ;
}
MPI_Recv ( b , SIZE , MPI_FLOAT , source , tag , MPI_COMM_WORLD , &stat ) ;
printf ( "rank= %d b= %3.1 f %3.1 f %3.1 f %3.1 f \n" ,
32 rank , b [ 0 ] , b [ 1 ] , b [ 2 ] , b [ 3 ] ) ;
} e l s e
printf ( "Must s pe c i f y %d pr oc e s s or s . Termi nati ng . \ n" , SIZE ) ;
MPI_Type_free(&columntype ) ;
37 MPI_Finalize ( ) ;
}
4.3 Cc c ch truyn thng ip
Cc c ch giao tip trong MPI gm c:
Point-to-point c ch giao tip im-im, y l c ch giao tip gia tng cp tc v vi
nhau, trong 1 tc v thc hin cng vic gi thng ip v tc v cn li c nhim v nhn
thng ip tng ng . Thng ip c phn bit bi ch s ca tc v v nhn (tag) ca
thng ip. Trong c ch ny c nhiu kiu giao tip vi nhau, chng hn nh
Blocking: cc lnh gi/nhn d liu s kt thc khi vic gi/nhn d liu hon tt.
16
ng Nguyn Phng Ti liu ni b NMTP
Non-blocking: cc lnh gi/nhn d liu s kt thc ngay m quan tm n vic d liu
thc s c hon ton gi i hoc nhn v hay cha. Vic d liu thc s c
gi i hay nhn v s c kim tra cc lnh khc trong th vin MPI.
Synchronous: gi d liu ng b, qu trnh gi d liu ch c th c kt thc khi qu
trnh nhn d liu c bt u.
Buffer: mt vng nh m s c to ra cha d liu trc khi c gi i, ngi
dng c th ghi ln vng b nh cha d liu m khng s lm mt d liu chun b
gi.
Ready: qu trnh gi d liu ch c th c bt u khi qu trnh nhn d liu sn
sng.
Bng di y tng hp cc ch giao tip im-im v cc lnh gi/nhn thng ip tng
ng, thng tin chi tit v cc lnh ny s c trnh by nhng phn sau
Ch iu kin kt thc Blocking Non-blocking
Send Thng ip c gi MPI_Send MPI_Isend
Receive Thng ip c nhn MPI_Recv MPI_Irecv
Synchronous send Khi qu trnh nhn bt u MPI_Ssend MPI_Issend
Buffer send Lun kt thc, khng quan tm qu
trnh nhn bt u hay cha
MPI_Bsend MPI_Ibsend
Ready send Lun kt thc, khng quan tm qu
trnh nhn kt thc hay cha
MPI_Rsend MPI_Irsend
Collective communication c ch giao tip tp th, lin quan ti tt c cc tc v nm
trong phm vi ca communicator, cc kiu giao tip trong c ch ny (xem Hnh 2) gm c
Broadcast: d liu ging nhau c gi t tc v gc (root) n tt c cc tc v khc
trong communicator.
Scatter: cc d liu khc nhau c gi t tc v gc n tt c cc tc v khc trong
communicator.
Gather: cc d liu khc nhau c thu thp bi tc v gc t tt c cc tc v khc
trong communicator.
Reduce: phng thc ny cho php ta c th thu thp d liu t mi tc v, rt gn d
liu, lu tr d liu vo trong mt tc v gc hoc trong tt c cc tc v.
Hnh 2: Minh ha cc kiu giao tip theo c ch tp th
17
ng Nguyn Phng Ti liu ni b NMTP
4.4 Cc lnh truyn thng ip blocking
Mt s lnh thng dng cho ch truyn thng ip blocking gm c:
MPI_Send gi cc thng tin c bn
MPI_Send (&buf,count,datatype,dest,tag,comm)
Comm::Send(&buf,count,datatype,dest,tag)
MPI_Recv nhn cc thng tin c bn
MPI_Recv (&buf,count,datatype,source,tag,comm,&status)
Comm::Recv(&buf,count,datatype,source,tag,status)
MPI_Ssend gi ng b thng tin, lnh ny s ch cho n khi thng tin c nhn
(thng tin c gi s b gi li cho n khi b m ca tc v gi c gii phng c th
s dng li v tc v ch (destination process) bt u nhn thng tin)
MPI_Ssend (&buf,count,datatype,dest,tag,comm)
Comm::Ssend(&buf,count,datatype,dest,tag)
MPI_Bsend to mt b nh m (buffer) m d liu c lu vo cho n khi c gi i,
lnh ny s kt thc khi hon tt vic lu d liu vo b nh m.
MPI_Bsend (&buf,count,datatype,dest,tag,comm)
Comm::Bsend(&buf,count,datatype,dest,tag)
MPI_Buffer_attach cp pht dung lng b nh m cho thng tin c s dng bi lnh
MPI_Bsend()
MPI_Buffer_attach (&buffer,size)
Attach_buffer(&buffer,size)
MPI_Buffer_detach b cp pht dung lng b nh m cho thng tin c s dng bi
lnh MPI_Bsend()
MPI_Buffer_detach (&buffer,size)
Detach_buffer(&buffer,size)
MPI_Rsend gi thng tin theo ch ready, ch nn s dng khi ngi lp trnh chc chn
rng qu trnh nhn thng tin sn sng.
MPI_Rsend (&buf,count,datatype,dest,tag,comm)
Comm::Rsend(&buf,count,datatype,dest,tag)
MPI_Sendrecv gi thng tin i v sn sng cho vic nhn thng tin t tc v khc
MPI_Sendrecv (&sendbuf,sendcount,sendtype,dest,sendtag,
&recvbuf,recvcount,recvtype,source,recvtag,comm,&status)
Comm::Sendrecv(&sendbuf,sendcount,sendtype,dest,sendtag,
&recvbuf,recvcount,recvtype,source,recvtag,status)
MPI_Wait ch cho n khi cc tc v gi v nhn thng tin hon thnh
MPI_Wait (&request,&status)
Request::Wait(status)
18
ng Nguyn Phng Ti liu ni b NMTP
MPI_Probe kim tra tnh blocking ca thng tin
MPI_Probe (source,tag,comm,&status)
Comm::Probe(source,tag,status)
V d:
#include <stdio . h>
2 #include <mpi . h>
i nt main ( i nt argc , char argv )
{
i nt numtasks , rank , dest , source , rc , count , tag=1;
7 char inmsg , outmsg=' x ' ;
MPI_Status Stat ;
MPI_Init(&argc,&argv ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &numtasks ) ;
12 MPI_Comm_rank ( MPI_COMM_WORLD , &rank ) ;
i f ( rank == 0) {
dest = 1;
source = 1;
17 rc = MPI_Send(&outmsg , 1 , MPI_CHAR , dest , tag , MPI_COMM_WORLD ) ;
rc = MPI_Recv(&inmsg , 1 , MPI_CHAR , source , tag , MPI_COMM_WORLD , &
Stat ) ;
} e l s e i f ( rank == 1) {
dest = 0;
source = 0;
22 rc = MPI_Recv(&inmsg , 1 , MPI_CHAR , source , tag , MPI_COMM_WORLD , &
Stat ) ;
rc = MPI_Send(&outmsg , 1 , MPI_CHAR , dest , tag , MPI_COMM_WORLD ) ;
}
rc = MPI_Get_count(&Stat , MPI_CHAR , &count ) ;
27 printf ( "Task %d : Recei ved %d char ( s ) from t as k %d wi th tag %d \n" ,
rank , count , Stat . MPI_SOURCE , Stat . MPI_TAG ) ;
MPI_Finalize ( ) ;
}
4.5 Cc lnh truyn thng ip non-blocking
Mt s lnh thng dng cho ch truyn thng ip non-blocking gm c:
MPI_Isend gi thng ip non-blocking, xc nh mt khu vc ca b nh thc hin nhim
v nh l mt b m gi thng tin.
MPI_Isend (&buf,count,datatype,dest,tag,comm,&request)
Request Comm::Isend(&buf,count,datatype,dest,tag)
MPI_Irecv nhn thng ip non-blocking, xc nh mt khu vc ca b nh thc hin nhim
v nh l mt b m nhn thng tin.
MPI_Irecv (&buf,count,datatype,source,tag,comm,&request)
Request Comm::Irecv(&buf,count,datatype,source,tag)
19
ng Nguyn Phng Ti liu ni b NMTP
MPI_Issend gi thng ip non-blocking ng b (synchronous).
MPI_Issend (&buf,count,datatype,dest,tag,comm,&request)
Request Comm::Issend(&buf,count,datatype,dest,tag)
MPI_Ibsend gi thng ip non-blocking theo c ch buffer.
MPI_Ibsend (&buf,count,datatype,dest,tag,comm,&request)
Request Comm::Ibsend(&buf,count,datatype,dest,tag)
MPI_Irsend gi thng ip non-blocking theo c ch ready.
MPI_Irsend (&buf,count,datatype,dest,tag,comm,&request)
Request Comm::Irsend(&buf,count,datatype,dest,tag)
MPI_Test kim tra trng thi kt thc ca cc lnh gi v nhn thng ip non-blocking
Isend(), Irecv(). Tham s request l tn bin yu cu c dng trong cc lnh gi v
nhn thng ip, tham s flag s tr v gi tr 1 nu thao tc hon thnh v gi tr 0 trong
trng hp ngc li.
MPI_Test (&request,&flag,&status)
Request::Test(status)
MPI_Iprobe kim tra tnh non-blocking ca thng ip
MPI_Iprobe (source,tag,comm,&flag,&status)
Comm::Iprobe(source,tag,status)
V d:
#include <stdio . h>
#include <mpi . h>
4 i nt main ( i nt argc , char argv )
{
i nt numtasks , rank , next , prev , buf [ 2 ] , tag1=1, tag2=2;
MPI_Request reqs [ 4 ] ;
MPI_Status stats [ 2 ] ;
9
MPI_Init(&argc,&argv ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &numtasks ) ;
MPI_Comm_rank ( MPI_COMM_WORLD , &rank ) ;
14 prev = rank 1;
next = rank+1;
i f ( rank == 0) prev = numtasks 1;
i f ( rank == ( numtasks 1) ) next = 0;
19 MPI_Irecv(&buf [ 0 ] , 1 , MPI_INT , prev , tag1 , MPI_COMM_WORLD , &reqs [ 0 ] ) ;
MPI_Irecv(&buf [ 1 ] , 1 , MPI_INT , next , tag2 , MPI_COMM_WORLD , &reqs [ 1 ] ) ;
MPI_Isend(&rank , 1 , MPI_INT , prev , tag2 , MPI_COMM_WORLD , &reqs [ 2 ] ) ;
MPI_Isend(&rank , 1 , MPI_INT , next , tag1 , MPI_COMM_WORLD , &reqs [ 3 ] ) ;
24
{ /do some work/ }
MPI_Waitall ( 4 , reqs , stats ) ;
29 MPI_Finalize ( ) ;
20
ng Nguyn Phng Ti liu ni b NMTP
}
4.6 Cc lnh truyn thng tp th
Mt s lnh thng dng cho cho c ch truyn thng tp th gm c:
MPI_Barrier lnh ng b ha (ro chn), tc v ti ro chn (barrier) phi ch cho n
khi tt c cc tc v khc trn cng mt communicator u hon thnh (xem Hnh 3).
MPI_Barrier (comm)
Intracomm::Barrier()
Hnh 3: Minh ha lnh ro chn
MPI_Bcast gi bn sao ca b m c kch thc count t tc v root n tt c cc tin
trnh khc trong cng mt communicator.
MPI_Bcast (&buffer,count,datatype,root,comm)
Intracomm::Bcast(&buffer,count,datatype,root)
MPI_Scatter phn pht gi tr b m ln tt c cc tc v khc, b m c chia thnh
sendcnt phn.
MPI_Scatter (&sendbuf,sendcnt,sendtype,&recvbuf,recvcnt,recvtype,root,comm)
Intracomm::Scatter(&sendbuf,sendcnt,sendtype,&recvbuf,recvcnt,recvtype,root)
MPI_Gather to mi mt gi tr b m ring cho mnh t cc mnh d liu gp li.
MPI_Gather (&sendbuf,sendcnt,sendtype,&recvbuf,recvcnt,recvtype,root,comm)
Intracomm::Gather(&sendbuf,sendcnt,sendtype,&recvbuf,recvcnt,recvtype,root)
MPI_Allgather tng t nh MPI_GATHER nhng sao chp b m mi cho tt c cc tc
v.
MPI_Allgather (&sendbuf,sendcnt,sendtype,&recvbuf,recvcount,recvtype,comm)
Intracomm::Allgather(&sendbuf,sendcnt,sendtype,&recvbuf,recvcnt,recvtype)
MPI_Reduce p dng cc ton t rt gn (tham s op) cho tt c cc tc v v lu kt
qu vo mt tc v duy nht.
MPI_Reduce (&sendbuf,&recvbuf,count,datatype,op,root,comm)
Intracomm::Reduce(&sendbuf,&recvbuf,count,datatype,op,root)
Cc ton t rt gn gm c: MPI_MAX (cc i), MPI_MIN (cc tiu), MPI_SUM (tng), MPI_PROD
(tch), MPI_LAND (ton t AND logic), MPI_BAND (ton t AND bitwise), MPI_LOR (ton t OR
21
ng Nguyn Phng Ti liu ni b NMTP
logic), MPI_BOR (ton t OR bitwise), MPI_LXOR (ton t XOR logic), MPI_BXOR (ton t XOR
bitwise), MPI_MAXLOC (gi tr cc i v v tr), MPI_MINLOC (gi tr cc tiu v v tr).
MPI_Allreduce tng t nh MPI_Reduce nhng lu kt qu vo tt c cc tc v.
MPI_Allreduce (&sendbuf,&recvbuf,count,datatype,op,comm)
Intracomm::Allreduce(&sendbuf,&recvbuf,count,datatype,op)
MPI_Reduce_scatter tng ng vi vic p dng lnh MPI_Reduce ri ti lnh MPI_Scatter.
MPI_Reduce_scatter (&sendbuf,&recvbuf,recvcount,datatype,op,comm)
Intracomm::Reduce_scatter(&sendbuf,&recvbuf,recvcount[], datatype,op)
MPI_Alltoall tng ng vi vic p dng lnh MPI_Scatter ri ti lnh MPI_Gather.
MPI_Alltoall (&sendbuf,sendcount,sendtype,&recvbuf,recvcnt,recvtype,comm)
Intracomm::Alltoall(&sendbuf,sendcount,sendtype,&recvbuf,recvcnt,recvtype)
MPI_Scan kim tra vic thc hin ton t rt gn ca cc tc v.
MPI_Scan (&sendbuf,&recvbuf,count,datatype,op,comm)
Intracomm::Scan(&sendbuf,&recvbuf,count,datatype,op)
Hnh 4: Minh ha mt s lnh giao tip tp th
V d:
#include <stdio . h>
#include <mpi . h>
i nt main ( i nt argc , char argv )
5 {
i nt numtasks , rank , sendcount , recvcount , source ;
f l o a t sendbuf [ SIZE ] [ SIZE ] = {
{1. 0 , 2. 0 , 3. 0 , 4. 0} ,
{5. 0 , 6. 0 , 7. 0 , 8. 0} ,
10 {9. 0 , 10. 0 , 11. 0 , 12. 0} ,
{13. 0 , 14. 0 , 15. 0 , 16. 0} };
f l o a t recvbuf [ SIZE ] ;
MPI_Init(&argc,&argv ) ;
15 MPI_Comm_rank ( MPI_COMM_WORLD , &rank ) ;
MPI_Comm_size ( MPI_COMM_WORLD , &numtasks ) ;
22
ng Nguyn Phng Ti liu ni b NMTP
i f ( numtasks == SIZE ) {
source = 1;
20 sendcount = SIZE ;
recvcount = SIZE ;
MPI_Scatter ( sendbuf , sendcount , MPI_FLOAT , recvbuf , recvcount ,
MPI_FLOAT , source , MPI_COMM_WORLD ) ;
printf ( "rank= %d Res ul t s : %f %f %f %f \n" , rank , recvbuf [ 0 ] ,
25 recvbuf [ 1 ] , recvbuf [ 2 ] , recvbuf [ 3 ] ) ;
} e l s e
printf ( "Must s pe c i f y %d pr oc e s s or s . Termi nati ng . \ n" , SIZE ) ;
MPI_Finalize ( ) ;
30 }
5 Mt s v d
5.1 V d tnh s
Trong v d ny ta s tin hnh lp trnh song song cho php tnh s . Gi tr ca s c th
c xc nh qua cng thc tch phn
=

1
0
f(x)dx , vi f(x) =
4
(1 +x
2
)
(1)
Tch phn ny c th c xp x theo gii tch s nh sau
=
1
n
n

i=1
f(x
i
) , vi x
i
=
(i
1
2
)
n
(2)
Cng thc xp x trn c th d dng xy dng vi C
h = 1. 0 / ( double ) n ;
sum = 0 . 0 ;
for ( i = 1; i <= n ; i++) {
x = h ( ( double ) i 0. 5) ;
5 sum += ( 4. 0 / ( 1. 0 + xx) ) ;
}
mypi = h sum ;
Trong v d ny, ta s s dng c ch truyn thng tp th. Da vo cng thc pha trn ta c
th d dng nhn ra rng ch c mt tham s duy nht, l n, do ta s truyn tham s ny
cho tt c cc tc v trong h thng thng qua lnh MPI_Bcast
MPI_Bcast(&n , 1 , MPI_INT , 0 , MPI_COMM_WORLD ) ;
Mi tc v con s thc thi cng thc xp x n/numtasks ln, vi numtasks l tng s cc tc
v, do vng lp s c chnh sa li
h = 1. 0 / ( double ) n ;
sum = 0 . 0 ;
for ( i = myid + 1 ; i <= n ; i += numtasks ) {
4 x = h ( ( double ) i 0. 5) ;
sum += ( 4. 0 / ( 1. 0 + xx) ) ;
}
mypi = h sum ;
23
ng Nguyn Phng Ti liu ni b NMTP
vi myid l ch s ca tc v ang thc thi.
Kt qu chy t cc tc v s c tnh tng v lu tc v ch thng qua lnh MPI_Reduce
MPI_Reduce(&mypi , &pi , 1 , MPI_DOUBLE , MPI_SUM , 0 , MPI_COMM_WORLD ) ;
on code chng trnh sau khi thm phn MPI
#include <stdio . h>
#include <math . h>
#i nc l ude <mpi . h>
4
int main ( int argc , char argv )
{
i nt n , myid , numprocs , i ;
doubl e mypi , pi , h , sum, x ;
9
MPI_Init(&argc ,&argv ) ;
MPI_Comm_size(MPI_COMM_WORLD,&numprocs ) ;
MPI_Comm_rank(MPI_COMM_WORLD,&myid) ;
14 MPI_Bcast(&n , 1 , MPI_INT, 0 , MPI_COMM_WORLD) ;
h = 1. 0 / ( double ) n ;
sum = 0 . 0 ;
for ( i = myid + 1; i <= n ; i += numprocs ) {
19 x = h ( ( double ) i 0. 5) ;
sum += ( 4. 0 / ( 1. 0 + xx) ) ;
}
mypi = h sum ;
MPI_Reduce(&mypi , &pi , 1 , MPI_DOUBLE, MPI_SUM, 0 , MPI_COMM_WORLD) ;
24
MPI_Finalize ( ) ;
return 0;
}
Chng trnh tnh gi tr s hon chnh nh sau
#include <stdio . h>
#include <math . h>
3 #include <mpi . h>
i nt main ( i nt argc , char argv )
{
i nt n , myid , numprocs , i ;
8 doubl e PI25DT = 3. 141592653589793238462643;
doubl e mypi , pi , h , sum , x ;
MPI_Init(&argc,&argv ) ;
MPI_Comm_size ( MPI_COMM_WORLD ,&numprocs ) ;
13 MPI_Comm_rank ( MPI_COMM_WORLD ,&myid ) ;
whi l e ( 1) {
i f ( myid == 0) {
printf ( "Enter the number of i nt e r v a l s : (0 qui t s ) " ) ;
18 scanf ( "%d",&n) ;
}
MPI_Bcast(&n , 1 , MPI_INT , 0 , MPI_COMM_WORLD ) ;
i f ( n == 0)
24
ng Nguyn Phng Ti liu ni b NMTP
break ;
23 e l s e {
h = 1. 0 / ( doubl e ) n ;
sum = 0 . 0 ;
f or ( i = myid + 1; i <= n ; i += numprocs ) {
x = h ( ( doubl e ) i 0. 5) ;
28 sum += ( 4. 0 / ( 1. 0 + xx) ) ;
}
mypi = h sum ;
MPI_Reduce(&mypi , &pi , 1 , MPI_DOUBLE , MPI_SUM , 0 ,
MPI_COMM_WORLD ) ;
i f ( myid == 0)
33 printf ( " pi i s approxi matel y %.16 f , Error i s %.16 f \n" , pi ,
fabs ( pi PI25DT ) ) ;
}
}
MPI_Finalize ( ) ;
r et ur n 0;
38 }
Chng trnh tnh s cng c th c vit li theo ngn ng C++ nh sau
#include <math . h>
2 #include <mpi . h>
i nt main ( i nt argc , char argv )
{
i nt n , rank , size , i ;
7 doubl e PI25DT = 3. 141592653589793238462643;
doubl e mypi , pi , h , sum , x ;
MPI : : Init ( argc , argv ) ;
size = MPI : : COMM_WORLD . Get_size ( ) ;
12 rank = MPI : : COMM_WORLD . Get_rank ( ) ;
whi l e ( 1) {
i f ( rank == 0) {
cout << "Enter the number of i nt e r v a l s : (0 qui t s ) " << endl ;
17 cin >> n ;
}
MPI : : COMM_WORLD . Bcast(&n , 1 , MPI : : INT , 0) ;
i f ( n==0)
22 break ;
e l s e {
h = 1. 0 / ( doubl e ) n ;
sum = 0 . 0 ;
f or ( i = rank + 1; i <= n ; i += size ) {
27 x = h ( ( doubl e ) i 0. 5) ;
sum += ( 4. 0 / ( 1. 0 + xx) ) ;
}
mypi = h sum ;
32 MPI : : COMM_WORLD . Reduce(&mypi , &pi , 1 , MPI : : DOUBLE ,
MPI : : SUM , 0) ;
i f ( rank == 0)
cout << " pi i s approxi matel y " << pi << " , Error i s " <<
fabs ( pi PI25DT ) << endl ;
25
ng Nguyn Phng Ti liu ni b NMTP
}
37 }
MPI : : Finalize ( ) ;
r et ur n 0;
}
5.2 V d nhn ma trn
Trong v d ny ta s xy dng mt chng trnh tnh tch ca hai ma trn bng phng php
tnh ton song song. Gi s ta c ma trn C l tch ca hai ma trn A v B, ta c th khai bo
trong C nh sau
#define NRA 62
#define NCA 15
#define NCB 7
5 doubl e a [ NRA ] [ NCA ] , b [ NCA ] [ NCB ] , c [ NRA ] [ NCB ] ;
trong NRA, NCA v NCB ln lt l s ct v s dng ca ma trn A, s dng ca ma trn B.
im c bit trong v d ny l ta s chia cc tc v (tin trnh) ra lm hai loi: tc v chnh
v tc v con, mi loi tc v s thc hin nhng cng vic khc nhau. thun tin trong
vic ghi nh, ta c th khai bo cc tham s biu din cho ch s ca tc v chnh (MASTER), v
nhn (tag) nh du rng d liu c gi l t tc v chnh (FROM_MASTER) hay tc v con
(FROM_WORKER).
#define MASTER 0
#define FROM_MASTER 1
#define FROM_WORKER 2
Cc cng vic ca tc v chnh gm c
Khi to cc ma trn A v B
f or ( i=0; i<NRA ; i++)
2 f or ( j=0; j<NCA ; j++)
a [ i ] [ j]= i+j ;
f or ( i=0; i<NCA ; i++)
f or ( j=0; j<NCB ; j++)
b [ i ] [ j]= ij ;
Gi d liu cho cc tc v con. Trong v d ny s ct ca ma trn B s c chia thnh
numworkers phn tng tng vi s lng tc v con.
/ Send matri x data to the worker t as ks /
averow = NRA/numworkers ;
extra = NRA%numworkers ;
4 offset = 0;
mtype = FROM_MASTER ;
f or ( dest=1; dest<=numworkers ; dest++) {
rows = ( dest <= extra ) ? averow+1 : averow ;
printf ( "Sendi ng %d rows to t ask %d o f f s e t=%d\n" , rows , dest ,
9 offset ) ;
MPI_Send(&offset , 1 , MPI_INT , dest , mtype , MPI_COMM_WORLD ) ;
MPI_Send(&rows , 1 , MPI_INT , dest , mtype , MPI_COMM_WORLD ) ;
MPI_Send(&a [ offset ] [ 0 ] , rowsNCA , MPI_DOUBLE , dest , mtype ,
MPI_COMM_WORLD ) ;
14 MPI_Send(&b , NCANCB , MPI_DOUBLE , dest , mtype , MPI_COMM_WORLD ) ;
26
ng Nguyn Phng Ti liu ni b NMTP
offset = offset + rows ;
}
Nhn d liu t tc v con
/ Recei ve r e s u l t s from worker t as ks /
mtype = FROM_WORKER ;
f or ( i=1; i<=numworkers ; i++) {
4 source = i ;
MPI_Recv(&offset , 1 , MPI_INT , source , mtype , MPI_COMM_WORLD , &
status ) ;
MPI_Recv(&rows , 1 , MPI_INT , source , mtype , MPI_COMM_WORLD , &
status ) ;
MPI_Recv(&c [ offset ] [ 0 ] , rowsNCB , MPI_DOUBLE , source , mtype ,
MPI_COMM_WORLD , &status ) ;
9 printf ( " Recei ved r e s u l t s from t as k %d\n" , source ) ;
}
In kt qu
/ Pri nt r e s u l t s /
printf ( "\n" ) ;
printf ( " Resul t Matri x : \ n" ) ;
f or ( i=0; i<NRA ; i++) {
5 printf ( "\n" ) ;
f or ( j=0; j<NCB ; j++)
printf ( "%6.2 f " , c [ i ] [ j ] ) ;
}
printf ( "\n\n" ) ;
10 printf ( "Done . \ n" ) ;
Cc cng vic ca tc v con gm c
Nhn d liu t tc v chnh
/ Recei ve matri x data from master t as k /
mtype = FROM_MASTER ;
MPI_Recv(&offset , 1 , MPI_INT , MASTER , mtype , MPI_COMM_WORLD ,&status ) ;
MPI_Recv(&rows , 1 , MPI_INT , MASTER , mtype , MPI_COMM_WORLD , &status ) ;
5 MPI_Recv(&a , rowsNCA , MPI_DOUBLE , MASTER , mtype , MPI_COMM_WORLD , &
status ) ;
MPI_Recv(&b , NCANCB , MPI_DOUBLE , MASTER , mtype , MPI_COMM_WORLD , &
status ) ;
Tnh ton nhn ma trn
/ Do matri x mul t i pl y /
f or ( k=0; k<NCB ; k++)
f or ( i=0; i<rows ; i++) {
4 c [ i ] [ k ] = 0 . 0 ;
f or ( j=0; j<NCA ; j++)
c [ i ] [ k ] = c [ i ] [ k ] + a [ i ] [ j ] b [ j ] [ k ] ;
}
Tr kt qu v cho tc v chnh
/ Send r e s u l t s back to master t ask /
mtype = FROM_WORKER ;
3 MPI_Send(&offset , 1 , MPI_INT , MASTER , mtype , MPI_COMM_WORLD ) ;
27
ng Nguyn Phng Ti liu ni b NMTP
MPI_Send(&rows , 1 , MPI_INT , MASTER , mtype , MPI_COMM_WORLD ) ;
MPI_Send(&c , rowsNCB , MPI_DOUBLE , MASTER , mtype , MPI_COMM_WORLD ) ;
Chng trnh nhn hai ma trn hon chnh nh sau
#include <stdio . h>
#include <stdlib . h>
#include <mpi . h>
5 #define NRA 62
#define NCA 15
#define NCB 7
#define MASTER 0
#define FROM_MASTER 1
10 #define FROM_WORKER 2
i nt main ( i nt argc , char argv )
{
i nt numtasks , taskid , numworkers , source , dest , mtype , rows , averow ,
extra , offset , i , j , k , rc ;
15 doubl e a [ NRA ] [ NCA ] , b [ NCA ] [ NCB ] , c [ NRA ] [ NCB ] ;
MPI_Status status ;
MPI_Init(&argc,&argv ) ;
MPI_Comm_rank ( MPI_COMM_WORLD ,&taskid ) ;
20 MPI_Comm_size ( MPI_COMM_WORLD ,&numtasks ) ;
i f ( numtasks < 2 ) {
printf ( "Need at l e a s t two MPI t as ks . Qui t t i ng . . . \ n" ) ;
MPI_Abort ( MPI_COMM_WORLD , rc) ;
exit ( 1) ;
25 }
numworkers = numtasks 1;
/ master t as k /
i f ( taskid == MASTER ) {
30 printf ( "mpi_mm has s t ar t e d wi th %d t as ks . \ n" , numtasks ) ;
printf ( " I n i t i a l i z i n g ar r ays . . . \ n" ) ;
f or ( i=0; i<NRA ; i++)
f or ( j=0; j<NCA ; j++)
a [ i ] [ j]= i+j ;
35 f or ( i=0; i<NCA ; i++)
f or ( j=0; j<NCB ; j++)
b [ i ] [ j]= ij ;
/ Send matri x data to the worker t as ks /
40 averow = NRA/numworkers ;
extra = NRA%numworkers ;
offset = 0;
mtype = FROM_MASTER ;
f or ( dest=1; dest<=numworkers ; dest++) {
45 rows = ( dest <= extra ) ? averow+1 : averow ;
printf ( "Sendi ng %d rows to t ask %d o f f s e t=%d\n" , rows , dest , offset ) ;
MPI_Send(&offset , 1 , MPI_INT , dest , mtype , MPI_COMM_WORLD ) ;
MPI_Send(&rows , 1 , MPI_INT , dest , mtype , MPI_COMM_WORLD ) ;
MPI_Send(&a [ offset ] [ 0 ] , rowsNCA , MPI_DOUBLE , dest , mtype ,
50 MPI_COMM_WORLD ) ;
MPI_Send(&b , NCANCB , MPI_DOUBLE , dest , mtype , MPI_COMM_WORLD ) ;
offset = offset + rows ;
28
ng Nguyn Phng Ti liu ni b NMTP
}
55 / Recei ve r e s u l t s from worker t as ks /
mtype = FROM_WORKER ;
f or ( i=1; i<=numworkers ; i++) {
source = i ;
MPI_Recv(&offset , 1 , MPI_INT , source , mtype , MPI_COMM_WORLD , &
status ) ;
60 MPI_Recv(&rows , 1 , MPI_INT , source , mtype , MPI_COMM_WORLD , &status ) ;
MPI_Recv(&c [ offset ] [ 0 ] , rowsNCB , MPI_DOUBLE , source , mtype ,
MPI_COMM_WORLD , &status ) ;
printf ( " Recei ved r e s u l t s from t as k %d\n" , source ) ;
}
65
/ Pri nt r e s u l t s /
printf ( "\n" ) ;
printf ( " Resul t Matri x : \ n" ) ;
f or ( i=0; i<NRA ; i++) {
70 printf ( "\n" ) ;
f or ( j=0; j<NCB ; j++)
printf ( "%6.2 f " , c [ i ] [ j ] ) ;
}
printf ( "\n\n" ) ;
75 printf ( "Done . \ n" ) ;
}
/ worker t as k /
i f ( taskid > MASTER ) {
80 / Recei ve matri x data from master t as k /
mtype = FROM_MASTER ;
MPI_Recv(&offset , 1 , MPI_INT , MASTER , mtype , MPI_COMM_WORLD ,&status ) ;
MPI_Recv(&rows , 1 , MPI_INT , MASTER , mtype , MPI_COMM_WORLD , &status ) ;
MPI_Recv(&a , rowsNCA , MPI_DOUBLE , MASTER , mtype , MPI_COMM_WORLD , &
status ) ;
85 MPI_Recv(&b , NCANCB , MPI_DOUBLE , MASTER , mtype , MPI_COMM_WORLD , &
status ) ;
/ Do matri x mul t i pl y /
f or ( k=0; k<NCB ; k++)
f or ( i=0; i<rows ; i++) {
90 c [ i ] [ k ] = 0 . 0 ;
f or ( j=0; j<NCA ; j++)
c [ i ] [ k ] = c [ i ] [ k ] + a [ i ] [ j ] b [ j ] [ k ] ;
}
95 / Send r e s u l t s back to master t ask /
mtype = FROM_WORKER ;
MPI_Send(&offset , 1 , MPI_INT , MASTER , mtype , MPI_COMM_WORLD ) ;
MPI_Send(&rows , 1 , MPI_INT , MASTER , mtype , MPI_COMM_WORLD ) ;
MPI_Send(&c , rowsNCB , MPI_DOUBLE , MASTER , mtype , MPI_COMM_WORLD ) ;
100 }
MPI_Finalize ( ) ;
}
29
ng Nguyn Phng Ti liu ni b NMTP
Ti liu
[1] William Gropp et al, MPICH2 Users Guide Version 1.0.6, Mathematics and Computer
Science Division, Argonne National Laboratory, 2007.
[2] Serrano Pereira, Building a simple Beowulf cluster with Ubuntu
http://byobu.info/article/Building_a_simple_Beowulf_cluster_with_Ubuntu/
[3] Blaise Barney, Message Passing Interface (MPI)
https://computing.llnl.gov/tutorials/mpi/
[4] Paul Burton, An Introduction to MPI Programming
http://www.ecmwf.int/services/computing/training/material/hpcf/Intro_MPI_
Programming.pdf
[5] Stefano Cozzini, MPI tutorial, Democritos/ICTP course in Tools for computational
physics, 2005
http://www.democritos.it/events/computational_physics/lecture_stefano4.pdf
[6] Ng Vn Thanh, Tnh ton song song
http://iop.vast.ac.vn/~nvthanh/cours/parcomp/
[7] https://www.surfsara.nl/systems/shared/mpi/mpi-intro
[8] http://chryswoods.com/book/export/html/117
[9] http://beige.ucs.indiana.edu/B673/node150.html
[10] http://www.cs.indiana.edu/classes/b673/notes/mpi1.html
[11] http://geco.mines.edu/workshop/class2/examples/mpi/index.html
[12] http://www.mcs.anl.gov/research/projects/mpi/usingmpi/examples/simplempi/
main.htm
30

You might also like