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)
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()
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()
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
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
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()
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()