From 7d1a590ddc0d0dd4603ea1189e649062d3c05c30 Mon Sep 17 00:00:00 2001
From: Martin Bauer <martin.bauer@fau.de>
Date: Thu, 23 Feb 2017 17:30:09 +0100
Subject: [PATCH] Ensured that same method description produces exactly same
 code on two runs

- due to unordered containers  the same method could produce different but functionally equivalent code
- this behaviour is bad for caching

-> switched to ordered containers
---
 cpu/cpujit.py      |  3 ++-
 sympyextensions.py |  2 +-
 transformations.py | 12 +++++++-----
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/cpu/cpujit.py b/cpu/cpujit.py
index 20d414aeb..459359e3a 100644
--- a/cpu/cpujit.py
+++ b/cpu/cpujit.py
@@ -170,7 +170,8 @@ def compile(code, tmpDir, libFile, createAssemblyCode=False):
 def compileAndLoad(kernelFunctionNode):
     tmpDir = tempfile.mkdtemp()
     libFile = os.path.join(tmpDir, "jit.so")
-    compile(generateC(kernelFunctionNode), tmpDir, libFile)
+    sourceCode = generateC(kernelFunctionNode)
+    compile(sourceCode, tmpDir, libFile)
     loadedJitLib = cdll.LoadLibrary(libFile)
     shutil.rmtree(tmpDir)
 
diff --git a/sympyextensions.py b/sympyextensions.py
index 687f97d79..73dc9e2fa 100644
--- a/sympyextensions.py
+++ b/sympyextensions.py
@@ -129,7 +129,7 @@ def replaceSecondOrderProducts(expr, searchSymbols, positive=None, replaceMixed=
             else:
                 otherFactors *= t
         if len(distinctVelTerms) == 2 and nrOfVelTerms == 2:
-            u, v = list(distinctVelTerms)
+            u, v = sorted(list(distinctVelTerms), key=lambda symbol: symbol.name)
             if positive is None:
                 otherFactorsWithoutSymbols = otherFactors
                 for s in otherFactors.atoms(sp.Symbol):
diff --git a/transformations.py b/transformations.py
index e026cd379..e07b1de9c 100644
--- a/transformations.py
+++ b/transformations.py
@@ -1,4 +1,4 @@
-from collections import defaultdict
+from collections import defaultdict, OrderedDict
 from operator import attrgetter
 
 import sympy as sp
@@ -62,7 +62,7 @@ def makeLoopOverDomain(body, functionName, iterationSlice=None, ghostLayers=None
         if len(shapeSet) != 1:
             raise ValueError("Differently sized field accesses in loop body: " + str(shapeSet))
 
-    shape = list(shapeSet)[0]
+    shape = list(sorted(shapeSet, key=lambda e: str(e[0])))[0]
 
     if iterationSlice is not None:
         iterationSlice = normalizeSlice(iterationSlice, shape)
@@ -222,6 +222,9 @@ def resolveFieldAccesses(astNode, readOnlyFieldNames=set(), fieldToBasePointerIn
                                     counters to index the field these symbols are used as coordinates
     :return: transformed AST
     """
+    fieldToBasePointerInfo = OrderedDict(sorted(fieldToBasePointerInfo.items(), key=lambda pair: pair[0]))
+    fieldToFixedCoordinates = OrderedDict(sorted(fieldToFixedCoordinates.items(), key=lambda pair: pair[0]))
+
     def visitSympyExpr(expr, enclosingBlock, sympyAssignment):
         if isinstance(expr, Field.Access):
             fieldAccess = expr
@@ -359,9 +362,8 @@ def splitInnerLoop(astNode, symbolGroups):
     assert len(outerLoop) == 1, "Error in AST, multiple outermost loops."
     outerLoop = outerLoop[0]
 
-    symbolsWithTemporaryArray = dict()
-
-    assignmentMap = {a.lhs: a for a in innerLoop.body.args}
+    symbolsWithTemporaryArray = OrderedDict()
+    assignmentMap = OrderedDict((a.lhs, a) for a in innerLoop.body.args)
 
     assignmentGroups = []
     for symbolGroup in symbolGroups:
-- 
GitLab