提交 3e86efec authored 作者: Frédéric Bastien's avatar Frédéric Bastien 提交者: GitHub

Merge pull request #6143 from affanv14/metaopt

Implement Meta-optimizer on new backend
...@@ -1116,3 +1116,26 @@ import theano and print the config variable, as in: ...@@ -1116,3 +1116,26 @@ import theano and print the config variable, as in:
The number of user stack level to keep for variables during Theano The number of user stack level to keep for variables during Theano
compilation. If higher then 0, will make us keep Theano internal compilation. If higher then 0, will make us keep Theano internal
stack trace. stack trace.
.. attribute:: config.metaopt.verbose
Int value, default: 0
The verbosity level of the meta-optimizer. 0 for silent.
1 to only warn if we cannot meta-optimize some op.
2 for full output of separate timings and selected implementation
.. attribute:: config.metaopt.optimizer_excluding
Default: ``""``
A list of optimizer tags that we don't want included in the Meta-optimizer.
If multiple tags, separate them by ':'.
.. attribute:: config.metaopt.optimizer_including
Default: ``""``
A list of optimizer tags that we want included in the Meta-optimizer.
If multiple tags, separate them by ':'.
...@@ -1456,10 +1456,23 @@ AddConfigVar('blas.ldflags', ...@@ -1456,10 +1456,23 @@ AddConfigVar('blas.ldflags',
AddConfigVar( AddConfigVar(
'metaopt.verbose', 'metaopt.verbose',
"Enable verbose output for meta optimizers", "0 for silent, 1 for only warnings, 2 for full output with"
theano.configparser.BoolParam(False), "timings and selected implementation",
theano.configparser.IntParam(0),
in_c_key=False) in_c_key=False)
AddConfigVar('metaopt.optimizer_excluding',
("exclude optimizers with these tags. "
"Separate tags with ':'."),
StrParam(""),
in_c_key=False)
AddConfigVar('metaopt.optimizer_including',
("include optimizers with these tags. "
"Separate tags with ':'."),
StrParam(""),
in_c_key=False)
AddConfigVar('profile', AddConfigVar('profile',
"If VM should collect profile information", "If VM should collect profile information",
BoolParam(False), BoolParam(False),
......
...@@ -1131,13 +1131,20 @@ class LocalMetaOptimizer(LocalOptimizer): ...@@ -1131,13 +1131,20 @@ class LocalMetaOptimizer(LocalOptimizer):
""" """
def __init__(self, tracks=None, optimizers=()): def __init__(self):
self._tracks = tracks
self.optimizers = list(optimizers)
self.verbose = config.metaopt.verbose self.verbose = config.metaopt.verbose
self.track_dict = defaultdict(lambda: [])
self.tag_dict = defaultdict(lambda: [])
self._tracks = []
self.optimizers = []
def register(self, optimizer): def register(self, optimizer, tag_list):
self.optimizers.append(optimizer) self.optimizers.append(optimizer)
for c in optimizer.tracks():
self.track_dict[c].append(optimizer)
self._tracks.append(c)
for tag in tag_list:
self.tag_dict[tag].append(optimizer)
def tracks(self): def tracks(self):
return self._tracks return self._tracks
...@@ -1167,39 +1174,40 @@ class LocalMetaOptimizer(LocalOptimizer): ...@@ -1167,39 +1174,40 @@ class LocalMetaOptimizer(LocalOptimizer):
missing.difference_update(givens.keys()) missing.difference_update(givens.keys())
# ensure we have data for all input variables that need it # ensure we have data for all input variables that need it
if missing: if missing:
if self.verbose: if self.verbose > 0:
print(("%s cannot meta-optimize %s, " print(("%s cannot meta-optimize %s, "
"%d of %d input shapes unknown" % "%d of %d input shapes unknown" %
(self.__class__.__name__, node, len(missing), node.nin))) (self.__class__.__name__, node, len(missing), node.nin)))
return return
# now we can apply the different optimizations in turn, # now we can apply the different optimizations in turn,
# compile the resulting subgraphs and time their execution # compile the resulting subgraphs and time their execution
if self.verbose: if self.verbose > 1:
print(("%s meta-optimizing %s (%d choices):" % print(("%s meta-optimizing %s (%d choices):" %
(self.__class__.__name__, node, len(self.optimizers)))) (self.__class__.__name__, node, len(self.get_opts(node)))))
timings = [] timings = []
for opt in self.optimizers: for opt in self.get_opts(node):
outputs = opt.transform(node) outputs = opt.transform(node)
if outputs: if outputs:
try: try:
fn = theano.function([], outputs, givens=givens, fn = theano.function([], outputs, givens=givens,
on_unused_input='ignore') on_unused_input='ignore')
timing = min(self.time_call(fn) for _ in range(3)) fn.trust_input = True
timing = min(self.time_call(fn) for _ in range(2))
except Exception as e: except Exception as e:
if self.verbose: if self.verbose > 0:
print("* %s: exception" % opt, e) print("* %s: exception" % opt, e)
continue continue
else: else:
if self.verbose: if self.verbose > 1:
print("* %s: %.5g sec" % (opt, timing)) print("* %s: %.5g sec" % (opt, timing))
timings.append((timing, outputs, opt)) timings.append((timing, outputs, opt))
else: else:
if self.verbose: if self.verbose > 0:
print("* %s: not applicable" % opt) print("* %s: not applicable" % opt)
# finally, we choose the fastest one # finally, we choose the fastest one
if timings: if timings:
timings.sort() timings.sort()
if self.verbose: if self.verbose > 1:
print("= %s" % timings[0][2]) print("= %s" % timings[0][2])
return timings[0][1] return timings[0][1]
return return
...@@ -1213,6 +1221,12 @@ class LocalMetaOptimizer(LocalOptimizer): ...@@ -1213,6 +1221,12 @@ class LocalMetaOptimizer(LocalOptimizer):
""" """
raise NotImplementedError() raise NotImplementedError()
def get_opts(self, node):
"""
Can be overrided to change the way opts are selected
"""
return self.track_dict[type(node.op)]
def time_call(self, fn): def time_call(self, fn):
start = time.time() start = time.time()
fn() fn()
...@@ -2313,7 +2327,6 @@ class EquilibriumOptimizer(NavigatorOptimizer): ...@@ -2313,7 +2327,6 @@ class EquilibriumOptimizer(NavigatorOptimizer):
self.final_optimizers = [] self.final_optimizers = []
self.cleanup_optimizers = [] self.cleanup_optimizers = []
self.tracks_on_change_inputs = tracks_on_change_inputs self.tracks_on_change_inputs = tracks_on_change_inputs
for opt in optimizers: for opt in optimizers:
if isinstance(opt, LocalOptimizer): if isinstance(opt, LocalOptimizer):
if opt.tracks() is None: if opt.tracks() is None:
......
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论