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
            )
Exemple #2
0
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))
Exemple #4
0
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)
Exemple #5
0
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))