@@ -44,13 +44,13 @@ def write_input_file(args, ast, d, n):
44
44
return ifile
45
45
46
46
47
- def run_once (args , ast , rng ):
47
+ def run_once_with_primary (args , ast , rng , primary_idx ):
48
48
import sys , shutil , tempfile , json
49
49
r = {}
50
50
try :
51
51
d = tempfile .mkdtemp ()
52
52
inputs = [write_input_file (args , ast , d , i ) for i in rng ]
53
- primary = inputs [- 1 ]
53
+ primary = inputs [primary_idx ]
54
54
ofile = os .path .join (d , "out.o" )
55
55
mode = "-c"
56
56
if args .parse :
@@ -72,11 +72,13 @@ def run_once(args, ast, rng):
72
72
[line .split () for line in open (trace )]
73
73
if len (fields ) == 2 }
74
74
else :
75
+ if args .debug :
76
+ command = ["lldb" , "--" ] + command
75
77
stats = os .path .join (d , "stats.json" )
76
- subprocess . check_call (
77
- command + [ "-Xllvm" , "-stats" ,
78
- "-Xllvm" , "-stats-json" ,
79
- "-Xllvm" , "-info-output-file=" + stats ] )
78
+ argv = command + [ "-Xllvm" , "-stats" ,
79
+ "-Xllvm" , "-stats-json " ,
80
+ "-Xllvm" , "-info-output-file=" + stats ]
81
+ subprocess . check_call ( argv )
80
82
with open (stats ) as f :
81
83
r = json .load (f )
82
84
finally :
@@ -85,6 +87,20 @@ def run_once(args, ast, rng):
85
87
return {k :v for (k ,v ) in r .items () if args .select in k }
86
88
87
89
90
+ def run_once (args , ast , rng ):
91
+ if args .sum_multi :
92
+ cumulative = {}
93
+ for i in range (len (rng )):
94
+ tmp = run_once_with_primary (args , ast , rng , i )
95
+ for (k , v ) in tmp .items ():
96
+ if k in cumulative :
97
+ cumulative [k ] += v
98
+ else :
99
+ cumulative [k ] = v
100
+ return cumulative
101
+ else :
102
+ return run_once_with_primary (args , ast , rng , - 1 )
103
+
88
104
def run_many (args ):
89
105
90
106
if args .dtrace and has_debuginfo (args .swiftc_binary ):
@@ -101,23 +117,51 @@ def run_many(args):
101
117
102
118
ast = gyb .parse_template (args .file .name , args .file .read ())
103
119
rng = range (args .begin , args .end , args .step )
104
- if args .multi_file :
105
- return (rng , [run_once (args , ast , rng [ 0 : i + 1 ]) for i in range ( len ( rng )) ])
120
+ if args .multi_file or args . sum_multi :
121
+ return (rng , [run_once (args , ast , range ( i )) for i in rng ])
106
122
else :
107
123
return (rng , [run_once (args , ast , [r ]) for r in rng ])
108
124
109
125
126
+ def linear_regression (x , y ):
127
+ # By the book: https://en.wikipedia.org/wiki/Simple_linear_regression
128
+ n = len (x )
129
+ assert n == len (y )
130
+ if n == 0 :
131
+ return 0 , 0
132
+ prod_sum = 0
133
+ sum_x = sum (x )
134
+ sum_y = sum (y )
135
+ sum_prod = sum (a * b for a , b in zip (x , y ))
136
+ sum_x_sq = sum (a ** 2 for a in x )
137
+ mean_x = sum_x / n
138
+ mean_y = sum_y / n
139
+ mean_prod = sum_prod / n
140
+ mean_x_sq = sum_x_sq / n
141
+ covar_xy = mean_prod - mean_x * mean_y
142
+ var_x = mean_x_sq - mean_x ** 2
143
+ slope = covar_xy / var_x
144
+ inter = mean_y - slope * mean_x
145
+ return slope , inter
146
+
147
+
110
148
def report (args , rng , runs ):
111
- import numpy as np
149
+ import math
112
150
bad = False
113
151
keys = set .intersection (* [set (j .keys ()) for j in runs ])
114
- A = np .vstack ([np .log (rng ), np .ones (len (rng ))]).T
152
+ if len (keys ) == 0 :
153
+ print "No data found"
154
+ if len (args .select ) != 0 :
155
+ "(perhaps try a different --select?)"
156
+ return True
157
+ x = [math .log (n ) for n in rng ]
115
158
rows = []
116
159
for k in keys :
117
160
vals = [r [k ] for r in runs ]
118
161
bounded = [max (v , 1 ) for v in vals ]
119
- b , a = np .linalg .lstsq (A , np .log (bounded ))[0 ]
120
- b = 0 if np .isclose (b , 0 ) else b
162
+ y = [math .log (b ) for b in bounded ]
163
+ b , a = linear_regression (x , y )
164
+ b = 0 if abs (b ) < 1e-9 else b
121
165
rows .append ((b , k , vals ))
122
166
rows .sort ()
123
167
tolerance = 1.2
@@ -153,6 +197,9 @@ def main():
153
197
parser .add_argument (
154
198
'--multi-file' , action = 'store_true' ,
155
199
default = False , help = 'vary number of input files as well' )
200
+ parser .add_argument (
201
+ '--sum-multi' , action = 'store_true' ,
202
+ default = False , help = 'simulate a multi-primary run and sum stats' )
156
203
parser .add_argument (
157
204
'--begin' , type = int ,
158
205
default = 10 , help = 'first value for N' )
@@ -168,6 +215,9 @@ def main():
168
215
parser .add_argument (
169
216
'--select' ,
170
217
default = "" , help = 'substring of counters/symbols to restrict attention to' )
218
+ parser .add_argument (
219
+ '--debug' , action = 'store_true' ,
220
+ default = False , help = 'invoke lldb on each scale test' )
171
221
172
222
args = parser .parse_args (sys .argv [1 :])
173
223
(rng , runs ) = run_many (args )
0 commit comments