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

Fix integer division in Python frontend #1196

Merged
merged 20 commits into from
Mar 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion dace/codegen/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def find_outgoing_edges(node, dfg):

@lru_cache(maxsize=16384)
def _sym2cpp(s, arrayexprs):
return cppunparse.pyexpr2cpp(symbolic.symstr(s, arrayexprs))
return cppunparse.pyexpr2cpp(symbolic.symstr(s, arrayexprs, cpp_mode=True))


def sym2cpp(s, arrayexprs: Optional[Set[str]] = None) -> Union[str, List[str]]:
Expand Down
5 changes: 4 additions & 1 deletion dace/codegen/compiled_sdfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ def is_loaded(self) -> bool:
return True
if not os.path.isfile(self._stub_filename):
return False
self._stub = ctypes.CDLL(self._stub_filename)
try:
self._stub = ctypes.CDLL(self._stub_filename)
except OSError:
return False

# Set return types of stub functions
self._stub.load_library.restype = ctypes.c_void_p
Expand Down
8 changes: 7 additions & 1 deletion dace/codegen/cppunparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ def interleave(inter, f, seq, **kwargs):


class LocalScheme(object):

def is_defined(self, local_name, current_depth):
raise NotImplementedError('Abstract class')

Expand All @@ -131,6 +132,7 @@ def clear_scope(self, from_indentation):


class CPPLocals(LocalScheme):

def __init__(self):
# Maps local name to a 3-tuple of line number, scope (measured in indentation) and type
self.locals = {}
Expand Down Expand Up @@ -163,6 +165,7 @@ class CPPUnparser:
"""Methods in this class recursively traverse an AST and
output C++ source code for the abstract syntax; original formatting
is disregarded. """

def __init__(self,
tree,
depth,
Expand Down Expand Up @@ -1132,7 +1135,9 @@ def py2cpp(code, expr_semicolon=True, defined_symbols=None):
return '\n'.join(py2cpp(stmt) for stmt in code)
elif isinstance(code, sympy.Basic):
from dace import symbolic
return cppunparse(ast.parse(symbolic.symstr(code)), expr_semicolon, defined_symbols=defined_symbols)
return cppunparse(ast.parse(symbolic.symstr(code, cpp_mode=True)),
expr_semicolon,
defined_symbols=defined_symbols)
elif code.__class__.__name__ == 'function':
try:
code_str = inspect.getsource(code)
Expand All @@ -1151,6 +1156,7 @@ def py2cpp(code, expr_semicolon=True, defined_symbols=None):
else:
raise NotImplementedError('Unsupported type for py2cpp')


@lru_cache(maxsize=16384)
def pyexpr2cpp(expr):
return py2cpp(expr, expr_semicolon=False)
2 changes: 1 addition & 1 deletion dace/codegen/targets/cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,7 @@ def visit_BinOp(self, node: ast.BinOp):
**self.constants, 'dace': dace,
'math': math
}))
evaluated = symbolic.symstr(symbolic.evaluate(unparsed, self.constants))
evaluated = symbolic.symstr(symbolic.evaluate(unparsed, self.constants), cpp_mode=True)
node.right = ast.parse(evaluated).body[0].value
except (TypeError, AttributeError, NameError, KeyError, ValueError, SyntaxError):
return self.generic_visit(node)
Expand Down
6 changes: 3 additions & 3 deletions dace/codegen/targets/cuda.py
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ def _emit_copy(self, state_id, src_node, src_storage, dst_node, dst_storage, dst
callsite_stream.write("}")

if dims == 1 and not (src_strides[-1] != 1 or dst_strides[-1] != 1):
copysize = ' * '.join([cppunparse.pyexpr2cpp(symbolic.symstr(s)) for s in copy_shape])
copysize = ' * '.join(_topy(copy_shape))
array_length = copysize
copysize += ' * sizeof(%s)' % dtype.ctype

Expand Down Expand Up @@ -2439,8 +2439,8 @@ def make_ptr_vector_cast(self, *args, **kwargs):
def _topy(arr):
""" Converts an array of symbolic variables (or one) to C++ strings. """
if not isinstance(arr, list):
return cppunparse.pyexpr2cpp(symbolic.symstr(arr))
return [cppunparse.pyexpr2cpp(symbolic.symstr(d)) for d in arr]
return cppunparse.pyexpr2cpp(symbolic.symstr(arr, cpp_mode=True))
return [cppunparse.pyexpr2cpp(symbolic.symstr(d, cpp_mode=True)) for d in arr]


def _named_idx(idx):
Expand Down
13 changes: 7 additions & 6 deletions dace/codegen/targets/fpga.py
Original file line number Diff line number Diff line change
Expand Up @@ -1629,7 +1629,7 @@ def _emit_copy(self, sdfg, state_id, src_node, src_storage, dst_node, dst_storag
else:
raise TypeError("Memory copy type mismatch: {} vs {}".format(host_dtype, device_dtype))

copysize = " * ".join([cppunparse.pyexpr2cpp(dace.symbolic.symstr(s)) for s in copy_shape])
copysize = " * ".join([cppunparse.pyexpr2cpp(dace.symbolic.symstr(s, cpp_mode=True)) for s in copy_shape])

src_subset = memlet.src_subset or memlet.subset
dst_subset = memlet.dst_subset or memlet.subset
Expand Down Expand Up @@ -2198,13 +2198,14 @@ def _generate_MapExit(self, sdfg, dfg, state_id, node, function_stream, callsite
# ranges could have been defined in terms of floor/ceiling. Before printing the code
# they are converted from a symbolic expression to a C++ compilable expression
for it, r in reversed(list(zip(pipeline.params, pipeline.range))):
callsite_stream.write("if ({it} >= {end}) {{\n{it} = {begin};\n".format(it=it,
begin=dace.symbolic.symstr(
r[0]),
end=dace.symbolic.symstr(r[1])))
callsite_stream.write("if ({it} >= {end}) {{\n{it} = {begin};\n".format(
it=it,
begin=dace.symbolic.symstr(r[0], cpp_mode=True),
end=dace.symbolic.symstr(r[1], cpp_mode=True)))
for it, r in zip(pipeline.params, pipeline.range):
callsite_stream.write("}} else {{\n{it} += {step};\n}}\n".format(it=it,
step=dace.symbolic.symstr(r[2])))
step=dace.symbolic.symstr(
r[2], cpp_mode=True)))
if len(cond) > 0:
callsite_stream.write("}\n")
callsite_stream.write("}\n}\n")
Expand Down
11 changes: 5 additions & 6 deletions dace/codegen/targets/intel_fpga.py
Original file line number Diff line number Diff line change
Expand Up @@ -1476,12 +1476,11 @@ def visit_BinOp(self, node):
left_value = cppunparse.cppunparse(self.visit(node.left), expr_semicolon=False)

try:
unparsed = symbolic.pystr_to_symbolic(
evalnode(node.right, {
**self.constants,
'dace': dace,
}))
evaluated = symbolic.symstr(evaluate(unparsed, self.constants))
unparsed = symbolic.pystr_to_symbolic(evalnode(node.right, {
**self.constants,
'dace': dace,
}))
evaluated = symbolic.symstr(evaluate(unparsed, self.constants), cpp_mode=True)
infered_type = infer_expr_type(evaluated, self.dtypes)
right_value = evaluated

Expand Down
4 changes: 2 additions & 2 deletions dace/codegen/targets/mpi.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ def generate_scope(self, sdfg, dfg_scope, state_id, function_stream, callsite_st
callsite_stream.write('{\n', sdfg, state_id, map_header)
callsite_stream.write(
'%s %s = %s + __dace_comm_rank * (%s);\n' %
(symtypes[var], var, cppunparse.pyexpr2cpp(
symbolic.symstr(begin)), cppunparse.pyexpr2cpp(symbolic.symstr(skip))), sdfg, state_id, map_header)
(symtypes[var], var, cppunparse.pyexpr2cpp(symbolic.symstr(begin, cpp_mode=True)),
cppunparse.pyexpr2cpp(symbolic.symstr(skip, cpp_mode=True))), sdfg, state_id, map_header)

self._frame.allocate_arrays_in_scope(sdfg, map_header, function_stream, callsite_stream)

Expand Down
1 change: 0 additions & 1 deletion dace/codegen/targets/sve/infer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from dace import dtypes
from dace.codegen import cppunparse
from dace.symbolic import SymExpr
from dace.symbolic import symstr
import sympy
import sys

Expand Down
9 changes: 6 additions & 3 deletions dace/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ def validate(self):
# `validate` function.
def _validate(self):
if any(not isinstance(s, (int, symbolic.SymExpr, symbolic.symbol, symbolic.sympy.Basic)) for s in self.shape):
raise TypeError('Shape must be a list or tuple of integer values ' 'or symbols')
raise TypeError('Shape must be a list or tuple of integer values '
'or symbols')
return True

def to_json(self):
Expand Down Expand Up @@ -615,7 +616,7 @@ def validate(self):
raise TypeError('Strides must be the same size as shape')

if any(not isinstance(s, (int, symbolic.SymExpr, symbolic.symbol, symbolic.sympy.Basic)) for s in self.strides):
raise TypeError('Strides must be a list or tuple of integer ' 'values or symbols')
raise TypeError('Strides must be a list or tuple of integer values or symbols')

if len(self.offset) != len(self.shape):
raise TypeError('Offset must be the same size as shape')
Expand Down Expand Up @@ -848,7 +849,7 @@ def sizes(self):
return [d.name if isinstance(d, symbolic.symbol) else str(d) for d in self.shape]

def size_string(self):
return (" * ".join([cppunparse.pyexpr2cpp(symbolic.symstr(s)) for s in self.shape]))
return (" * ".join([cppunparse.pyexpr2cpp(symbolic.symstr(s, cpp_mode=True)) for s in self.shape]))

def is_stream_array(self):
return _prod(self.shape) != 1
Expand Down Expand Up @@ -926,6 +927,7 @@ class View(Array):
In the Python frontend, ``numpy.reshape`` and ``numpy.ndarray.view`` both
generate Views.
"""

def validate(self):
super().validate()

Expand All @@ -949,6 +951,7 @@ class Reference(Array):

In order to enable data-centric analysis and optimizations, avoid using References as much as possible.
"""

def validate(self):
super().validate()

Expand Down
16 changes: 12 additions & 4 deletions dace/frontend/python/newast.py
Original file line number Diff line number Diff line change
Expand Up @@ -2988,16 +2988,24 @@ def _add_access(

state = self.last_state

new_memlet = None
if has_indirection:
new_memlet = dace.Memlet.from_array(parent_name, parent_array)
volume = rng.num_elements()
new_memlet.volume = volume if not symbolic.issymbolic(volume) else -1
else:
new_memlet = dace.Memlet.simple(parent_name, rng)

if access_type == 'r':
if has_indirection:
self.inputs[var_name] = (state, dace.Memlet.from_array(parent_name, parent_array), inner_indices)
self.inputs[var_name] = (state, new_memlet, inner_indices)
else:
self.inputs[var_name] = (state, dace.Memlet.simple(parent_name, rng), inner_indices)
self.inputs[var_name] = (state, new_memlet, inner_indices)
else:
if has_indirection:
self.outputs[var_name] = (state, dace.Memlet.from_array(parent_name, parent_array), inner_indices)
self.outputs[var_name] = (state, new_memlet, inner_indices)
else:
self.outputs[var_name] = (state, dace.Memlet.simple(parent_name, rng), inner_indices)
self.outputs[var_name] = (state, new_memlet, inner_indices)

self.variables[var_name] = var_name
return (var_name, squeezed_rng)
Expand Down
4 changes: 2 additions & 2 deletions dace/frontend/python/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ def infer_symbols_from_datadescriptor(sdfg: SDFG,
if repldict:
sym_dim = sym_dim.subs(repldict)

equations.append(sym_dim - real_dim)
if symbolic.issymbolic(sym_dim - real_dim):
equations.append(sym_dim - real_dim)

if len(symbols) == 0:
return {}
Expand Down Expand Up @@ -893,5 +894,4 @@ def _generate_pdp(self, args: Tuple[Any], kwargs: Dict[str, Any], simplify: Opti
sdfg._regenerate_code = self.regenerate_code
sdfg._recompile = self.recompile


return sdfg, cached
14 changes: 12 additions & 2 deletions dace/frontend/python/replacements.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,12 @@ def _arange(pv: ProgramVisitor, sdfg: SDFG, state: SDFGState, *args, **kwargs):

@oprepo.replaces('elementwise')
@oprepo.replaces('dace.elementwise')
def _elementwise(pv: 'ProgramVisitor', sdfg: SDFG, state: SDFGState, func: Union[StringLiteral, str], in_array: str, out_array=None):
def _elementwise(pv: 'ProgramVisitor',
sdfg: SDFG,
state: SDFGState,
func: Union[StringLiteral, str],
in_array: str,
out_array=None):
"""
Apply a lambda function to each element in the input.
"""
Expand Down Expand Up @@ -1904,7 +1909,9 @@ def _scalar_sym_binop(visitor: ProgramVisitor, sdfg: SDFG, state: SDFGState, lef
">=": sp.GreaterThan,
"<=": sp.LessThan,
">": sp.StrictGreaterThan,
"<": sp.StrictLessThan
"<": sp.StrictLessThan,
# Binary ops
"//": symbolic.int_floor,
}


Expand Down Expand Up @@ -4612,10 +4619,13 @@ def _cupy_empty(pv: ProgramVisitor, sdfg: SDFG, state: SDFGState, shape: Shape,
'GtE': '__ge__'
}


def _makeboolop(op: str, method: str):

@oprepo.replaces_operator('StringLiteral', op, otherclass='StringLiteral')
def _op(visitor: 'ProgramVisitor', sdfg: SDFG, state: SDFGState, op1: StringLiteral, op2: StringLiteral):
return getattr(op1, method)(op2)


for op, method in _boolop_to_method.items():
_makeboolop(op, method)
5 changes: 2 additions & 3 deletions dace/libraries/blas/nodes/dot.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import dace.library
import dace.properties
import dace.sdfg.nodes
from dace.symbolic import symstr
from dace.transformation.transformation import ExpandTransformation
from dace.libraries.blas import blas_helpers
from .. import environments
Expand Down Expand Up @@ -544,9 +543,9 @@ def validate(self, sdfg, state):
desc_res = sdfg.arrays[e.data.data]

if desc_x.dtype != desc_y.dtype:
raise TypeError("Data types of input operands must be equal: " f"{desc_x.dtype}, {desc_y.dtype}")
raise TypeError(f"Data types of input operands must be equal: {desc_x.dtype}, {desc_y.dtype}")
if desc_x.dtype.base_type != desc_res.dtype.base_type:
raise TypeError("Data types of input and output must be equal: " f"{desc_x.dtype}, {desc_res.dtype}")
raise TypeError(f"Data types of input and output must be equal: {desc_x.dtype}, {desc_res.dtype}")

# Squeeze input memlets
squeezed1 = copy.deepcopy(in_memlets[0].subset)
Expand Down
4 changes: 2 additions & 2 deletions dace/libraries/blas/nodes/gemm.py
Original file line number Diff line number Diff line change
Expand Up @@ -995,8 +995,8 @@ def __init__(self, name, location=None, transA=False, transB=False, alpha=1, bet
location=location,
inputs=({"_a", "_b", "_cin"} if beta != 0 and cin else {"_a", "_b"}),
outputs={"_c"})
self.transA = transA
self.transB = transB
self.transA = True if transA else False
self.transB = True if transB else False
self.alpha = alpha
self.beta = beta
self.cin = cin
Expand Down
3 changes: 1 addition & 2 deletions dace/libraries/blas/nodes/ger.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Copyright 2019-2021 ETH Zurich and the DaCe authors. All rights reserved.
from dace.symbolic import symstr
from dace.properties import Property, SymbolicProperty
from dace.transformation.transformation import ExpandTransformation
from dace.frontend.common import op_repository as oprepo
Expand Down Expand Up @@ -288,7 +287,7 @@ def validate(self, sdfg, state):
desc_y = sdfg.arrays[memlet.data]

if size_a is None or size_x is None:
raise ValueError("Expected at least two inputs to Ger " "(matrix A and vector x)")
raise ValueError("Expected at least two inputs to Ger (matrix A and vector x)")

if size_y is None:
raise ValueError("Expected exactly one output from Ger (vector y).")
Expand Down
1 change: 0 additions & 1 deletion dace/libraries/lapack/nodes/getri.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import dace.library
import dace.properties
import dace.sdfg.nodes
from dace.symbolic import symstr
from dace.transformation.transformation import ExpandTransformation
from .. import environments
from dace import data as dt, dtypes, memlet as mm, SDFG, SDFGState, symbolic
Expand Down
1 change: 0 additions & 1 deletion dace/libraries/lapack/nodes/getrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import dace.library
import dace.properties
import dace.sdfg.nodes
from dace.symbolic import symstr
from dace.transformation.transformation import ExpandTransformation
from .. import environments
from dace import data as dt, dtypes, memlet as mm, SDFG, SDFGState, symbolic
Expand Down
Loading