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