Skip to content

Commit

Permalink
Add first prototype of deferred allocation support
Browse files Browse the repository at this point in the history
  • Loading branch information
ThrudPrimrose committed Oct 24, 2024
1 parent fae0704 commit 023c86c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 24 deletions.
24 changes: 12 additions & 12 deletions dace/codegen/targets/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,13 +395,13 @@ def allocate_array(self, sdfg: SDFG, cfg: ControlFlowRegion, dfg: StateSubgraphV

# Compute array size
arrsize = nodedesc.total_size
deferred_allocation = any([s for s in nodedesc.shape if str(s).startswith("__dace_defer")])
arrsize_bytes = None
if not isinstance(nodedesc.dtype, dtypes.opaque):
arrsize_bytes = arrsize * nodedesc.dtype.bytes

if isinstance(nodedesc, data.Structure) and not isinstance(nodedesc, data.StructureView):
declaration_stream.write(f"{nodedesc.ctype} {name} = new {nodedesc.dtype.base_type};\n")
declaration_stream.write(f"// C")
define_var(name, DefinedType.Pointer, nodedesc.ctype)
if allocate_nested_data:
for k, v in nodedesc.members.items():
Expand Down Expand Up @@ -496,10 +496,9 @@ def allocate_array(self, sdfg: SDFG, cfg: ControlFlowRegion, dfg: StateSubgraphV

if not declared:
declaration_stream.write(f'{nodedesc.dtype.ctype} *{name};\n', cfg, state_id, node)
if isinstance(arrsize, symbolic.symbol) and str(arrsize) == "__dace_defer":
allocation_stream.write("// Deferred Allocation")
if deferred_allocation:
allocation_stream.write(
"%s = nullptr;" %
"%s = nullptr; // Deferred Allocation" %
(alloc_name,),
cfg,
state_id,
Expand Down Expand Up @@ -677,12 +676,16 @@ def reallocate(
function_stream: CodeIOStream,
callsite_stream: CodeIOStream,
):
callsite_stream.write(
f"// Reallocate Called"
function_stream.write(
"#include <cstdlib>"
)
dtype = sdfg.arrays[node.data].dtype
data_name = node.data
size_array_name = f"{data_name}_size"
data = sdfg.arrays[data_name]
dtype = sdfg.arrays[data_name].dtype
size_str = " * ".join([f"{size_array_name}[{i}]" for i in range(len(data.shape))])
callsite_stream.write(
f"{node.data} = realloc({node.data}, {edge.data.data} * sizeof({dtype}));"
f"{node.data} = static_cast<{dtype} *>(std::realloc(static_cast<void *>({node.data}), {size_str} * sizeof({dtype})));"
)

def _emit_copy(
Expand Down Expand Up @@ -1142,11 +1145,9 @@ def process_out_memlets(self,
elif isinstance(node, nodes.AccessNode):
if dst_node != node and not isinstance(dst_node, nodes.Tasklet) :
# If it is a size change, reallocate will be called
if edge.dst_conn.endswith("_size"):
result.write("// No Copy as AN -> AN write is to ")
if edge.dst_conn is not None and edge.dst_conn.endswith("_size"):
continue

result.write("// COPY2")
dispatcher.dispatch_copy(
node,
dst_node,
Expand Down Expand Up @@ -2223,7 +2224,6 @@ def _generate_AccessNode(self, sdfg: SDFG, cfg: ControlFlowRegion, dfg: StateSub
# Only generate code in case this is the innermost scope
# (copies are generated at the inner scope, where both arrays exist)
if (scope_contains_scope(sdict, src_node, node) and sdict[src_node] != sdict[node]):
callsite_stream.write("// COPY1")
self._dispatcher.dispatch_copy(
src_node,
node,
Expand Down
47 changes: 35 additions & 12 deletions dace/sdfg/sdfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,7 @@ def clear_data_reports(self):

def call_with_instrumented_data(self, dreport: 'InstrumentedDataReport', *args, **kwargs):
"""
Invokes an SDFG with an instrumented data report, generating and compiling code if necessary.
Invokes an SDFG with an instrumented data report, generating and compiling code if necessary.
Arguments given as ``args`` and ``kwargs`` will be overriden by the data containers defined in the report.
:param dreport: The instrumented data report to use upon calling.
Expand Down Expand Up @@ -1694,21 +1694,28 @@ def add_array(self,
may_alias=False) -> Tuple[str, dt.Array]:
""" Adds an array to the SDFG data descriptor store. """

# convert strings to int if possible

# Every Array also supports reallocation, we need to create a secondary size array
# The array size is constant and not changeable, yet the values in the array can change

# convert strings to int if possible, unless it is not the reserved symbol for deferred allocation
newshape = []
for s in shape:
try:
newshape.append(int(s))
except:
newshape.append(dace.symbolic.pystr_to_symbolic(s))
for i, s in enumerate(shape):
if isinstance(s, str) and s == "__dace_defer":
newshape.append(dace.symbolic.pystr_to_symbolic(f"{s}_dim{i}"))
else:
try:
newshape.append(int(s))
except:
newshape.append(dace.symbolic.pystr_to_symbolic(s))
shape = newshape
strides = strides or None

if isinstance(dtype, type) and dtype in dtypes._CONSTANT_TYPES[:-1]:
dtype = dtypes.typeclass(dtype)

desc = dt.Array(dtype,
shape,
desc = dt.Array(dtype=dtype,
shape=shape,
storage=storage,
location=location,
allow_conflicts=allow_conflicts,
Expand All @@ -1721,7 +1728,23 @@ def add_array(self,
total_size=total_size,
may_alias=may_alias)

return self.add_datadesc(name, desc, find_new_name=find_new_name), desc
size_desc = dt.Array(dtype=dace.uint64,
shape=(len(shape),),
storage=storage,
location=location,
allow_conflicts=False,
transient=True,
strides=(1,),
offset=(0,),
lifetime=lifetime,
alignment=alignment,
debuginfo=debuginfo,
total_size=len(shape),
may_alias=False)

array_name = self.add_datadesc(name, desc, find_new_name=find_new_name)
self.add_datadesc(f"{array_name}_size", size_desc, find_new_name=False)
return array_name, desc

def add_view(self,
name: str,
Expand Down Expand Up @@ -2602,7 +2625,7 @@ def apply_transformations_once_everywhere(self,
print_report: Optional[bool] = None,
order_by_transformation: bool = True,
progress: Optional[bool] = None) -> int:
"""
"""
This function applies a transformation or a set of (unique) transformations
until throughout the entire SDFG once. Operates in-place.
Expand Down Expand Up @@ -2718,7 +2741,7 @@ def expand_library_nodes(self, recursive=True):

def generate_code(self):
""" Generates code from this SDFG and returns it.
:return: A list of `CodeObject` objects containing the generated
code of different files and languages.
"""
Expand Down

0 comments on commit 023c86c

Please sign in to comment.