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