2020 VOID , Byref , DefFunction , FieldFromPointer , IndexedPointer , ListInitializer , SizeOf ,
2121 as_long , pow_to_mul , unevaluate
2222)
23- from devito .tools import as_list , as_mapper , as_tuple , filter_sorted , flatten
23+ from devito .tools import as_list , as_mapper , as_tuple , filter_sorted , flatten , is_integer
2424from devito .types import (
2525 Array , ComponentAccess , CustomDimension , DeviceMap , DeviceRM , Dimension , Eq , Symbol ,
2626 size_t
@@ -91,6 +91,27 @@ def __init__(self, rcompile=None, sregistry=None, platform=None,
9191 self .sregistry = sregistry
9292 self .platform = platform
9393
94+ # Off inside the recursive compilation of a zero-init itself, which
95+ # would otherwise ask for a zero-init of its own, ad infinitum
96+ self .zero_init = (options or {}).get ('zero-init' , True )
97+
98+ def _zero_init (self , obj , storage ):
99+ """
100+ The nodes zeroing `obj` upfront, if it asks for it, plus the efuncs
101+ they call, if any.
102+ """
103+ if not (obj ._is_zero_init and self .zero_init ):
104+ return (), ()
105+
106+ return self ._make_zero_init (obj , storage )
107+
108+ def _make_zero_init (self , obj , storage ):
109+ """How to zero `obj`'s whole allocation, padding included."""
110+ storage .include (self .langbb ['header-memcpy' ])
111+ nbytes = SizeOf (obj ._C_typedata )* as_long (obj .size )
112+
113+ return (self .langbb ['host-memset' ](obj ._C_symbol , 0 , nbytes ),), ()
114+
94115 def _alloc_object_on_low_lat_mem (self , site , obj , storage ):
95116 """
96117 Allocate a LocalObject in the low latency memory.
@@ -172,11 +193,13 @@ def _alloc_host_array_on_high_bw_mem(self, site, obj, storage, *args):
172193 memptr = VOID (Byref (obj ._C_symbol ), '**' )
173194 alignment = obj ._data_alignment
174195 nbytes = SizeOf (obj ._C_typedata )* as_long (obj .size )
175- alloc = self .langbb ['host-alloc' ](memptr , alignment , nbytes )
196+ zeroing , efuncs = self ._zero_init (obj , storage )
197+ allocs = [decl , self .langbb ['host-alloc' ](memptr , alignment , nbytes ),
198+ * zeroing ]
176199
177200 free = self .langbb ['host-free' ](obj ._C_symbol )
178201
179- storage .update (obj , site , allocs = ( decl , alloc ), frees = free )
202+ storage .update (obj , site , allocs = tuple ( allocs ), frees = free , efuncs = efuncs )
180203
181204 def _alloc_local_array_on_high_bw_mem (self , site , obj , storage , * args ):
182205 """
@@ -568,7 +591,7 @@ def __init__(self, options=None, **kwargs):
568591 self .gpu_create = options ['gpu-create' ]
569592 self .gpu_place_transfers = options .get ('place-transfers' )
570593
571- super ().__init__ (** kwargs )
594+ super ().__init__ (options = options , ** kwargs )
572595
573596 def _alloc_local_array_on_high_bw_mem (self , site , obj , storage ):
574597 """
@@ -579,11 +602,22 @@ def _alloc_local_array_on_high_bw_mem(self, site, obj, storage):
579602 dofree = self .langbb ['device-free' ]
580603
581604 nbytes = SizeOf (obj ._C_typedata )* obj .size
582- init = doalloc (nbytes , deviceid , retobj = obj )
605+
606+ zeroing , efuncs = self ._zero_init (obj , storage )
607+ allocs = [doalloc (nbytes , deviceid , retobj = obj ), * zeroing ]
583608
584609 free = dofree (obj ._C_name , deviceid )
585610
586- storage .update (obj , site , allocs = init , frees = free )
611+ storage .update (obj , site , allocs = tuple (allocs ), frees = free , efuncs = efuncs )
612+
613+ def _make_zero_init (self , obj , storage ):
614+ # No language here has a device-side memset, so use a kernel. It gains
615+ # nothing from tiling, and nvc++ trips over the padded loop bounds
616+ # when it is asked to tile them
617+ efuncs , init = make_zero_init (obj , self .rcompile , self .sregistry ,
618+ options = {'par-tile' : False })
619+
620+ return (init ,), efuncs
587621
588622 def _map_array_on_high_bw_mem (self , site , obj , storage ):
589623 """
@@ -702,18 +736,20 @@ def process(self, graph):
702736 self .place_casts (graph )
703737
704738
705- def make_zero_init (obj , rcompile , sregistry ):
739+ def make_zero_init (obj , rcompile , sregistry , options = None ):
706740 cdims = []
707- for d , (h0 , h1 ), s in zip (
708- obj .dimensions , obj ._size_halo , obj .symbolic_shape , strict = True
741+ for d , (h0 , h1 ), (_ , p1 ), s in zip (
742+ obj .dimensions , obj ._size_halo , obj ._size_padding , obj .symbolic_shape ,
743+ strict = True
709744 ):
710745 if d .is_NonlinearDerived :
711- assert h0 == h1 == 0
746+ assert h0 == h1
712747 m = 0
713748 M = s - 1
714749 else :
715750 m = d .symbolic_min - h0
716- M = d .symbolic_max + h1
751+ # Object needing padding zeroing need symbolic padding
752+ M = d .symbolic_max + h1 + (0 if is_integer (p1 ) else p1 )
717753 cdims .append (CustomDimension (name = d .name , parent = d ,
718754 symbolic_min = m , symbolic_max = M ))
719755
@@ -722,7 +758,8 @@ def make_zero_init(obj, rcompile, sregistry):
722758 else :
723759 eqns = [Eq (obj [cdims ], 0 )]
724760
725- irs , byproduct = rcompile (eqns )
761+ irs , byproduct = rcompile (eqns , options = {'zero-init' : False ,
762+ ** (options or {})})
726763
727764 init = irs .iet .body .body [0 ]
728765
0 commit comments