Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Signature computation speedup #94

Merged
merged 6 commits into from
Apr 24, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions ufl/algorithms/signature.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
GeometricQuantity, ConstantValue, Constant,
ExprList, ExprMapping)
from ufl.log import error
from ufl.corealg.traversal import traverse_unique_terminals, pre_traversal
from ufl.corealg.traversal import traverse_unique_terminals, unique_post_traversal
from ufl.algorithms.domain_analysis import canonicalize_metadata


Expand Down Expand Up @@ -93,21 +93,22 @@ def compute_terminal_hashdata(expressions, renumbering):
return terminal_hashdata


def compute_expression_hashdata(expression, terminal_hashdata):
# The hashdata computed here can be interpreted as prefix operator
# notation, i.e. we store the equivalent of '+ * a b * c d' for
# the expression (a*b)+(c*d)
expression_hashdata = []
for expr in pre_traversal(expression):
def compute_expression_hashdata(expression, terminal_hashdata) -> bytes:
cache = {}

for expr in unique_post_traversal(expression):
# Uniquely traverse tree and hash each node
# E.g. (a + b*c) is hashed as hash([+, hash(a), hash([*, hash(b), hash(c)])])
# Traversal uses post pattern, so children hashes are cached
if expr._ufl_is_terminal_:
data = terminal_hashdata[expr]
data = [terminal_hashdata[expr]]
else:
data = expr._ufl_typecode_ # TODO: Use expr._ufl_signature_data_()? More extensible, but more overhead.
expression_hashdata.append(data)
# Oneliner: TODO: Benchmark, maybe use a generator?
# expression_hashdata = [(terminal_hashdata[expr] if expr._ufl_is_terminal_ else expr._ufl_typecode_)
# for expr in pre_traversal(expression)]
return expression_hashdata
data = [expr._ufl_typecode_]

for op in expr.ufl_operands:
data += [cache[op]]
wence- marked this conversation as resolved.
Show resolved Hide resolved
cache[expr] = hashlib.sha512(str(data).encode("utf-8")).digest()
wence- marked this conversation as resolved.
Show resolved Hide resolved
return cache[expression]


def compute_expression_signature(expr, renumbering): # FIXME: Fix callers
Expand All @@ -121,8 +122,7 @@ def compute_expression_signature(expr, renumbering): # FIXME: Fix callers

# Pass it through a seriously overkill hashing algorithm
# (should we use sha1 instead?)
data = str(expression_hashdata).encode("utf-8")
return hashlib.sha512(data).hexdigest()
return expression_hashdata.hex()


def compute_form_signature(form, renumbering): # FIXME: Fix callers
Expand Down