def _visit_homogenous_space(self, node): offset_versions = [] # so that we can apply all of the spaces simultaneously for space in node.space.spaces: cp = copy.deepcopy(node.body) shifter = StencilShifter(space.low) output = [shifter.visit(part) for part in cp] offset_versions.extend(output) low = Vector((0,) * node.space.ndim) high = node.space.spaces[0].high - node.space.spaces[0].low stride = node.space.spaces[0].stride return IterationSpace( space=NDSpace([Space(low, high, stride)]), body=offset_versions )
def create_component(ndim, dim): # each component is one dimension -> A[i] = B[i](A[i] - A[i-1]) + B[i+1](A[i+1] - A[i]) lower_diff = StencilComponent("mesh", SparseWeightArray({Vector.zero_vector(ndim): 1, -Vector.unit_vector(dim, ndim): -1})) lower_diff *= StencilComponent("beta_{}".format(dim), SparseWeightArray({Vector.zero_vector(ndim): 1})) upper_diff = StencilComponent("mesh", SparseWeightArray({Vector.zero_vector(ndim): -1, Vector.unit_vector(dim, ndim): 1})) upper_diff *= StencilComponent("beta_{}".format(dim), SparseWeightArray({Vector.unit_vector(dim, ndim): 1})) return lower_diff + upper_diff
def test_boundaries(): """ Tests if boundaries can be parallelized (or not). """ dimensions = 3 def reference_vector(vec): first_nonzero_position = next(i for i in range(len(vec)) if vec[i]) return -vec * Vector.unit_vector(first_nonzero_position, len(vec)) def get_stencil(boundary): # boundaries of 1-norm n depend on boundaries of 1-norm n-1 by looking in on the first non-zero element. read_vector = reference_vector(boundary) component = StencilComponent( 'mesh', SparseWeightArray( { read_vector: 1 } ) ) return Stencil(component, 'mesh', [ (-1, 0, 1) if bound == 1 else (0, 1, 1) if bound == -1 else (1, -1, 1) for bound in boundary ]) stencils = [ (boundary, get_stencil(boundary)) for boundary in Vector.moore_vectors(dimensions) ] group = StencilGroup([stencil for bound, stencil in stencils]) serial = create_dependency_graph(group, {"mesh": (32,)*dimensions}) parallel = create_parallel_graph(group, {"mesh": (32,)*dimensions}) # print(serial) # print(parallel) # print(serial == parallel) # exit() for (b1, s1), (b2, s2) in itertools.product(stencils, repeat=2): has_conflict = b2+reference_vector(b2) == b1 or b1 == b2 graph_conflict = serial[hash(s2)][hash(s1)] parallel_conflict = parallel[hash(s2)][hash(s1)] reported = stencil_conflict(s1, s2, shape_map={"mesh": (32,)*dimensions}) print(b1, b2, reported, has_conflict, graph_conflict, parallel_conflict, '*'*10*(parallel_conflict != has_conflict))
def run_affine(): weight_array = SparseWeightArray( {Vector.index_vector(3) + (1, 1, 1) : 5} ) component = StencilComponent( "input", weight_array ) stencil = Stencil( component, "output", [(1, -1, 1)]*3 ) compiler = PythonCompiler() kern = compiler.compile(stencil) arr = np.arange(6**3, dtype=np.float).reshape((6, 6, 6)) out = np.zeros_like(arr) kern(out, arr) print(out)
def _stencil_conflict(data1, data2, shape_map): # shadows = get_shadow(stencil2) # these are all of the offset vectors for each array shadows = data2.shadow if data1.output not in shadows: return False # not read/writing from same mesh shade = shadows[data1.output] # these are vectors that are used. shape = shape_map[data1.primary_mesh] if data1.output == data2.output: # if they write to the same array shade |= {Vector.zero_vector(len(shape))} # Perform exhaustive search over pairs of iteration spaces? # TODO: Probably should make this smarter for write_domain in data1.iteration_space.reify(shape).domains: for read_domain in data2.iteration_space.reify(shape).domains: # in order to save time, compute the projections for each vector onto each dimension. collisions = [{} for _ in shape] for vector in shade: for dim, val in enumerate(vector): collisions[dim][val] = False # using 1d slices of each domain for wd_1d, rd_1d, offsets in zip( zip(write_domain.lower, write_domain.upper, write_domain.stride), zip(read_domain.lower, read_domain.upper, read_domain.stride), collisions, ): for offset in offsets: offsets[offset] = _has_conflict(wd_1d, rd_1d, offset) # print(collisions) for vector in shade: if all( collisions[dim][val] for dim, val in enumerate(vector) ): # some vector has a collision on all dimensions return True return False
def reference_vector(vec): first_nonzero_position = next(i for i in range(len(vec)) if vec[i]) return -vec * Vector.unit_vector(first_nonzero_position, len(vec))
def test_collision(): """ Test using Red Black. All of them should collide. """ dimensions = 3 # Red domains are formed by the origin plus all non-negative vectors with 1-norm 2. red_domain_starts = [Vector.zero_vector(dimensions)] + [i for i in Vector.von_neumann_vectors(dimensions, 2) if all(coord >= 0 for coord in i)] red_domain = DomainUnion([ RectangularDomain([(s, -1, 2) for s in start]) for start in red_domain_starts ]) # Black domains are formed by non-negative vectors with 1-norm 1. black_domain_starts = [i for i in Vector.von_neumann_vectors(dimensions, 1) if all(coord >= 0 for coord in i)] black_domain = DomainUnion([ RectangularDomain([(s, -1, 2) for s in start]) for start in black_domain_starts ]) star_neighborhood = {Vector.unit_vector(d, dimensions): 1 for d in range(dimensions)} star_neighborhood.update( {-Vector.unit_vector(d, dimensions): 1 for d in range(dimensions)} ) red = Stencil( StencilComponent( "mesh", SparseWeightArray( star_neighborhood ) ), "mesh", red_domain ) black = Stencil( StencilComponent( "mesh", SparseWeightArray( star_neighborhood ) ), "mesh", black_domain ) red_oop = Stencil( StencilComponent( "mesh", SparseWeightArray( star_neighborhood ) ), "output", red_domain ) black_oop = Stencil( StencilComponent( "mesh", SparseWeightArray( star_neighborhood ) ), "output", black_domain ) print("Testing with simulated 32^dimensions mesh") print("WRITE-READ", "has collision") print("RED - RED", stencil_conflict(red, red, {"mesh": (32,)*dimensions})) print("BLACK - BLACK", stencil_conflict(black, black, {"mesh": (32,)*dimensions})) print("RED - BLACK", stencil_conflict(red, black, {"mesh": (32,)*dimensions})) print("BLACK - RED", stencil_conflict(black, red, {"mesh": (32,)*dimensions})) print("REDOOP - BLACKOOP", stencil_conflict(red_oop, black_oop, {"mesh": (32,)*dimensions})) print("BLACKOOP - REDOOP", stencil_conflict(black_oop, red_oop, {"mesh": (32,)*dimensions})) print("INTRA-red is valid", validate_stencil(red)) print("INTRA-black is valid", validate_stencil(black))