@@ -403,8 +403,13 @@ def generate_buffers(clusters, key, sregistry, options, **kwargs):
403403 # Finally create the actual buffer
404404 cls = callback or Array
405405 name = sregistry .make_name (prefix = '%sb' % f .name )
406+ # We specify the padding to match the input Function's one, so that
407+ # the array can be used in place of the Function with valid strides
408+ # Plain Array do not track mapped so we default to no padding
409+ padding = 0 if cls is Array else f .padding
406410 mapper [f ] = cls (name = name , dimensions = dimensions , dtype = f .dtype ,
407- grid = f .grid , halo = f .halo , space = 'mapped' , mapped = f , f = f )
411+ padding = padding , grid = f .grid , halo = f .halo ,
412+ space = 'mapped' , mapped = f , f = f )
408413
409414 return mapper
410415
@@ -436,25 +441,6 @@ def __init__(self, f, b, clusters):
436441
437442 self .indices = extract_indices (f , self .dim , clusters )
438443
439- # The IterationSpace within which the buffer will be accessed
440- # NOTE: The `key` is to avoid Clusters including `f` but not directly
441- # using it in an expression, such as HaloTouch Clusters
442- key = lambda c : any (i in c .ispace .dimensions for i in self .bdims )
443- ispaces = {c .ispace for c in clusters if key (c )}
444-
445- if len (ispaces ) > 1 :
446- # Best effort to make buffering work in the presence of multiple
447- # IterationSpaces
448- stamp = Stamp ()
449- ispaces = {i .lift (self .bdims , v = stamp ) for i in ispaces }
450-
451- if len (ispaces ) > 1 :
452- raise CompilationError ("Unsupported `buffering` over different "
453- "IterationSpaces" )
454-
455- assert len (ispaces ) == 1 , "Unexpected form of `buffering`"
456- self .ispace = ispaces .pop ()
457-
458444 def __repr__ (self ):
459445 return "Descriptor[%s -> %s]" % (self .f , self .b )
460446
@@ -474,6 +460,47 @@ def itdims(self):
474460 """
475461 return (self .xd , self .dim .root )
476462
463+ @cached_property
464+ def ispace (self ):
465+ # The IterationSpace within which the buffer will be accessed
466+
467+ # NOTE: The `key` is to avoid Clusters including `f` but not directly
468+ # using it in an expression, such as HaloTouch Clusters
469+ def key (c ):
470+ bufferdim = any (i in c .ispace .dimensions for i in self .bdims )
471+ xd_only = all (d ._defines & self .xd ._defines for d in c .ispace .dimensions )
472+ return bufferdim or xd_only
473+
474+ ispaces = set ()
475+ for c in self .clusters :
476+ if not key (c ):
477+ continue
478+
479+ # Skip wild clusters (e.g. HaloTouch Clusters)
480+ if c .is_wild :
481+ continue
482+
483+ # Iterations space and buffering dims
484+ edims = [d for d in self .bdims if d not in c .ispace .dimensions ]
485+ if not edims :
486+ ispaces .add (c .ispace )
487+ else :
488+ # Add all missing buffering dimensions and reorder to
489+ # avoid duplicates with different ordering
490+ ispaces .add (c .ispace .insert (self .dim , edims ).reorder ())
491+
492+ if len (ispaces ) > 1 :
493+ # Best effort to make buffering work in the presence of multiple
494+ # IterationSpaces
495+ stamp = Stamp ()
496+ ispaces = {i .lift (self .bdims , v = stamp ) for i in ispaces }
497+
498+ if len (ispaces ) > 1 :
499+ raise CompilationError ("Unsupported `buffering` over different "
500+ "IterationSpaces" )
501+
502+ return ispaces .pop ()
503+
477504 @cached_property
478505 def subdims_mapper (self ):
479506 return {d .root : d for d in self .ispace .itdims if d .is_AbstractSub }
0 commit comments