Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
H
hpvm-release
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
llvm
hpvm-release
Commits
9b49fd62
Commit
9b49fd62
authored
5 years ago
by
Elizabeth
Browse files
Options
Downloads
Patches
Plain Diff
Wrapped functionality in class for encapsulation and extensibility
parent
f08a6b06
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
llvm/projects/soc_simulator/src/driver.py
+200
-226
200 additions, 226 deletions
llvm/projects/soc_simulator/src/driver.py
with
200 additions
and
226 deletions
llvm/projects/soc_simulator/src/driver.py
+
200
−
226
View file @
9b49fd62
...
@@ -6,9 +6,9 @@ import sys
...
@@ -6,9 +6,9 @@ import sys
class
Driver
:
class
Driver
:
def
driver
(
self
):
def
driver
(
self
):
self
.
parse_tensor_layer_file
()
self
.
parse_tensor_layer_file
()
#
self.parse_tensor_table()
self
.
parse_tensor_table
()
#
self.run_simulations()
self
.
run_simulations
()
#
self.display_results()
self
.
display_results
()
def
__init__
(
self
,
layer_filename
,
table_filename
,
config_filename
,
results_filename
):
def
__init__
(
self
,
layer_filename
,
table_filename
,
config_filename
,
results_filename
):
self
.
__layer_filename
=
layer_filename
self
.
__layer_filename
=
layer_filename
...
@@ -21,6 +21,14 @@ class Driver:
...
@@ -21,6 +21,14 @@ class Driver:
# since it corresponds to the data in the configuration file
# since it corresponds to the data in the configuration file
self
.
__tensor_layers
=
[]
self
.
__tensor_layers
=
[]
# [layer_name][operation_name][cols]
# Operation names need to be stored in order of insertion
self
.
__tensor_table
=
defaultdict
(
lambda
:
list
(
defaultdict
(
str
)))
# [Time/Energy][number corresponding to order the layer config was read in] = time/energy
self
.
__aggregate_results
=
defaultdict
(
lambda
:
defaultdict
(
float
))
self
.
__config_count
=
0
@staticmethod
@staticmethod
def
is_conv
(
operation_name
):
def
is_conv
(
operation_name
):
return
operation_name
.
startswith
(
"
Conv
"
)
return
operation_name
.
startswith
(
"
Conv
"
)
...
@@ -33,12 +41,6 @@ class Driver:
...
@@ -33,12 +41,6 @@ class Driver:
def
is_fc
(
operation_name
):
def
is_fc
(
operation_name
):
return
operation_name
.
startswith
(
"
FC
"
)
return
operation_name
.
startswith
(
"
FC
"
)
def
driver
(
self
):
self
.
parse_tensor_layer_file
()
#self.parse_tensor_table()
#self.run_simulations()
#self.display_results()
def
parse_tensor_layer_file
(
self
):
def
parse_tensor_layer_file
(
self
):
if
not
os
.
path
.
isfile
(
self
.
__layer_filename
):
if
not
os
.
path
.
isfile
(
self
.
__layer_filename
):
print
(
"
ERROR: %s was not found.
"
%
self
.
__layer_filename
)
print
(
"
ERROR: %s was not found.
"
%
self
.
__layer_filename
)
...
@@ -75,234 +77,206 @@ class Driver:
...
@@ -75,234 +77,206 @@ class Driver:
self
.
__tensor_layers
.
append
(
tensor_layer
)
self
.
__tensor_layers
.
append
(
tensor_layer
)
layer_file
.
close
()
layer_file
.
close
()
'''
# [layer_name][operation_name][cols]
# Operation names need to be stored in order of insertion
tensor_table = defaultdict(lambda: list(defaultdict(str)))
def parse_tensor_table(table_filename):
if not os.path.isfile(table_filename):
print(
"
ERROR: %s was not found.
"
% table_filename)
exit(1)
table_file = open(table_filename,
"
r
"
)
line = table_file.readline().strip()
while line:
def
parse_tensor_table
(
self
):
# Line here MUST be a header or there
'
s a bug
if
not
os
.
path
.
isfile
(
self
.
__table_filename
):
# Get the description of the layer
print
(
"
ERROR: %s was not found.
"
%
self
.
__table_filename
)
assert(line.startswith(
"
**
"
))
exit
(
1
)
table_file
=
open
(
self
.
__table_filename
,
"
r
"
)
line
=
table_file
.
readline
().
strip
()
while
line
:
# Line here MUST be a header or there's a bug
# Get the description of the layer
assert
(
line
.
startswith
(
"
**
"
))
header_contents
=
line
.
split
(
'
'
)[
1
:]
layer_name
=
header_contents
[
0
]
num_ops
=
int
(
header_contents
[
1
])
col_names
=
header_contents
[
2
:]
layer_operations
=
[]
header_contents = line.split(
'
'
)[1:]
# Go through all operations in the layer
layer_name = header_contents[0]
for
op_count
in
range
(
num_ops
):
num_ops = int(header_contents[1])
operation_data
=
defaultdict
(
str
)
col_names = header_contents[2:]
layer_operations = []
line
=
table_file
.
readline
().
strip
()
op_data
=
line
.
split
(
'
'
)
op_name
=
op_data
[
0
]
operation_data
[
"
Name
"
]
=
op_name
# Go through all operations in the layer
# Number of data items (#s) needs to match up with the # of cols
for op_count in range(num_ops):
assert
(
len
(
op_data
)
-
1
==
len
(
col_names
))
operation_data = defaultdict(str)
# Go through all data items (each col element) per operation
for
i
in
range
(
len
(
col_names
)):
operation_data
[
col_names
[
i
]]
=
float
(
op_data
[
i
+
1
])
layer_operations
.
append
(
operation_data
)
self
.
__tensor_table
[
layer_name
]
=
layer_operations
line
=
table_file
.
readline
().
strip
()
line
=
table_file
.
readline
().
strip
()
op_data = line.split(
'
'
)
table_file
.
close
()
op_name = op_data[0]
operation_data[
"
Name
"
] = op_name
# Number of data items (#s) needs to match up with the # of cols
fp16_swing
=
8
assert(len(op_data) - 1 == len(col_names))
# Go through all data items (each col element) per operation
class
ApproxTypes
:
for i in range(len(col_names)):
FP16
=
0
operation_data[col_names[i]] = float(op_data[i + 1])
FP32
=
1
PROMISE
=
2
layer_operations.append(operation_data)
@staticmethod
def
is_promise
(
config_layer
):
return
float
(
config_layer
.
split
(
'
'
)[
0
])
<
Driver
.
fp16_swing
def
__quantize
(
self
,
curr_layer
,
prev_layer
,
h2f_f2h_operation_ind
,
layer_data
):
if
curr_layer
==
prev_layer
or
curr_layer
==
Driver
.
ApproxTypes
.
PROMISE
\
or
prev_layer
==
Driver
.
ApproxTypes
.
PROMISE
:
# No quantization needed
return
0.0
,
0.0
layer_name
=
layer_data
[
"
Name
"
]
# NOTE: Ignoring logic where curr == promise or prev == promise bc
# smartDMA is always true so we'd return near the beginning of the method
# Get h2f/f2h data using the first tensor operation in the layer
# (which is why order matters in the tensor table)
tensor_op_row
=
self
.
__tensor_table
[
layer_name
][
h2f_f2h_operation_ind
]
if
curr_layer
==
Driver
.
ApproxTypes
.
FP32
:
time
=
tensor_op_row
[
"
h2f_time
"
]
energy
=
tensor_op_row
[
"
h2f_energy
"
]
elif
curr_layer
==
Driver
.
ApproxTypes
.
FP16
:
time
=
tensor_op_row
[
"
f2h_time
"
]
energy
=
tensor_op_row
[
"
f2h_energy
"
]
print
(
"
Quantization: (%f, %f)
"
%
(
time
,
energy
))
return
(
time
,
energy
)
def
__run_promise_simulation
(
self
,
swing
,
layer_data
):
layer_name
=
layer_data
[
"
Name
"
]
patch_factor
=
1
if
Driver
.
is_conv
(
layer_name
):
rows_a
=
layer_data
[
"
N
"
]
*
layer_data
[
"
H
"
]
*
layer_data
[
"
W
"
]
\
/
(
layer_data
[
"
Sh
"
]
*
layer_data
[
"
Sw
"
])
cols_a
=
layer_data
[
"
Cin
"
]
*
layer_data
[
"
Kh
"
]
*
layer_data
[
"
Kw
"
]
rows_b
=
cols_a
cols_b
=
layer_data
[
"
Cout
"
]
patch_factor
=
layer_data
[
"
Kh
"
]
*
layer_data
[
"
Kw
"
]
elif
Driver
.
is_fc
(
layer_name
):
rows_a
=
layer_data
[
"
RA
"
]
cols_a
=
layer_data
[
"
CA
"
]
rows_b
=
cols_a
cols_b
=
layer_data
[
"
CB
"
]
else
:
print
(
"
PROMISE can
'
t run whatever this layer is.
"
)
exit
(
1
)
# Run promise simulator
# TODO need to print time and energy in the ptm runner so we can pipe it
output
=
subprocess
.
Popen
([
"
./ptm
"
,
str
(
rows_a
),
str
(
cols_a
),
str
(
rows_b
),
\
str
(
cols_b
),
str
(
patch_factor
),
str
(
swing
)],
\
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
).
communicate
()[
0
]
total_time_energy
=
output
.
strip
().
split
(
'
,
'
)
assert
(
len
(
total_time_energy
)
==
2
)
print
(
"
PROMISE: (%s, %s)
"
%
(
total_time_energy
[
0
],
total_time_energy
[
1
]))
return
float
(
total_time_energy
[
0
]),
float
(
total_time_energy
[
1
])
def
__run_gpu_simulation
(
self
,
curr_layer
,
layer_name
,
tensor_ind
):
tensor_info
=
self
.
__tensor_table
[
layer_name
][
tensor_ind
]
if
curr_layer
==
Driver
.
ApproxTypes
.
FP32
:
conversion_time
=
tensor_info
[
"
fp32_time
"
]
conversion_energy
=
tensor_info
[
"
fp32_energy
"
]
else
:
conversion_time
=
tensor_info
[
"
fp16_time
"
]
conversion_energy
=
tensor_info
[
"
fp16_energy
"
]
print
(
"
GPU: (%f, %f)
"
%
(
conversion_time
,
conversion_energy
))
return
(
conversion_time
,
conversion_energy
)
# Default dict of default dicts
results_time_key
=
"
Time
"
results_energy_key
=
"
Energy
"
def
run_simulations
(
self
):
print
(
"
run sim
"
)
if
not
os
.
path
.
isfile
(
self
.
__config_filename
):
print
(
"
ERROR: %s was not found
"
%
self
.
__config_filename
)
exit
(
1
)
tensor_table[layer_name] = layer_operations
config_file
=
open
(
self
.
__config_filename
,
"
r
"
)
line = table_file.readline().strip()
table_file.close()
# each line = indepedent configuration
# layers are separated by commas
fp16_swing = 8
# tensor ops are separated by spaces
for
config
in
config_file
:
class ApproxTypes:
config_layers
=
config
.
strip
().
split
(
'
,
'
)
FP16 = 0
prev_layer
=
Driver
.
ApproxTypes
.
FP32
FP32 = 1
curr_layer
=
None
PROMISE = 2
for
layer_ind
,
config_layer
in
enumerate
(
config_layers
):
# level
def get_approx_type(approx_type):
layer_data
=
self
.
__tensor_layers
[
layer_ind
]
# layer
if approx_type == 0:
layer_name
=
layer_data
[
"
Name
"
]
return
"
fp16
"
elif approx_type == 1:
if
Driver
.
is_promise
(
config_layer
):
return
"
fp32
"
print
(
"
Running layer %s on PROMISE
"
%
layer_name
)
return
"
promise
"
curr_layer
=
Driver
.
ApproxTypes
.
PROMISE
quant_time
,
quant_energy
=
self
.
__quantize
(
curr_layer
,
prev_layer
,
0
,
layer_data
)
def Driver.is_promise(config_layer):
# Compute
# TODO overhead in call to split?
time
,
energy
=
self
.
__run_promise_simulation
(
config_layer
,
layer_data
)
return float(config_layer.split(
'
'
)[0]) < fp16_swing
print
(
time
,
energy
)
self
.
__aggregate_results
[
Driver
.
results_time_key
][
self
.
__config_count
]
+=
time
self
.
__aggregate_results
[
Driver
.
results_energy_key
][
self
.
__config_count
]
+=
energy
def quantize(curr_layer, prev_layer, h2f_f2h_operation_ind, layer_data):
else
:
#print(get_approx_type(curr_layer), get_approx_type(prev_layer))
print
(
"
Running layer %s on the GPU
"
%
layer_name
)
if curr_layer == prev_layer or curr_layer == ApproxTypes.PROMISE
\
tensor_ops
=
config_layer
.
split
(
'
'
)
or prev_layer == ApproxTypes.PROMISE: # No quantization needed
return 0.0, 0.0
total_time
=
0
total_energy
=
0
layer_name = layer_data[
"
Name
"
]
for
tensor_ind
,
tensor_op
in
enumerate
(
tensor_ops
):
# sublevle
tensor_op
=
int
(
tensor_op
)
# NOTE: Ignoring logic where curr == promise or prev == promise bc
if
tensor_op
==
Driver
.
fp16_swing
:
# smartDMA is always true so we
'
d return near the beginning of the method
curr_layer
=
Driver
.
ApproxTypes
.
FP16
else
:
# Get h2f/f2h data using the first tensor operation in the layer
curr_layer
=
Driver
.
ApproxTypes
.
FP32
# (which is why order matters in the tensor table)
quant_time
,
quant_energy
=
self
.
__quantize
(
curr_layer
,
prev_layer
,
tensor_ind
,
layer_data
)
tensor_op_row = tensor_table[layer_name][h2f_f2h_operation_ind]
conv_time
,
conv_energy
=
self
.
__run_gpu_simulation
(
curr_layer
,
layer_name
,
tensor_ind
)
if curr_layer == ApproxTypes.FP32:
total_time
+=
quant_time
+
conv_time
time = tensor_op_row[
"
h2f_time
"
]
total_energy
+=
quant_energy
+
conv_energy
energy = tensor_op_row[
"
h2f_energy
"
]
elif curr_layer == ApproxTypes.FP16:
self
.
__aggregate_results
[
Driver
.
results_time_key
][
self
.
__config_count
]
+=
total_time
time = tensor_op_row[
"
f2h_time
"
]
self
.
__aggregate_results
[
Driver
.
results_energy_key
][
self
.
__config_count
]
+=
total_energy
energy = tensor_op_row[
"
f2h_energy
"
]
prev_layer
=
curr_layer
print(
"
Quantization: (%f, %f)
"
% (time, energy))
self
.
__config_count
+=
1
return (time, energy)
print
(
"
\n
"
)
config_file
.
close
()
def run_promise_simulation(swing, layer_data):
layer_name = layer_data[
"
Name
"
]
def
display_results
(
self
):
patch_factor = 1
results_file
=
open
(
self
.
__results_filename
,
"
w
"
)
attributes_to_print
=
[
Driver
.
results_time_key
,
Driver
.
results_energy_key
]
if Driver.is_conv(layer_name):
rows_a = layer_data[
"
N
"
] * layer_data[
"
H
"
] * layer_data[
"
W
"
]
\
for
attribute
in
attributes_to_print
:
/ (layer_data[
"
Sh
"
] * layer_data[
"
Sw
"
])
results_file
.
write
(
"
%s
\n
"
%
attribute
)
cols_a = layer_data[
"
Cin
"
] * layer_data[
"
Kh
"
] * layer_data[
"
Kw
"
]
results_file
.
write
(
"
Configuration,Total,Improvement
\n
"
)
rows_b = cols_a
cols_b = layer_data[
"
Cout
"
]
baseline_val
=
self
.
__aggregate_results
[
attribute
][
0
]
patch_factor = layer_data[
"
Kh
"
] * layer_data[
"
Kw
"
]
print
(
baseline_val
)
elif Driver.is_fc(layer_name):
best_config
=
None
rows_a = layer_data[
"
RA
"
]
best_result
=
None
cols_a = layer_data[
"
CA
"
]
rows_b = cols_a
for
config_ind
in
range
(
self
.
__config_count
):
cols_b = layer_data[
"
CB
"
]
results_file
.
write
(
"
c%d
"
%
config_ind
)
else:
time_or_energy_val
=
self
.
__aggregate_results
[
attribute
][
config_ind
]
print(
"
PROMISE can
'
t run whatever this layer is.
"
)
results_file
.
write
(
"
,%f
"
%
time_or_energy_val
)
exit(1)
results_file
.
write
(
"
,%f
\n
"
%
(
baseline_val
/
(
time_or_energy_val
+
0.0001
)))
#print(
"
[%f x %f] x [%f x %f] : %f
"
% (rows_a, cols_a, rows_b, cols_b, swing))
# Run promise simulator
if
not
best_result
or
time_or_energy_val
<
best_result
:
# TODO need to print time and energy in the ptm runner so we can pipe it
best_result
=
time_or_energy_val
output = subprocess.Popen([
"
./ptm
"
, str(rows_a), str(cols_a), str(rows_b),
\
best_config
=
config_ind
str(cols_b), str(patch_factor), str(swing)],
\
results_file
.
write
(
"
\n
c%d,%f
\n\n
"
%
(
best_config
,
self
.
__aggregate_results
[
attribute
][
best_config
]))
stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()[0]
results_file
.
close
()
total_time_energy = output.strip().split(
'
,
'
)
assert(len(total_time_energy) == 2)
print(
"
PROMISE: (%s, %s)
"
% (total_time_energy[0], total_time_energy[1]))
return float(total_time_energy[0]), float(total_time_energy[1])
def run_gpu_simulation(curr_layer, layer_name, tensor_ind):
tensor_info = tensor_table[layer_name][tensor_ind]
if curr_layer == ApproxTypes.FP32:
conversion_time = tensor_info[
"
fp32_time
"
]
conversion_energy = tensor_info[
"
fp32_energy
"
]
else:
conversion_time = tensor_info[
"
fp16_time
"
]
conversion_energy = tensor_info[
"
fp16_energy
"
]
print(
"
GPU: (%f, %f)
"
% (conversion_time, conversion_energy))
return (conversion_time, conversion_energy)
# Default dict of default dicts
results_time_key =
"
Time
"
results_energy_key =
"
Energy
"
# [Time/Energy][number corresponding to order the layer config was read in] = time/energy
aggregate_results = defaultdict(lambda: defaultdict(float))
config_count = 0
def run_simulations(config_filename):
global config_count
if not os.path.isfile(config_filename):
print(
"
ERROR: %s was not found
"
% config_filename)
exit(1)
config_file = open(config_filename,
"
r
"
)
# each line = indepedent configuration
# layers are separated by commas
# tensor ops are separated by spaces
for config in config_file:
config_layers = config.strip().split(
'
,
'
)
prev_layer = ApproxTypes.FP32
curr_layer = None
for layer_ind, config_layer in enumerate(config_layers): # level
layer_data = tensor_layers[layer_ind] # layer
layer_name = layer_data[
"
Name
"
]
if Driver.is_promise(config_layer):
print(
"
Running layer %s on PROMISE
"
% layer_name)
curr_layer = ApproxTypes.PROMISE
quant_time, quant_energy = quantize(curr_layer, prev_layer, 0, layer_data)
# Compute
time, energy = run_promise_simulation(config_layer, layer_data)
print(time, energy)
aggregate_results[results_time_key][config_count] += time
aggregate_results[results_energy_key][config_count] += energy
else:
print(
"
Running layer %s on the GPU
"
% layer_name)
tensor_ops = config_layer.split(
'
'
)
total_time = 0
total_energy = 0
for tensor_ind, tensor_op in enumerate(tensor_ops): # sublevle
tensor_op = int(tensor_op)
if tensor_op == fp16_swing:
curr_layer = ApproxTypes.FP16
else:
curr_layer = ApproxTypes.FP32
quant_time, quant_energy = quantize(curr_layer, prev_layer, tensor_ind,
\
layer_data)
conv_time, conv_energy = run_gpu_simulation(curr_layer, layer_name, tensor_ind)
total_time += quant_time + conv_time
total_energy += quant_energy + conv_energy
aggregate_results[results_time_key][config_count] += total_time
aggregate_results[results_energy_key][config_count] += total_energy
prev_layer = curr_layer
config_count += 1
print(
"
\n
"
)
config_file.close()
def display_results(results_filename):
results_file = open(results_filename,
"
w
"
)
attributes_to_print = [results_time_key, results_energy_key]
for attribute in attributes_to_print:
results_file.write(
"
%s
\n
"
% attribute)
results_file.write(
"
Configuration,Total,Improvement
\n
"
)
baseline_val = aggregate_results[attribute][0]
print(baseline_val)
best_config = None
best_result = None
for config_ind in range(config_count):
results_file.write(
"
c%d
"
% config_ind)
time_or_energy_val = aggregate_results[attribute][config_ind]
results_file.write(
"
,%f
"
% time_or_energy_val)
results_file.write(
"
,%f
\n
"
% (baseline_val / (time_or_energy_val + 0.0001)))
if not best_result or time_or_energy_val < best_result:
best_result = time_or_energy_val
best_config = config_ind
results_file.write(
"
\n
c%d,%f
\n\n
"
% (best_config, aggregate_results[attribute][best_config]))
results_file.close()
def driver(tensor_layers_file, tensor_table_file, conf_file, output_file):
print(tensor_layers_file, tensor_table_file, conf_file, output_file)
parse_tensor_layer_file(tensor_layers_file)
parse_tensor_table(tensor_table_file)
run_simulations(conf_file)
display_results(output_file)
'''
if
__name__
==
"
__main__
"
:
if
__name__
==
"
__main__
"
:
if
len
(
sys
.
argv
)
!=
5
:
if
len
(
sys
.
argv
)
!=
5
:
print
(
"
Usage: python driver.py <layer info> <tensor info> <configurations> <results file>
"
)
print
(
"
Usage: python driver.py <layer info> <tensor info> <configurations> <results file>
"
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment