Aproksimacija števila π se lahko dobi z naslednjim približkom
kjer se odgovor dobi s približkom, ki postaja boljši z naraščajočim N. Iteracije so med seboj neodvisne od i in s tem jih je tako možno paralelizirati. Za naslednje primere uporabite N=2310, ki je deljivo z 2,3,4,5,6,7,8,9,10,11 in 12
# -*- coding: utf-8 -*- pi0.py
from mpi4py import MPI
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
N = 2310
vsota=0.0
for i in range(N):
vsota += 1/(1+((i+0.5)/N)**2)
print "Pi = ", 4*vsota/N
half mpirun -np 2 python pi1.py
Upoštevajte, da je
range([start,] stop[, step]) -> list of integers
Na roke seštejte in preverite, če so delne vsote pravilne.
# -*- coding: utf-8 -*- pi1.py
from mpi4py import MPI
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
N = 2310
vsota = 0.0
start = rank*N/size
stop = (rank+1)*N/size
for i in range(start, stop):
vsota += 1/(1+((i+0.5)/N)**2)
print "%f rank %d [%d,%d]" % (4*vsota/N, rank, start, stop)
Za večje število procesov uporabimo awk
node mpirun -np 11 python pi1.py|awk '{sum+=$1}END{print "Pi=",sum}'
# -*- coding: utf-8 -*- pi2.py
from mpi4py import MPI
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
N = 2310
vsota = 0.0
start = rank*N/size
stop = (rank+1)*N/size
for i in range(start, stop):
vsota += 1/(1+((i+0.5)/N)**2)
if rank == 0:
for i in range(1, size):
vsota += comm.recv(source=i, tag=1)
print "Pi =", 4*vsota/N
else:
comm.send(vsota, dest=0, tag=1)
#..
pi = comm.reduce(vsota, op=MPI.SUM, root=0)
if rank == 0:
print "Pi =", 4*pi/N
pi = comm.bcast(vsota, root=0)
t0 = MPI.Wtime()
#... računamo
print "preteklo =", MPI.Wtime() - t0
deluje hitreje kot če zahtevate natančen vrstni red. Koliko procentov hitreje je wildcard sprejem? Poskusite ponoviti izračun večkrat, da dobite boljši povprečni rezultat. Kaj pa če naredimo dva dela kode, ki se hkrati izvajata in vsak računa svoj Pi. Ali lahko to potem ločimo v wildcard z izbiro tag-a?vsota += comm.recv(source=MPI.ANY_SOURCE, tag=1)
import math
#..
error = pi - math.pi