Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ouputs explicit C code to be included in the network model
[simgrid.git] / contrib / network_model / calibrate_piecewise.py
1 #!/usr/bin/env python
2
3
4 import sys
5 from math import sqrt
6
7
8 if len(sys.argv) < 5:
9    print("Usage : %s datafile links latency bandwidth [size...]" % sys.argv[0])
10    print("where : datafile is a SkaMPI pingpong measurement log file"); 
11    print("        links is the number of links between nodes")
12    print("        latency is the nominal latency given in the platform file")
13    print("        bandwidth is the nominal bandwidth given in the platform file")
14    print("        size are segments limits")
15    sys.exit(-1)
16
17 ##-----------------------------------------
18 ## avg : return average of a list of values
19 ## param l list of values
20 ##-----------------------------------------
21 def avg (l):
22    sum = 0
23    for e in l:
24       sum += float(e);
25    return sum / len(l)
26
27 ##-------------------------------------------------
28 ## cov : covariance
29 ## param X first data vector (..x_i..)
30 ## param Y second data vector (..x_i..)
31 ## = 1/n \Sum_{i=1}^n (x_i - avg(x)) * (y_i - avg(y))
32 ##--------------------------------------------------
33 def cov (X, Y):
34    assert len(X) == len(Y)
35    n = len(X)   #  n=len(X)=len(Y)
36    avg_X = avg(X)
37    avg_Y = avg(Y)
38    S_XY = 0.0
39    for i in range(n):
40       S_XY += (X[i] - avg_X) * (Y[i] - avg_Y)
41    return (S_XY / n)
42
43 ##---------------------------------------------------------------------
44 ## variance : variance
45 ## param X data vector ( ..x_i.. )
46 ## (S_X)^2 = (Sum ( x_i - avg(x) )^2 ) / n
47 ##---------------------------------------------------------------------
48 def variance (X):
49    n = len(X)
50    avg_X = avg (X)
51    S_X2 = 0.0
52    for i in range(n):
53       S_X2 += (X[i] - avg_X) ** 2
54    return (S_X2 / n)
55
56 ##---------------------------------------------------------------------
57 ## calibrate : output correction factors, c_lat on latency, c_bw on bw
58 ## such that bandwidth * c_bw = bw_regr, latency * c_lat = lat_regr
59 ## where bw_regr and lat_regr are the values approximatong experimental
60 ## observations.
61 ##
62 ## param links number of links traversed during ping-pong
63 ## param latency as specified on command line, in s
64 ## param bandwidth as specified on command line, in Byte/s
65 ## param sizes vector of data sizes, in Bytes
66 ## param timings vector of time taken: timings[i] for sizes[i], in us
67 ##---------------------------------------------------------------------
68 def calibrate (links, latency, bandwidth, sizes, timings):
69    assert len(sizes) == len(timings)
70    if len(sizes) < 2:
71       return None
72    # compute linear regression : find an affine form  a*size+b
73    S_XY = cov(sizes, timings)
74    S_X2 = variance(sizes)
75    a = S_XY / S_X2
76    b = avg(timings) - a * avg(sizes)
77    # corresponding bandwith, in s (was in us in skampi dat)
78    bw_regr = 1e6 / a     
79    # corresponding latency, in s (was in us in skampi dat)
80    lat_regr = b*1e-6
81    #print("\nregression: {0} * x + {1}".format(a,b))
82    #print("corr_bw = bw_regr/bandwidth= {0}/{1}={2}     lat_regr/(lat_xml*links)={3}/({4}*{5}))".format(bw_regr,bandwidth,bw_regr/bandwidth,lat_regr,latency,links))
83    # return correction factors c_bw,c_lat
84    return bw_regr/bandwidth, lat_regr/(latency*links)
85
86 ##-----------------------------------------------------------------------------------------------
87 ## main
88 ##-----------------------------------------------------------------------------------------------
89 links = int(sys.argv[2])
90 latency = float(sys.argv[3])
91 bandwidth = float(sys.argv[4])
92 skampidat = open(sys.argv[1], "r")
93
94 ## read data from skampi logs.
95 timings = []
96 sizes = []
97 readdata =[]
98 for line in skampidat:
99         l = line.split();
100         if line[0] != '#' and len(l) >= 3:   # is it a comment ?
101       ## expected format
102       ## ---------------
103       #count= 8388608  8388608  144916.1       7.6       32  144916.1  143262.0
104       #("%s %d %d %f %f %d %f %f\n" % (countlbl, count, countn, time, stddev, iter, mini, maxi)
105                 readdata.append( (int(l[1]),float(l[3]) / 2) );   # divide by 2 because of ping-pong measured
106
107 ## These may not be sorted so sort it by message size before processing.
108 sorteddata = sorted( readdata, key=lambda pair: pair[0])
109 sizes,timings= zip(*sorteddata)
110
111
112 ## adds message sizes of interest: if values are specified starting from the 6th command line arg 
113 ## and these values are found as message sizes in te log file, add it to the limits list.
114 ## Each of these value si considered a potential inflexion point between two segments.
115 ##
116 ## If no value specified, a single segment is considered from 1st to last message size logged.
117 limits = []
118 if len(sys.argv) > 5:
119    for i in range(5, len(sys.argv)):
120       limits += [idx for idx in range(len(sizes)) if sizes[idx] == int(sys.argv[i])]
121 limits.append(len(sizes) - 1)
122
123 factors = []
124 low = 0
125 for lim in limits:
126    correc = calibrate(links, latency, bandwidth, sizes[low:lim + 1], timings[low:lim + 1])
127    if correc:
128         # save interval [lb,ub] and correction factors for bw and lat resp.
129         factors.append( (sizes[low],sizes[lim], correc[0], correc[1]) )
130         print("Segment [%d:%d] --Bandwidth factor=%g --Latency factor=%g " % (sizes[low], sizes[lim], correc[0], correc[1]))
131    low = lim + 1
132
133 print("\n/**\n *------------------ <copy/paste C code snippet in surf/network.c> ----------------------")
134 print(" *\n * produced by: {0}\n *".format(' '.join(sys.argv)))
135 print(" *---------------------------------------------------------------------------------------\n **/")
136 print("static double smpi_bandwidth_factor(double size)\n{")                                
137 for (lb,ub,factor_bw,factor_lat) in factors:
138         print("\t /* case %d Bytes <= size <=%d Bytes */" % (lb,ub))
139         print("\t if (%d <= size && size <=  %d) {" % (lb,ub))
140         print("\t       return(%g);" % (factor_bw))
141         print("\t }")
142 print("}\n")  
143
144 print("static double smpi_latency_factor(double size)\n{")                                
145 for (lb,ub,factor_bw,factor_lat) in factors:
146         print("\t /* case %d Bytes <= size <=%d Bytes */" % (lb,ub))
147         print("\t if (%d <= size && size <=  %d) {" % (lb,ub))
148         print("\t       return(%g);" % (factor_lat))
149         print("\t }")
150 print("}\n")  
151 print("/**\n *------------------ </copy/paste C code snippet in surf/network.c> ---------------------\n **/")