提交 3c6281d1 authored 作者: James Bergstra's avatar James Bergstra

ENH: comments and all() syntax in vm.Stack

上级 b177065f
...@@ -209,6 +209,20 @@ class Stack(VM): ...@@ -209,6 +209,20 @@ class Stack(VM):
node_idx[node] = i node_idx[node] = i
self.apply_time[node] = 0 self.apply_time[node] = 0
self.outputs_size[node] = [] self.outputs_size[node] = []
# XXX: inconsistent style - why modify node here rather
# than track destroy_dependencies with dictionary like
# storage_map?
#
# destroy_dependencies
# --------------------
# The destroy_dependencies is a list of variables that are implicit
# dependencies induced by a destroy_map (compare node.inputs which
# are *explicit* dependencies). The variables in
# destroy_dependencies would be impossible to compute after the
# current `node` runs, because node.thunk() is going to destroy a
# common input variable needed by whatever node owns each variable
# in destroy_depenencies.
node.destroy_dependencies = [] node.destroy_dependencies = []
if node in ords: if node in ords:
for prereq in ords[node]: for prereq in ords[node]:
...@@ -272,32 +286,25 @@ class Stack(VM): ...@@ -272,32 +286,25 @@ class Stack(VM):
last_apply_stack_len = apply_stack_len last_apply_stack_len = apply_stack_len
current_apply = apply_stack.pop() current_apply = apply_stack.pop()
current_inputs = current_apply.inputs
current_outputs = current_apply.outputs
current_deps = current_inputs + current_apply.destroy_dependencies
# Use these for loops + breaks to short circuit evaluation computed_ins = all(compute_map[v][0] for v in current_deps)
# This is a significant performance point computed_outs = all(compute_map[v][0] for v in current_outputs)
computed_ins = True
for i in current_apply.inputs:
if not compute_map[i][0]:
computed_ins = False
break
computed_outs = True
for o in current_apply.outputs:
if not compute_map[o][0]:
computed_outs = False
break
if computed_ins:
for d in current_apply.destroy_dependencies:
if not compute_map[d][0]:
computed_ins = False
break
if not thunks[self.node_idx[current_apply]].lazy: if not thunks[self.node_idx[current_apply]].lazy:
#
# stack loop: Normal Non-Lazy Case
# ================================
#
# Check if all inputs are in place # Check if all inputs are in place
# If so compute thunk and remove it from the apply_stack # If so compute thunk and remove it from the apply_stack
# If not leave it in, and add to the apply_stack those # If not leave it in, and add to the apply_stack those
# that will produce you those inputs # that will produce you those inputs
if computed_ins and not computed_outs: if computed_ins and not computed_outs:
# -- Non-lazy case: have inputs, time to compute outputs
try: try:
_, dt = self.run_thunk_of_node(current_apply) _, dt = self.run_thunk_of_node(current_apply)
del _ del _
...@@ -325,30 +332,34 @@ class Stack(VM): ...@@ -325,30 +332,34 @@ class Stack(VM):
raise_with_op(current_apply) raise_with_op(current_apply)
for o in current_apply.outputs: for o in current_apply.outputs:
compute_map[o][0] = 1 compute_map[o][0] = 1
# Garbage Collection -> check if anybody else uses
# this input
if self.allow_gc: if self.allow_gc:
for i in current_apply.inputs: for i in current_apply.inputs:
if (dependencies[i] and i.owner # Garbage Collection -> check if anybody else uses
and i not in self.outputs): # this input
empty_storage_map = True if (dependencies[i]
for x in dependencies[i]: and i.owner
if not compute_map[x][0]: and i not in self.outputs):
empty_storage_map = False if all(compute_map[v][0]
break for v in dependencies[i]):
if empty_storage_map:
storage_map[i][0] = None storage_map[i][0] = None
compute_map[i][0] = 0
elif not computed_ins: elif not computed_ins:
# -- Non-lazy case, need inputs
apply_stack.append(current_apply) apply_stack.append(current_apply)
apply_stack.extend(inp.owner for inp apply_stack.extend(inp.owner
in current_apply.inputs if inp.owner) for inp in current_deps
apply_stack.extend(inp.owner for inp if inp.owner)
in current_apply.destroy_dependencies
if inp.owner)
elif not computed_outs: elif not computed_outs:
# Try and run it to see if it works #
# stack loop: Lazy Evaluation Case
# ================================
#
# Lazy evaluation protocol is to run the thunk with the
# current storage_map and compute_map accessed via closure,
# and the thunk will return a list of variables from its input
# list that it requires.
try: try:
requires, dt = self.run_thunk_of_node(current_apply) requires, dt = self.run_thunk_of_node(current_apply)
self.apply_time[current_apply] += dt self.apply_time[current_apply] += dt
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论