diff --git a/cpu/cpujit.py b/cpu/cpujit.py index f79ff7c5605c3eaa7d5ecd9c52795b5f002b6ba1..18429d1200c9a04f0c50cb7abc994c43398ff63a 100644 --- a/cpu/cpujit.py +++ b/cpu/cpujit.py @@ -7,6 +7,8 @@ import numpy as np import pickle import hashlib +from pystencils.transformations import symbolNameToVariableName + CONFIG_GCC = { 'compiler': 'g++', 'flags': '-Ofast -DNDEBUG -fPIC -shared -march=native -fopenmp', @@ -104,6 +106,7 @@ def compileAndLoad(kernelFunctionNode): def buildCTypeArgumentList(parameterSpecification, argumentDict): + argumentDict = {symbolNameToVariableName(k): v for k, v in argumentDict.items()} ctArguments = [] for arg in parameterSpecification: if arg.isFieldArgument: diff --git a/field.py b/field.py index e0835bc6f5d96ea75da7b2d931b16b75bb31f3ae..70031708aa9c2c0686c9942ba3865db96c0735c3 100644 --- a/field.py +++ b/field.py @@ -74,6 +74,7 @@ class Field: def createGeneric(fieldName, spatialDimensions, dtype=np.float64, indexDimensions=0, layout='numpy'): """ Creates a generic field where the field size is not fixed i.e. can be called with arrays of different sizes + :param fieldName: symbolic name for the field :param dtype: numpy data type of the array the kernel is called with later :param spatialDimensions: see documentation of Field diff --git a/gpucuda/cudajit.py b/gpucuda/cudajit.py index 077e755d0e79e7a887408ab461a687c555e5992e..71c00832e008c7ca5c78b7cbe53cb6c38e285e4c 100644 --- a/gpucuda/cudajit.py +++ b/gpucuda/cudajit.py @@ -4,6 +4,7 @@ import pycuda.autoinit from pycuda.compiler import SourceModule from pycuda.gpuarray import GPUArray from pystencils.backends.cbackend import generateCUDA +from pystencils.transformations import symbolNameToVariableName def numpyTypeFromString(typename, includePointers=True): @@ -34,6 +35,7 @@ def numpyTypeFromString(typename, includePointers=True): def buildNumpyArgumentList(kernelFunctionNode, argumentDict): + argumentDict = {symbolNameToVariableName(k): v for k, v in argumentDict.items()} result = [] for arg in kernelFunctionNode.parameters: if arg.isFieldArgument: diff --git a/gpucuda/kernelcreation.py b/gpucuda/kernelcreation.py index d2394304a8d14d97a9bbc107e90159504a8ec688..f3b68c2f7eafdf2d2ccffbf9552911bee637c141 100644 --- a/gpucuda/kernelcreation.py +++ b/gpucuda/kernelcreation.py @@ -39,6 +39,8 @@ def createCUDAKernel(listOfEquations, functionName="kernel", typeForSymbol=None) fieldsRead, fieldsWritten, assignments = typeAllEquations(listOfEquations, typeForSymbol) readOnlyFields = set([f.name for f in fieldsRead - fieldsWritten]) + allFields = fieldsRead.union(fieldsWritten) + code = KernelFunction(Block(assignments), fieldsRead.union(fieldsWritten), functionName) code.globalVariables.update(BLOCK_IDX + THREAD_IDX) @@ -49,7 +51,9 @@ def createCUDAKernel(listOfEquations, functionName="kernel", typeForSymbol=None) allFields = fieldsRead.union(fieldsWritten) basePointerInfo = [['spatialInner0']] basePointerInfos = {f.name: parseBasePointerInfo(basePointerInfo, [2, 1, 0], f) for f in allFields} - resolveFieldAccesses(code, readOnlyFields, fieldToFixedCoordinates={'src': coordMapping, 'dst': coordMapping}, + + coordMapping = {f.name: coordMapping for f in allFields} + resolveFieldAccesses(code, readOnlyFields, fieldToFixedCoordinates=coordMapping, fieldToBasePointerInfo=basePointerInfos) # add the function which determines #blocks and #threads as additional member to KernelFunction node # this is used by the jit diff --git a/transformations.py b/transformations.py index b39bd92b2dd289014c85a64146c78e5bfa94c7f9..f3f3675f00d02a2fba3c8067dc4b8a15d1abba19 100644 --- a/transformations.py +++ b/transformations.py @@ -226,7 +226,7 @@ def resolveFieldAccesses(astNode, readOnlyFieldNames=set(), fieldToBasePointerIn if field.name in readOnlyFieldNames: dtype.const = True - fieldPtr = TypedSymbol("%s%s" % (Field.DATA_PREFIX, field.name), dtype) + fieldPtr = TypedSymbol("%s%s" % (Field.DATA_PREFIX, symbolNameToVariableName(field.name)), dtype) lastPointer = fieldPtr @@ -392,6 +392,11 @@ def splitInnerLoop(astNode, symbolGroups): outerLoop.parent.append(ast.TemporaryMemoryFree(tmpArray)) +def symbolNameToVariableName(symbolName): + """Replaces characters which are allowed in sympy symbol names but not in C/C++ variable names""" + return symbolName.replace("^", "_") + + def typeAllEquations(eqs, typeForSymbol): """ Traverses AST and replaces every :class:`sympy.Symbol` by a :class:`pystencils.typedsymbol.TypedSymbol`. @@ -415,7 +420,7 @@ def typeAllEquations(eqs, typeForSymbol): elif isinstance(term, TypedSymbol): return term elif isinstance(term, sp.Symbol): - return TypedSymbol(term.name, typeForSymbol[term.name]) + return TypedSymbol(symbolNameToVariableName(term.name), typeForSymbol[term.name]) else: newArgs = [processRhs(arg) for arg in term.args] return term.func(*newArgs) if newArgs else term