root / Pi / MP / PiMP.py @ 159
Historique | Voir | Annoter | Télécharger (7,5 ko)
1 |
#!/usr/bin/env python
|
---|---|
2 |
|
3 |
# Version using Multiprocessing module
|
4 |
#
|
5 |
# Pi-by-MC
|
6 |
#
|
7 |
# CC BY-NC-SA 2013 : <emmanuel.quemener@ens-lyon.fr>
|
8 |
#
|
9 |
|
10 |
import getopt |
11 |
import numpy |
12 |
|
13 |
from random import random |
14 |
# Multithread library call
|
15 |
from multiprocessing import Pool |
16 |
|
17 |
# Common tools
|
18 |
import sys |
19 |
import getopt |
20 |
import time |
21 |
import matplotlib.pyplot as plt |
22 |
import math |
23 |
from scipy.optimize import curve_fit |
24 |
from socket import gethostname |
25 |
|
26 |
# Predicted Amdahl Law (Reduced with s=1-p)
|
27 |
def AmdahlR(N, T1, p): |
28 |
return (T1*(1-p+p/N)) |
29 |
|
30 |
# Predicted Amdahl Law
|
31 |
def Amdahl(N, T1, s, p): |
32 |
return (T1*(s+p/N))
|
33 |
|
34 |
# Predicted Mylq Law with first order
|
35 |
def Mylq(N, T1,s,c,p): |
36 |
return (T1*(s+c*N+p/N))
|
37 |
|
38 |
# Predicted Mylq Law with second order
|
39 |
def Mylq2(N, T1,s,c1,c2,p): |
40 |
return (T1*(s+c1*N+c2*N*N+p/N))
|
41 |
|
42 |
def MainLoop(iterations): |
43 |
|
44 |
total=0
|
45 |
# Absulute necessary to use xrange instead of range to avoid out of memory !
|
46 |
for i in xrange(iterations): |
47 |
# Random access coordonate
|
48 |
x,y=random(),random() |
49 |
|
50 |
if ((x*x+y*y) < 1.0): |
51 |
total+=1
|
52 |
|
53 |
return(total)
|
54 |
|
55 |
def MetropolisMP(circle,iterations,steps,jobs): |
56 |
|
57 |
MyPi=numpy.zeros(steps) |
58 |
MyDuration=numpy.array([]) |
59 |
|
60 |
# Define iterations to send to each node
|
61 |
if iterations%jobs==0: |
62 |
iterationsMP=iterations/jobs |
63 |
else:
|
64 |
iterationsMP=iterations/jobs+1
|
65 |
print "%i iterations will be send to each core" % iterationsMP |
66 |
|
67 |
WorkItems=[] |
68 |
for i in xrange(0,jobs): |
69 |
WorkItems.append(iterationsMP) |
70 |
|
71 |
for i in xrange(steps): |
72 |
start=time.time() |
73 |
pool=Pool(processes=jobs) |
74 |
# Define the number of processes to be launched at a time
|
75 |
# pool=Pool(processes=CORES)
|
76 |
print "Start on %i processors..." % jobs |
77 |
# MAP: distribution of usecases T to be applied to MetropolisStrip
|
78 |
# WorkLaunches=[ pool.apply_async(MainLoop,(wi,)) for wi in WorkItems ]
|
79 |
# circle=[wl.get() for wl in WorkLaunches]
|
80 |
circle=pool.map(MainLoop,WorkItems) |
81 |
MyDuration=numpy.append(MyDuration,time.time()-start) |
82 |
MyPi[i]=4.*float(numpy.sum(circle))/float(iterationsMP)/float(jobs) |
83 |
|
84 |
return(numpy.mean(MyDuration),numpy.median(MyDuration),numpy.std(MyDuration))
|
85 |
|
86 |
def FitAndPrint(N,D,Curves): |
87 |
|
88 |
try:
|
89 |
coeffs_Amdahl, matcov_Amdahl = curve_fit(Amdahl, N, D) |
90 |
|
91 |
D_Amdahl=Amdahl(N,coeffs_Amdahl[0],coeffs_Amdahl[1],coeffs_Amdahl[2]) |
92 |
coeffs_Amdahl[1]=coeffs_Amdahl[1]*coeffs_Amdahl[0]/D[0] |
93 |
coeffs_Amdahl[2]=coeffs_Amdahl[2]*coeffs_Amdahl[0]/D[0] |
94 |
coeffs_Amdahl[0]=D[0] |
95 |
print "Amdahl Normalized: T=%.2f(%.6f+%.6f/N)" % \ |
96 |
(coeffs_Amdahl[0],coeffs_Amdahl[1],coeffs_Amdahl[2]) |
97 |
except:
|
98 |
print "Impossible to fit for Amdahl law : only %i elements" % len(D) |
99 |
|
100 |
try:
|
101 |
coeffs_AmdahlR, matcov_AmdahlR = curve_fit(AmdahlR, N, D) |
102 |
|
103 |
D_AmdahlR=AmdahlR(N,coeffs_AmdahlR[0],coeffs_AmdahlR[1]) |
104 |
coeffs_AmdahlR[1]=coeffs_AmdahlR[1]*coeffs_AmdahlR[0]/D[0] |
105 |
coeffs_AmdahlR[0]=D[0] |
106 |
print "Amdahl Reduced Normalized: T=%.2f(%.6f+%.6f/N)" % \ |
107 |
(coeffs_AmdahlR[0],1-coeffs_AmdahlR[1],coeffs_AmdahlR[1]) |
108 |
except:
|
109 |
print "Impossible to fit for Reduced Amdahl law : only %i elements" % len(D) |
110 |
|
111 |
try:
|
112 |
coeffs_Mylq, matcov_Mylq = curve_fit(Mylq, N, D) |
113 |
|
114 |
coeffs_Mylq[1]=coeffs_Mylq[1]*coeffs_Mylq[0]/D[0] |
115 |
coeffs_Mylq[2]=coeffs_Mylq[2]*coeffs_Mylq[0]/D[0] |
116 |
coeffs_Mylq[3]=coeffs_Mylq[3]*coeffs_Mylq[0]/D[0] |
117 |
coeffs_Mylq[0]=D[0] |
118 |
print "Mylq Normalized : T=%.2f(%.6f+%.6f*N+%.6f/N)" % (coeffs_Mylq[0], |
119 |
coeffs_Mylq[1],
|
120 |
coeffs_Mylq[2],
|
121 |
coeffs_Mylq[3])
|
122 |
D_Mylq=Mylq(N,coeffs_Mylq[0],coeffs_Mylq[1],coeffs_Mylq[2], |
123 |
coeffs_Mylq[3])
|
124 |
except:
|
125 |
print "Impossible to fit for Mylq law : only %i elements" % len(D) |
126 |
|
127 |
if Curves:
|
128 |
plt.xlabel("Number of Threads/work Items")
|
129 |
plt.ylabel("Total Elapsed Time")
|
130 |
|
131 |
Experience,=plt.plot(N,D,'ro')
|
132 |
try:
|
133 |
pAmdahl,=plt.plot(N,D_Amdahl,label="Loi de Amdahl")
|
134 |
pMylq,=plt.plot(N,D_Mylq,label="Loi de Mylq")
|
135 |
except:
|
136 |
print "Fit curves seem not to be available" |
137 |
|
138 |
plt.legend() |
139 |
plt.show() |
140 |
|
141 |
if __name__=='__main__': |
142 |
|
143 |
# Set defaults values
|
144 |
# Iterations is integer
|
145 |
Iterations=1000000
|
146 |
# JobStart in first number of Jobs to explore
|
147 |
JobStart=1
|
148 |
# JobEnd is last number of Jobs to explore
|
149 |
JobEnd=1
|
150 |
# Redo is the times to redo the test to improve metrology
|
151 |
Redo=1
|
152 |
# OutMetrology is method for duration estimation : False is GPU inside
|
153 |
OutMetrology=False
|
154 |
# Curves is True to print the curves
|
155 |
Curves=False
|
156 |
|
157 |
try:
|
158 |
opts, args = getopt.getopt(sys.argv[1:],"hoci:s:e:r:",["alu=","gpustyle=","parastyle=","iterations=","jobstart=","jobend=","redo=","device="]) |
159 |
except getopt.GetoptError:
|
160 |
print '%s -o (Out of Core Metrology) -c (Print Curves) -i <Iterations> -s <JobStart> -e <JobEnd> -r <RedoToImproveStats>' % sys.argv[0] |
161 |
sys.exit(2)
|
162 |
|
163 |
for opt, arg in opts: |
164 |
if opt == '-h': |
165 |
print '%s -o (Out of Core Metrology) -c (Print Curves) -i <Iterations> -s <JobStart> -e <JobEnd> -r <RedoToImproveStats>' % sys.argv[0] |
166 |
sys.exit() |
167 |
elif opt == '-o': |
168 |
OutMetrology=True
|
169 |
elif opt == '-c': |
170 |
Curves=True
|
171 |
elif opt in ("-i", "--iterations"): |
172 |
Iterations = numpy.uint32(arg) |
173 |
elif opt in ("-s", "--jobstart"): |
174 |
JobStart = int(arg)
|
175 |
elif opt in ("-e", "--jobend"): |
176 |
JobEnd = int(arg)
|
177 |
elif opt in ("-r", "--redo"): |
178 |
Redo = int(arg)
|
179 |
|
180 |
print "Iterations : %s" % Iterations |
181 |
print "Number of threads on start : %s" % JobStart |
182 |
print "Number of threads on end : %s" % JobEnd |
183 |
print "Number of redo : %s" % Redo |
184 |
print "Metrology done out : %r" % OutMetrology |
185 |
|
186 |
average=numpy.array([]).astype(numpy.float32) |
187 |
median=numpy.array([]).astype(numpy.float32) |
188 |
stddev=numpy.array([]).astype(numpy.float32) |
189 |
|
190 |
ExploredJobs=numpy.array([]).astype(numpy.uint32) |
191 |
|
192 |
Jobs=JobStart |
193 |
|
194 |
while Jobs <= JobEnd:
|
195 |
avg,med,std=0,0,0 |
196 |
ExploredJobs=numpy.append(ExploredJobs,Jobs) |
197 |
circle=numpy.zeros(Jobs).astype(numpy.uint32) |
198 |
|
199 |
if OutMetrology:
|
200 |
duration=numpy.array([]).astype(numpy.float32) |
201 |
for i in range(Redo): |
202 |
start=time.time() |
203 |
try:
|
204 |
MetropolisMP(circle,Iterations,Redo,Jobs) |
205 |
except:
|
206 |
print "Problem with %i // computations" % Jobs |
207 |
duration=numpy.append(duration,time.time()-start) |
208 |
avg=numpy.mean(duration) |
209 |
med=numpy.median(duration) |
210 |
std=numpy.std(duration) |
211 |
else:
|
212 |
try:
|
213 |
avg,med,std=MetropolisMP(circle,Iterations,Redo,Jobs) |
214 |
except:
|
215 |
print "Problem with %i // computations" % Jobs |
216 |
|
217 |
if (avg,med,std) != (0,0,0): |
218 |
print "avg,med,std",avg,med,std |
219 |
average=numpy.append(average,avg) |
220 |
median=numpy.append(median,med) |
221 |
stddev=numpy.append(stddev,std) |
222 |
else:
|
223 |
print "Values seem to be wrong..." |
224 |
# THREADS*=2
|
225 |
numpy.savez("Pi_%s_%i_%.8i_%s" % (JobStart,JobEnd,Iterations,gethostname()),(ExploredJobs,average,median,stddev))
|
226 |
Jobs+=1
|
227 |
|
228 |
FitAndPrint(ExploredJobs,median,Curves) |