Ejemplo n.º 1
0
def test_estimate_computation_speed():
    """ test estimate_computation_speed method """
    def f(x):
        return 2 * x

    def g(x):
        return np.sin(x) * np.cos(x)**2

    assert misc.estimate_computation_speed(
        f, 1) > misc.estimate_computation_speed(g, 1)
Ejemplo n.º 2
0
def main():
    """main routine testing the performance"""
    print("Reports calls-per-second (larger is better)\n")

    # Cartesian grid with different shapes and boundary conditions
    for size in [32, 512]:
        grid = UnitGrid([size, size], periodic=False)
        print(grid)

        field = ScalarField.random_normal(grid)
        bc_value = np.ones(size)
        result = field.laplace(bc={"value": 1}).data

        for bc in ["scalar", "array", "function", "time-dependent", "linked"]:
            if bc == "scalar":
                bcs = {"value": 1}
            elif bc == "array":
                bcs = {"value": bc_value}
            elif bc == "function":
                bcs = grid.get_boundary_conditions(
                    {"virtual_point": "2 - value"})
            elif bc == "time-dependent":
                bcs = grid.get_boundary_conditions({"value_expression": "t"})
            elif bc == "linked":
                bcs = grid.get_boundary_conditions({"value": bc_value})
                for ax, upper in grid._iter_boundaries():
                    bcs[ax][upper].link_value(bc_value)
            else:
                raise RuntimeError

            # create the operator with these conditions
            laplace = grid.make_operator("laplace", bc=bcs)
            if bc == "time-dependent":
                args = numba_dict({"t": 1})
                # call once to pre-compile and test result
                np.testing.assert_allclose(laplace(field.data, args=args),
                                           result)
                # estimate the speed
                speed = estimate_computation_speed(laplace,
                                                   field.data,
                                                   args=args)

            else:
                # call once to pre-compile and test result
                np.testing.assert_allclose(laplace(field.data), result)
                # estimate the speed
                speed = estimate_computation_speed(laplace, field.data)

            print(f"{bc:>14s}:{int(speed):>9d}")

        print()
Ejemplo n.º 3
0
def main():
    """ main routine testing the performance """
    print("Reports calls-per-second (larger is better)\n")

    # Cartesian grid with different shapes and boundary conditions
    for size in [32, 512]:
        grid = UnitGrid((size, size), periodic=False)
        print(grid)

        field = ScalarField.random_normal(grid)
        bc_value = np.ones(size)
        result = field.laplace(bc={"value": 1}).data

        for bc in ["scalar", "array", "linked"]:
            if bc == "scalar":
                bcs = {"value": 1}
            elif bc == "array":
                bcs = {"value": bc_value}
            elif bc == "linked":
                bcs = Boundaries.from_data(grid, {"value": bc_value}, rank=0)
                for ax, upper in grid._iter_boundaries():
                    bcs[ax][upper].link_value(bc_value)
            # result = field.laplace(bc=bcs).data
            laplace = grid.get_operator("laplace", bc=bcs)
            # call once to pre-compile and test result
            np.testing.assert_allclose(laplace(field.data), result)
            speed = estimate_computation_speed(laplace, field.data)
            print(f"{bc:>6s}:{int(speed):>9d}")

        print()
Ejemplo n.º 4
0
def time_function(func, arg, repeat=3, use_out=False):
    """estimates the computation speed of a function

    Args:
        func (callable): The function to test
        arg: The single argument on which the function will be estimate
        repeat (int): How often the function is tested
        use_out (bool): Whether to supply the `out` argument to the function

    Returns:
        float: Estimated duration of calling the function a single time
    """
    if use_out:
        out = np.empty(tuple(s - 2 for s in arg.shape))
        number = int(estimate_computation_speed(func, arg, out))
        func = functools.partial(func, arg, out)
    else:
        number = int(estimate_computation_speed(func, arg))
        func = functools.partial(func, arg)
    return min(timeit.repeat(func, number=number, repeat=repeat)) / number
Ejemplo n.º 5
0
def time_function(func, arg, repeat=3):
    """ estimates the computation speed of a function
    
    Args:
        func (callable): The function to test
        arg: The single argument on which the function will be estimate
        repeat (int): How often the function is tested
        
    Returns:
        float: Estimated duration of calling the function a single time
    """
    number = int(estimate_computation_speed(func, arg))
    func = functools.partial(func, arg)
    return min(timeit.repeat(func, number=number, repeat=repeat)) / number
Ejemplo n.º 6
0
def main():
    """main routine testing the performance"""
    print("Reports calls-per-second (larger is better)")
    print("  The `CUSTOM` method implemented by hand is the baseline case.")
    print("  The `FLEXIBLE` method is a serial implementation using the "
          "boundary conditions from the package.")
    print("  The other methods use the functions supplied by the package.\n")

    # Cartesian grid with different shapes and boundary conditions
    for shape in [(32, 32), (512, 512)]:
        for periodic in [True, False]:
            grid = UnitGrid(shape, periodic=periodic)
            print(grid)
            field = ScalarField.random_normal(grid)
            bcs = grid.get_boundary_conditions("natural", rank=0)
            expected = field.laplace("natural")

            for method in [
                    "CUSTOM", "FLEXIBLE", "OPTIMIZED", "numba", "scipy"
            ]:
                if method == "CUSTOM":
                    laplace = custom_laplace_2d(shape, periodic=periodic)
                elif method == "FLEXIBLE":
                    laplace = flexible_laplace_2d(bcs)
                elif method == "OPTIMIZED":
                    laplace = optimized_laplace_2d(bcs)
                elif method in {"numba", "scipy"}:
                    laplace = grid.make_operator("laplace",
                                                 bc=bcs,
                                                 backend=method)
                else:
                    raise ValueError(f"Unknown method `{method}`")

                # call once to pre-compile and test result
                if method == "OPTIMIZED":
                    result = laplace(field._data_all)
                    np.testing.assert_allclose(result, expected.data)
                    speed = estimate_computation_speed(laplace,
                                                       field._data_all)
                else:
                    np.testing.assert_allclose(laplace(field.data),
                                               expected.data)
                    speed = estimate_computation_speed(laplace, field.data)
                print(f"{method:>9s}: {int(speed):>9d}")
            print()

    # Cylindrical grid with different shapes
    for shape in [(32, 64), (512, 512)]:
        grid = CylindricalSymGrid(shape[0], [0, shape[1]], shape)
        print(f"Cylindrical grid, shape={shape}")
        field = ScalarField.random_normal(grid)
        bcs = Boundaries.from_data(grid, "derivative")
        expected = field.laplace(bcs)

        for method in ["CUSTOM", "numba"]:
            if method == "CUSTOM":
                laplace = custom_laplace_cyl_neumann(shape)
            elif method == "numba":
                laplace = grid.make_operator("laplace", bc=bcs)
            else:
                raise ValueError(f"Unknown method `{method}`")
            # call once to pre-compile and test result
            np.testing.assert_allclose(laplace(field.data), expected.data)
            speed = estimate_computation_speed(laplace, field.data)
            print(f"{method:>8s}: {int(speed):>9d}")
        print()

    # Spherical grid with different shapes
    for shape in [32, 512]:
        grid = SphericalSymGrid(shape, shape)
        print(grid)
        field = ScalarField.random_normal(grid)
        bcs = Boundaries.from_data(grid, "derivative")

        for conservative in [True, False]:
            laplace = grid.make_operator("laplace",
                                         bcs,
                                         conservative=conservative)
            laplace(field.data)  # call once to pre-compile
            speed = estimate_computation_speed(laplace, field.data)
            print(
                f" numba (conservative={str(conservative):<5}): {int(speed):>9d}"
            )
        print()
Ejemplo n.º 7
0
def main():
    """ main routine testing the performance """
    print("Reports calls-per-second (larger is better)")
    print("  The `CUSTOM` method implemented by hand is the baseline case.")
    print(
        "  The `FLEXIBLE` method is a serial implementation using the "
        "boundary conditions from the package."
    )
    print("  The other methods use the functions supplied by the package.\n")

    # Cartesian grid with different shapes and boundary conditions
    for shape in [(32, 32), (512, 512)]:
        data = np.random.random(shape)
        for periodic in [True, False]:
            grid = UnitGrid(shape, periodic=periodic)
            bcs = Boundaries.from_data(grid, "natural")
            print(grid)
            result = cartesian.make_laplace(bcs, method="scipy")(data)

            for method in ["FLEXIBLE", "CUSTOM", "numba", "matrix", "scipy"]:
                if method == "FLEXIBLE":
                    laplace = flexible_laplace_2d(bcs)
                elif method == "CUSTOM":
                    laplace = custom_laplace_2d(shape, periodic=periodic)
                elif method in {"numba", "matrix", "scipy"}:
                    laplace = cartesian.make_laplace(bcs, method=method)
                else:
                    raise ValueError(f"Unknown method `{method}`")
                # call once to pre-compile and test result
                np.testing.assert_allclose(laplace(data), result)
                speed = estimate_computation_speed(laplace, data)
                print(f"{method:>8s}: {int(speed):>9d}")
            print()

    # Cylindrical grid with different shapes
    for shape in [(32, 64), (512, 512)]:
        data = np.random.random(shape)
        grid = CylindricalGrid(shape[0], [0, shape[1]], shape)
        print(f"Cylindrical grid, shape={shape}")
        bcs = Boundaries.from_data(grid, "no-flux")
        laplace_cyl = cylindrical.make_laplace(bcs)
        result = laplace_cyl(data)

        for method in ["CUSTOM", "numba"]:
            if method == "CUSTOM":
                laplace = custom_laplace_cyl_no_flux(shape)
            elif method == "numba":
                laplace = laplace_cyl
            else:
                raise ValueError(f"Unknown method `{method}`")
            # call once to pre-compile and test result
            np.testing.assert_allclose(laplace(data), result)
            speed = estimate_computation_speed(laplace, data)
            print(f"{method:>8s}: {int(speed):>9d}")
        print()

    # Spherical grid with different shapes
    for shape in [32, 512]:
        data = np.random.random(shape)
        grid = SphericalGrid(shape, shape)
        print(grid)
        bcs = Boundaries.from_data(grid, "no-flux")
        make_laplace = spherical.make_laplace

        for conservative in [True, False]:
            laplace = make_laplace(bcs, conservative=conservative)
            # call once to pre-compile
            laplace(data)
            speed = estimate_computation_speed(laplace, data)
            print(f" numba (conservative={str(conservative):<5}): {int(speed):>9d}")
        print()