Statistiques
| Révision :

root / Pi / MP / PiMP-unprotected.py @ 84

Historique | Voir | Annoter | Télécharger (7,29 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
                MetropolisMP(circle,Iterations,Redo,Jobs)
204
                duration=numpy.append(duration,time.time()-start)
205
            avg=numpy.mean(duration)
206
            med=numpy.median(duration)
207
            std=numpy.std(duration)
208
        else:
209
            avg,med,std=MetropolisMP(circle,Iterations,Redo,Jobs)
210

    
211
        if (avg,med,std) != (0,0,0):
212
            print "avg,med,std",avg,med,std
213
            average=numpy.append(average,avg)
214
            median=numpy.append(median,med)
215
            stddev=numpy.append(stddev,std)
216
        else:
217
            print "Values seem to be wrong..."
218
        # THREADS*=2
219
        numpy.savez("Pi_%s_%i_%.8i_%s" % (JobStart,JobEnd,Iterations,gethostname()),(ExploredJobs,average,median,stddev))
220
        Jobs+=1
221

    
222
    FitAndPrint(ExploredJobs,median,Curves)