diff --git a/astnodes.py b/astnodes.py index f6c2d24de3cf93660b49d1ca563e3e92d49b694e..4a04a2a10d91bc1ff19d7e8ff835b215757a1967 100644 --- a/astnodes.py +++ b/astnodes.py @@ -1,5 +1,4 @@ import sympy as sp -import textwrap as textwrap from sympy.tensor import IndexedBase, Indexed from pystencils.field import Field from pystencils.types import TypedSymbol, DataType @@ -119,7 +118,7 @@ class KernelFunction(Node): def __str__(self): self._updateParameters() return '{0} {1}({2})\n{3}'.format(type(self).__name__, self.functionName, self.parameters, - textwrap.indent(str(self.body), '\t')) + ("\t" + "\t".join(str(self.body).splitlines(True)))) def __repr__(self): self._updateParameters() @@ -284,7 +283,7 @@ class LoopOverCoordinate(Node): def __str__(self): return 'loop:{!s} in {!s}:{!s}:{!s}\n{!s}'.format(self.loopCounterName, self.start, self.stop, self.step, - textwrap.indent(str(self.body), '\t')) + ("\t" + "\t".join(str(self.body).splitlines(True)))) def __repr__(self): return 'loop:{!s} in {!s}:{!s}:{!s}'.format(self.loopCounterName, self.start, self.stop, self.step) diff --git a/backends/cbackend.py b/backends/cbackend.py index 72be644e809d1bcfa0309b8e7acfe44711d578c7..dadb807c8e45e58ac2a15a68da3793d1fda85f63 100644 --- a/backends/cbackend.py +++ b/backends/cbackend.py @@ -1,4 +1,3 @@ -import textwrap from sympy.utilities.codegen import CCodePrinter from pystencils.astnodes import Node @@ -54,7 +53,7 @@ class PrintNode(CustomCppCode): # ------------------------------------------- Printer ------------------------------------------------------------------ -class CBackend: +class CBackend(object): def __init__(self, cuda=False, constantsAsFloats=False, sympyPrinter=None): self.cuda = cuda @@ -84,7 +83,7 @@ class CBackend: def _print_Block(self, node): blockContents = "\n".join([self._print(child) for child in node.args]) - return "{\n%s\n}" % (textwrap.indent(blockContents, self._indent)) + return "{\n%s\n}" % (self._indent + self._indent.join(blockContents.splitlines(True))) def _print_PragmaBlock(self, node): return "%s\n%s" % (node.pragmaLine, self._print_Block(node)) diff --git a/backends/dot.py b/backends/dot.py index 2c7e6ce2ce6c03ec901b0946a0c02162ce1ed2a8..b90ffc40a8434f16b8beac04495b5731d78d73c7 100644 --- a/backends/dot.py +++ b/backends/dot.py @@ -7,7 +7,7 @@ class DotPrinter(Printer): A printer which converts ast to DOT (graph description language). """ def __init__(self, nodeToStrFunction, **kwargs): - super().__init__() + super(DotPrinter, self).__init__() self._nodeToStrFunction = nodeToStrFunction self.dot = Digraph(**kwargs) self.dot.quote_edge = lang.quote diff --git a/cpu/cpujit.py b/cpu/cpujit.py index 1c578bc07854c57335e9174fed93e34422d95292..789d08a641a30e590995f1a9b67def34667ef76c 100644 --- a/cpu/cpujit.py +++ b/cpu/cpujit.py @@ -1,7 +1,9 @@ +from __future__ import print_function import os import subprocess from ctypes import cdll, c_double, c_float, sizeof -from tempfile import TemporaryDirectory +import tempfile +import shutil from pystencils.backends.cbackend import generateC import numpy as np import pickle @@ -31,11 +33,15 @@ CONFIG_INTEL_SUPERMUC = { } CONFIG_CLANG = { 'compiler': 'clang++', - 'flags': '-Ofast -DNDEBUG -fPIC -shared -march=native -fopenmp', + 'flags': '-Ofast -DNDEBUG -fPIC -shared -march=native ', } CONFIG = CONFIG_GCC +if CONFIG is CONFIG_CLANG and not 'Apple LLVM' in subprocess.check_output(['clang++', '--version']): + CONFIG_CLANG['flags'] += '-fopenmp' + + def ctypeFromString(typename, includePointers=True): import ctypes as ct @@ -85,7 +91,11 @@ def compile(code, tmpDir, libFile, createAssemblyCode=False): configEnv = CONFIG['env'] if 'env' in CONFIG else {} env = os.environ.copy() env.update(configEnv) - subprocess.call(compilerCmd, env=env) + try: + subprocess.check_output(compilerCmd, env=env, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + print(e.output) + raise e assembly = None if createAssemblyCode: @@ -97,10 +107,11 @@ def compile(code, tmpDir, libFile, createAssemblyCode=False): def compileAndLoad(kernelFunctionNode): - with TemporaryDirectory() as tmpDir: - libFile = os.path.join(tmpDir, "jit.so") - compile(generateC(kernelFunctionNode), tmpDir, libFile) - loadedJitLib = cdll.LoadLibrary(libFile) + tmpDir = tempfile.mkdtemp() + libFile = os.path.join(tmpDir, "jit.so") + compile(generateC(kernelFunctionNode), tmpDir, libFile) + loadedJitLib = cdll.LoadLibrary(libFile) + shutil.rmtree(tmpDir) return loadedJitLib @@ -187,7 +198,7 @@ def makePythonFunction(kernelFunctionNode, argumentDict={}): return lambda: func(*args) -class CachedKernel: +class CachedKernel(object): def __init__(self, configDict, ast, parameterValues): self.configDict = configDict self.ast = ast @@ -211,22 +222,23 @@ def hashToFunctionName(h): def createLibrary(cachedKernels, libraryFile): libraryInfoFile = libraryFile + ".info" - with TemporaryDirectory() as tmpDir: - code = "" - infoDict = {} - for cachedKernel in cachedKernels: - s = repr(sorted(cachedKernel.configDict.items())) - configHash = hashlib.sha1(s.encode()).hexdigest() - cachedKernel.ast.functionName = hashToFunctionName(configHash) - kernelCode = generateC(cachedKernel.ast) - code += kernelCode + "\n" - infoDict[configHash] = {'code': kernelCode, - 'parameterValues': cachedKernel.parameterValues, - 'configDict': cachedKernel.configDict, - 'parameterSpecification': cachedKernel.ast.parameters} - - compile(code, tmpDir, libraryFile) - pickle.dump(infoDict, open(libraryInfoFile, "wb")) + tmpDir = tempfile.mkdtemp() + code = "" + infoDict = {} + for cachedKernel in cachedKernels: + s = repr(sorted(cachedKernel.configDict.items())) + configHash = hashlib.sha1(s.encode()).hexdigest() + cachedKernel.ast.functionName = hashToFunctionName(configHash) + kernelCode = generateC(cachedKernel.ast) + code += kernelCode + "\n" + infoDict[configHash] = {'code': kernelCode, + 'parameterValues': cachedKernel.parameterValues, + 'configDict': cachedKernel.configDict, + 'parameterSpecification': cachedKernel.ast.parameters} + + compile(code, tmpDir, libraryFile) + pickle.dump(infoDict, open(libraryInfoFile, "wb")) + shutil.rmtree(tmpDir) def loadLibrary(libraryFile): diff --git a/equationcollection/equationcollection.py b/equationcollection/equationcollection.py index 91e483ef48bee5c4507af449c9e86f796b6e07c4..05787b5f3e6766b8415136fe463118d352d654ee 100644 --- a/equationcollection/equationcollection.py +++ b/equationcollection/equationcollection.py @@ -3,7 +3,7 @@ from copy import deepcopy from pystencils.sympyextensions import fastSubs, countNumberOfOperations, sortEquationsTopologically -class EquationCollection: +class EquationCollection(object): """ A collection of equations with subexpression definitions, also represented as equations, that are used in the main equations. EquationCollections can be passed to simplification methods. @@ -40,6 +40,9 @@ class EquationCollection: def __next__(self): self._ctr += 1 return sp.Symbol("xi_" + str(self._ctr)) + + def next(self): + return self.__next__() if subexpressionSymbolNameGenerator is None: self.subexpressionSymbolNameGenerator = SymbolGen() diff --git a/equationcollection/simplificationstrategy.py b/equationcollection/simplificationstrategy.py index 3162b9937de8e29c69eeec1fdedbbe6650a1067d..38f4c3f8b5918c56b8f9313d31b00a805cdd90d9 100644 --- a/equationcollection/simplificationstrategy.py +++ b/equationcollection/simplificationstrategy.py @@ -1,9 +1,8 @@ import sympy as sp -import textwrap from collections import namedtuple -class SimplificationStrategy: +class SimplificationStrategy(object): """ A simplification strategy is an ordered collection of simplification rules. Each simplification is a function taking an equation collection, and returning a new simplified @@ -71,15 +70,15 @@ class SimplificationStrategy: htmlTable += "</table>" return htmlTable - import time + import timeit report = Report() op = equationCollection.operationCount total = op['adds'] + op['muls'] + op['divs'] report.add(ReportElement("OriginalTerm", '-', op['adds'], op['muls'], op['divs'], total)) for t in self._rules: - startTime = time.perf_counter() + startTime = timeit.default_timer() equationCollection = t(equationCollection) - endTime = time.perf_counter() + endTime = timeit.default_timer() op = equationCollection.operationCount timeStr = "%.2f ms" % ((endTime - startTime) * 1000,) total = op['adds'] + op['muls'] + op['divs'] @@ -100,7 +99,7 @@ class SimplificationStrategy: if self.restrictSymbols: text += "\n".join([str(e) for e in eqColl.get(self.restrictSymbols)]) else: - text += textwrap.indent(str(eqColl), " " * 3) + text += (" " * 3 + (" " * 3).join(str(eqColl).splitlines(True))) return text result = printEqCollection("Initial Version", self.equationCollection) diff --git a/field.py b/field.py index 2b3c19e9da4a77dd9d718bb31d9d8f6395ceb1cd..acb31391f3eb7aeb78f65fe7c60eb975a9fb2c78 100644 --- a/field.py +++ b/field.py @@ -6,7 +6,7 @@ from sympy.tensor import IndexedBase from pystencils.types import TypedSymbol -class Field: +class Field(object): """ With fields one can formulate stencil-like update rules on structured grids. This Field class knows about the dimension, memory layout (strides) and optionally about the size of an array. diff --git a/llvm/control_flow.py b/llvm/control_flow.py index 9090d3de01714cc348608d821090fdc2dad9d8b4..bd138f6a04c4b273e176acff70b1a50bf1ad0514 100644 --- a/llvm/control_flow.py +++ b/llvm/control_flow.py @@ -1,7 +1,7 @@ import llvmlite.ir as ir -class Loop: +class Loop(object): def __init__(self, builder, start_val, stop_val, step_val=1, loop_name='loop', phi_name="_phi"): self.builder = builder self.start_val = start_val diff --git a/sympyextensions.py b/sympyextensions.py index 48e1b598b671025334cf55c4d6bc5e990eff75a3..687f97d79b7fbefdbdf7df471df054d966124eda 100644 --- a/sympyextensions.py +++ b/sympyextensions.py @@ -289,8 +289,8 @@ def mostCommonTermFactorization(term): if len(symbolsInFactorization) <= 1: return sp.Mul(commonFactor, term, evaluate=False) else: - return sp.Mul(commonFactor, *symbolsInFactorization[:-1], - constantsInFactorization * symbolsInFactorization[-1]) + args = symbolsInFactorization[:-1] + [constantsInFactorization * symbolsInFactorization[-1]] + return sp.Mul(commonFactor, *args) else: return sp.Mul(commonFactor, term, evaluate=False)