def make_grid(self, obj): """ Create and return a new :class:`Data`, a YASK grid wrapper. Memory is allocated. :param obj: The :class:`Function` for which a YASK grid is allocated. """ # 'hook' compiler solution: describes the grid # 'hook' kernel solution: allocates memory # A unique name for the 'hook' compiler and kernel solutions suffix = Signer._digest(self, obj, configuration, YaskContext._hookcounter) YaskContext._hookcounter += 1 name = namespace['jit-hook'](suffix) # Create 'hook' compiler solution yc_hook = self.make_yc_solution(name) if obj.indices != self.dimensions: # Note: YASK wants *at least* a grid with *all* space (domain) dimensions # *and* the stepping dimension. `obj`, however, may actually employ a # different set of dimensions (e.g., a strict subset and/or some misc # dimensions). In such a case, an extra dummy grid is attached # `obj` examples: u(x, d), u(x, y, z) dimensions = [ make_yask_ast(i, yc_hook, {}) for i in self.dimensions ] yc_hook.new_grid('dummy_grid_full', dimensions) dimensions = [make_yask_ast(i, yc_hook, {}) for i in obj.indices] yc_hook.new_grid('dummy_grid_true', dimensions) # Create 'hook' kernel solution yk_hook = YaskKernel(name, yc_hook) grid = yk_hook.new_grid(obj) # Where should memory be allocated ? alloc = obj._allocator if alloc.is_Numa: if alloc.put_onnode: grid.set_numa_preferred(alloc.node) elif alloc.put_local: grid.set_numa_preferred(namespace['numa-put-local']) for i, s, h in zip(obj.indices, obj.shape_allocated, obj._extent_halo): if i.is_Space: # Note: # From the YASK docs: "If the halo is set to a value larger than # the padding size, the padding size will be automatically increased # to accomodate it." grid.set_left_halo_size(i.name, h.left) grid.set_right_halo_size(i.name, h.right) else: # time and misc dimensions assert grid.is_dim_used(i.name) assert grid.get_alloc_size(i.name) == s grid.alloc_storage() self.grids[grid.get_name()] = grid return grid
def make_grid(self, obj): """ Create a Data wrapping a YASK grid. Memory is allocated. Parameters ---------- obj : Function The symbolic object for which a new YASK grid is created. """ # 'hook' compiler solution: describes the grid # 'hook' kernel solution: allocates memory # A unique name for the 'hook' compiler and kernel solutions suffix = Signer._digest(self, obj, configuration, YaskContext._hookcounter) YaskContext._hookcounter += 1 name = namespace['jit-hook'](suffix) # Create 'hook' compiler solution yc_hook = self.make_yc_solution(name) if obj.indices != self.dimensions: # Note: YASK wants *at least* a grid with *all* space (domain) dimensions # *and* the stepping dimension. `obj`, however, may actually employ a # different set of dimensions (e.g., a strict subset and/or some misc # dimensions). In such a case, an extra dummy grid is attached # `obj` examples: u(x, d), u(x, y, z) dimensions = [make_yask_ast(i, yc_hook) for i in self.dimensions] yc_hook.new_grid('dummy_grid_full', dimensions) dimensions = [make_yask_ast(i.root, yc_hook) for i in obj.indices] yc_hook.new_grid('dummy_grid_true', dimensions) # Create 'hook' kernel solution yk_hook = YaskKernel(name, yc_hook) grid = yk_hook.new_grid(obj) # Where should memory be allocated ? alloc = obj._allocator if alloc.is_Numa: if alloc.put_onnode: grid.set_numa_preferred(alloc.node) elif alloc.put_local: grid.set_numa_preferred(namespace['numa-put-local']) for i, s, h in zip(obj.indices, obj.shape_allocated, obj._size_halo): if i.is_Space: # Note: # From the YASK docs: "If the halo is set to a value larger than # the padding size, the padding size will be automatically increased # to accomodate it." grid.set_left_halo_size(i.name, h.left) grid.set_right_halo_size(i.name, h.right) else: # time and misc dimensions assert grid.is_dim_used(i.root.name) assert grid.get_alloc_size(i.root.name) == s grid.alloc_storage() self.grids[grid.get_name()] = grid return grid
def make_yc_solution(self, name): """ Create and return a YASK compiler solution object. """ yc_soln = cfac.new_solution(name) # Redirect stdout/strerr to a string or file if configuration.yask['dump']: filename = 'yc_dump.%s.%s.%s.txt' % ( name, configuration['platform'], configuration['isa']) filename = os.path.join(configuration.yask['dump'], filename) yc_soln.set_debug_output(ofac.new_file_output(filename)) else: yc_soln.set_debug_output(ofac.new_null_output()) # Set data type size yc_soln.set_element_bytes(self.dtype().itemsize) # Apply compile-time optimizations if configuration['isa'] != 'cpp': dimensions = [ make_yask_ast(i, yc_soln, {}) for i in self.space_dimensions ] # Vector folding for i, j in zip(dimensions, configuration.yask['folding']): yc_soln.set_fold_len(i, j) # Unrolling for i, j in zip(dimensions, configuration.yask['clustering']): yc_soln.set_cluster_mult(i, j) return yc_soln
def make_yc_solution(self, name): """Create a YASK compiler solution.""" yc_soln = cfac.new_solution(name) # Redirect stdout/strerr to a string or file if configuration.yask['dump']: filename = 'yc_dump.%s.%s.%s.txt' % (name, configuration['platform'], configuration['platform'].isa) filename = os.path.join(configuration.yask['dump'], filename) yc_soln.set_debug_output(ofac.new_file_output(filename)) else: yc_soln.set_debug_output(ofac.new_null_output()) # Set data type size yc_soln.set_element_bytes(self.dtype().itemsize) # Apply compile-time optimizations if configuration['platform'].isa != 'cpp': dimensions = [make_yask_ast(i, yc_soln) for i in self.space_dimensions] # Vector folding for i, j in zip(dimensions, configuration.yask['folding']): yc_soln.set_fold_len(i, j) # Unrolling for i, j in zip(dimensions, configuration.yask['clustering']): yc_soln.set_cluster_mult(i, j) return yc_soln
def make_var(self, obj): """ Create a Data wrapping a YASK var. Memory is allocated. Parameters ---------- obj : Function The symbolic object for which a new YASK var is created. """ # 'hook' compiler solution: describes the var # 'hook' kernel solution: allocates memory # A unique name for the 'hook' compiler and kernel solutions suffix = Signer._digest(self, obj, configuration, YaskContext._hookcounter) YaskContext._hookcounter += 1 name = namespace['jit-hook'](suffix) # Create 'hook' compiler solution yc_hook = self.make_yc_solution(name) # Tell YASK compiler about *all* space (domain) dimensions *and* the # stepping dimension. This is done to ensure that all hook solutions # have the same list of problem dimensions. Note: `obj` may # actually employ a different set of dimensions (e.g., a strict # subset and/or some misc dimensions). space_dims = [make_yask_ast(i, yc_hook) for i in self.space_dimensions] yc_hook.set_domain_dims(space_dims) step_dim = make_yask_ast(self.step_dimension, yc_hook) yc_hook.set_step_dim(step_dim) # Create YASK compiler variable based on dimensions of `obj`. # This is done to force YASK to generate code to create vars # of this type, which will be needed when creating the YASK # kernel variable below. dimensions = [make_yask_ast(i.root, yc_hook) for i in obj.indices] yc_hook.new_var('template_var', dimensions) # Create 'hook' kernel solution from `yc_hook` yk_hook = YaskKernel(name, yc_hook) # Create YASK kernel variable for `obj`. YASK knows how to # create a variable of these dimesions because of the # 'dummy_var' declared above. var = yk_hook.new_var(obj) # Where should memory be allocated ? alloc = obj._allocator if alloc.is_Numa: if alloc.put_onnode: var.set_numa_preferred(alloc.node) elif alloc.put_local: var.set_numa_preferred(namespace['numa-put-local']) for i, s, h in zip(obj.indices, obj.shape_allocated, obj._size_halo): if i.is_Space: # Note: # From the YASK docs: "If the halo is set to a value larger than # the padding size, the padding size will be automatically increased # to accommodate it." var.set_left_halo_size(i.name, h.left) var.set_right_halo_size(i.name, h.right) else: # time and misc dimensions assert var.is_dim_used(i.root.name) assert var.get_alloc_size(i.root.name) == s var.alloc_storage() self.vars[var.get_name()] = var return var