Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allocating multiple blocks to one mpi rank in LB #5026

Open
wants to merge 38 commits into
base: python
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
e76ecf5
Annotation for pure fluid integration
Nov 6, 2024
067d3fa
Annotation for pure fluid integration 2nd
Nov 6, 2024
6392e3c
Allocating many blocks to mpi rank
hidekb Jan 7, 2025
9e7f3c9
Add test script about domain decomposition for LBM
hidekb Jan 8, 2025
e3ee829
Added unit_tests and python integration tests for allocating multipul…
hidekb Jan 9, 2025
0135af7
Deleted unnecessary comment
hidekb Jan 9, 2025
0793276
Formatting codes for allocating multiple blocks to mpi rank
hidekb Jan 10, 2025
0c33a15
Merge branch 'python' into scale-lbm
hidekb Jan 10, 2025
d40edca
Formatting codes
hidekb Jan 10, 2025
75e9e17
Formatting codes for git style
hidekb Jan 10, 2025
e8d0b1e
Solve the conflict
hidekb Jan 10, 2025
281abc2
Formatting codes and Fix benchmarks script
hidekb Jan 10, 2025
a55c6bf
Responding to Reviews
hidekb Jan 15, 2025
cb1561c
Formatting codes
hidekb Jan 15, 2025
42a24e7
Formatting codes for clang-sanitizer
hidekb Jan 15, 2025
e26d439
Fortting codes in git style
hidekb Jan 15, 2025
a91eaf5
Responding reviews
hidekb Jan 17, 2025
a509615
Formatting codes
hidekb Jan 17, 2025
2d221c1
Fixed problems with debuging option
hidekb Jan 17, 2025
6091226
Formatting codes for clang-sanitizer
hidekb Jan 17, 2025
a6bac85
Responding to Reviews
hidekb Jan 17, 2025
1b0e7c1
Removing unneccessary comments
hidekb Jan 17, 2025
9d9bd13
Formatting codes for git-style
hidekb Jan 17, 2025
a806a06
Avoiding unintentional errors
hidekb Jan 20, 2025
f3a1520
Narrowing the scope of integerisation function
hidekb Jan 22, 2025
2229672
Refactoring
jngrad Jan 22, 2025
75d4564
Merge branch 'python' into scale-lbm
jngrad Jan 23, 2025
5f2993f
Bugfixes (WIP)
jngrad Jan 28, 2025
5e7b48b
Redesign LB composition design pattern
jngrad Jan 29, 2025
ce0de63
Cleanup
jngrad Jan 29, 2025
7acd2ba
Style
jngrad Jan 29, 2025
6a62442
Merge branch 'python' into scale-lbm
jngrad Jan 29, 2025
859c5ae
Responce to a review
hidekb Jan 30, 2025
9099a3d
Style
hidekb Jan 30, 2025
d695178
Style for git-style
hidekb Jan 30, 2025
b307474
Style for code formatting
hidekb Jan 30, 2025
3a44a6c
Style
hidekb Jan 30, 2025
0c8a53d
Style for Pylint
hidekb Jan 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion doc/sphinx/lb.rst
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,8 @@ will be used instead of the default ones.

.. note::

At the moment, LB only supports the case ``shear_plane_normal="y"``.
At the moment, LB only supports the case ``shear_plane_normal="y"`` and
doesn't allow domain decomposition along the shear and normal directions.

.. _Reading and setting properties of single lattice nodes:

Expand Down
11 changes: 10 additions & 1 deletion maintainer/benchmarks/lb.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
parser.add_argument("--output", metavar="FILEPATH", action="store",
type=str, required=False, default="benchmarks.csv",
help="Output file (default: benchmarks.csv)")
parser.add_argument("--blocks_per_mpi_rank", action="store", nargs=3,
type=int, default=[1, 1, 1], required=False,
help="blocks per mpi rank")
parser.add_argument("--weak_scaling", action="store_true", required=False,
help="The measurement of weak scaling")

args = parser.parse_args()

Expand Down Expand Up @@ -101,6 +106,9 @@
lb_grid = 3 * [lb_grid]
box_l = 3 * [box_l]

if args.weak_scaling:
box_l *= system.cell_system.node_grid

print(f"box length: {box_l}")
print(f"LB shape: {lb_grid}")
print(f"LB agrid: {agrid:.3f}")
Expand Down Expand Up @@ -145,7 +153,8 @@
if args.multi_gpu:
system.cuda_init_handle.call_method("set_device_id_per_rank")
lbf = lb_class(agrid=agrid, tau=system.time_step, kinematic_viscosity=1.,
density=1., single_precision=args.single_precision)
density=1., single_precision=args.single_precision,
blocks_per_mpi_rank=args.blocks_per_mpi_rank)
system.lb = lbf
if n_part:
system.thermostat.set_lb(LB_fluid=lbf, gamma=1., seed=42)
Expand Down
3 changes: 2 additions & 1 deletion src/core/unit_tests/ek_interface_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ static auto make_ek_actor() {
auto constexpr n_ghost_layers = 1u;
auto constexpr single_precision = true;
ek_lattice = std::make_shared<LatticeWalberla>(
params.grid_dimensions, ::communicator.node_grid, n_ghost_layers);
params.grid_dimensions, ::communicator.node_grid,
::communicator.node_grid, n_ghost_layers);
ek_container = std::make_shared<EK::EKWalberla::ek_container_type>(
params.tau, walberla::new_ek_poisson_none(ek_lattice, single_precision));
ek_reactions = std::make_shared<EK::EKWalberla::ek_reactions_type>();
Expand Down
6 changes: 4 additions & 2 deletions src/core/unit_tests/lb_particle_coupling_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ static auto make_lb_actor() {
auto constexpr single_precision = false;
lb_params = std::make_shared<LB::LBWalberlaParams>(params.agrid, params.tau);
lb_lattice = std::make_shared<LatticeWalberla>(
params.grid_dimensions, ::communicator.node_grid, n_ghost_layers);
params.grid_dimensions, ::communicator.node_grid,
::communicator.node_grid, n_ghost_layers);
lb_fluid = new_lb_walberla_cpu(lb_lattice, params.viscosity, params.density,
single_precision);
lb_fluid->set_collision_model(params.kT, params.seed);
Expand Down Expand Up @@ -535,7 +536,8 @@ bool test_lb_domain_mismatch_local() {
auto const params = std::make_shared<LB::LBWalberlaParams>(0.5, 0.01);
::communicator.node_grid = node_grid_reversed;
auto const lattice = std::make_shared<LatticeWalberla>(
Utils::Vector3i{12, 12, 12}, node_grid_original, n_ghost_layers);
Utils::Vector3i{12, 12, 12}, node_grid_original, node_grid_original,
n_ghost_layers);
auto const ptr = new_lb_walberla_cpu(lattice, 1.0, 1.0, false);
ptr->set_collision_model(0.0, 0);
::communicator.node_grid = node_grid_original;
Expand Down
37 changes: 24 additions & 13 deletions src/python/espressomd/detail/walberla.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,31 @@
import numpy as np

import espressomd.shapes
import espressomd.code_features
from espressomd.script_interface import ScriptInterfaceHelper, script_interface_register


@script_interface_register
class LatticeWalberla(ScriptInterfaceHelper):
"""
Interface to a waBLerla lattice.
Interface to a waLBerla lattice.

Parameters
----------
agrid : :obj:`float`
Lattice constant. The box size in every direction must be an integer
multiple of ``agrid``. Cannot be provided together with ``lattice``.
n_ghost_layers : :obj:`int`, optional
Lattice ghost layer thickness in units of ``agrid``.
blocks_per_mpi_rank : (3,) array_like of :obj:`int`, optional
Distribute more than one block to each MPI rank.
Meant to improve cache locality. Experimental.

"""
_so_name = "walberla::LatticeWalberla"
_so_creation_policy = "GLOBAL"
_so_features = ("WALBERLA",)

def __init__(self, *args, **kwargs):
if not espressomd.code_features.has_features("WALBERLA"):
raise NotImplementedError("Feature WALBERLA not compiled in")

if "sip" not in kwargs:
params = self.default_params()
params.update(kwargs)
Expand All @@ -46,14 +55,17 @@ def __init__(self, *args, **kwargs):
else:
super().__init__(**kwargs)

def valid_keys(self):
return {"agrid", "n_ghost_layers"}
@classmethod
def valid_keys(cls):
return {"agrid", "n_ghost_layers", "blocks_per_mpi_rank"}

def required_keys(self):
return self.valid_keys()
@classmethod
def required_keys(cls):
return {"agrid"}

def default_params(self):
return {}
@classmethod
def default_params(cls):
return {"n_ghost_layers": 1, "blocks_per_mpi_rank": [1, 1, 1]}

def get_node_indices_inside_shape(self, shape):
if not isinstance(shape, espressomd.shapes.Shape):
Expand Down Expand Up @@ -146,10 +158,9 @@ def get_slice_bounding_box(slices, grid_size):


class VTKOutputBase(ScriptInterfaceHelper):
_so_features = ("WALBERLA",)

def __init__(self, *args, **kwargs):
if not espressomd.code_features.has_features("WALBERLA"):
raise NotImplementedError("Feature WALBERLA not compiled in")
if "sip" not in kwargs:
params = self.default_params()
params.update(kwargs)
Expand Down
16 changes: 16 additions & 0 deletions src/python/espressomd/electrokinetics.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
import espressomd.shapes


def _check_lattice_blocks(class_name, pack):
if "lattice" in pack and np.prod(pack["lattice"].blocks_per_mpi_rank) != 1:
raise NotImplementedError(
f"Using more than one block per MPI rank is not supported for {class_name}")


@script_interface_register
class EKFFT(ScriptInterfaceHelper):
"""
Expand All @@ -46,6 +52,10 @@ class EKFFT(ScriptInterfaceHelper):
_so_features = ("WALBERLA_FFT",)
_so_creation_policy = "GLOBAL"

def __init__(self, *args, **kwargs):
_check_lattice_blocks(self.__class__.__name__, kwargs)
super().__init__(*args, **kwargs)


@script_interface_register
class EKNone(ScriptInterfaceHelper):
Expand All @@ -64,6 +74,10 @@ class EKNone(ScriptInterfaceHelper):
_so_features = ("WALBERLA",)
_so_creation_policy = "GLOBAL"

def __init__(self, *args, **kwargs):
_check_lattice_blocks(self.__class__.__name__, kwargs)
super().__init__(*args, **kwargs)


@script_interface_register
class EKSpecies(ScriptInterfaceHelper,
Expand Down Expand Up @@ -167,6 +181,7 @@ def __init__(self, *args, **kwargs):
if "sip" not in kwargs:
params = self.default_params()
params.update(kwargs)
_check_lattice_blocks(self.__class__.__name__, params)
super().__init__(*args, **params)
else:
super().__init__(**kwargs)
Expand Down Expand Up @@ -580,6 +595,7 @@ class VTKOutput(VTKOutputBase):
_so_name = "walberla::EKVTKHandle"
_so_creation_policy = "GLOBAL"
_so_bind_methods = ("enable", "disable", "write")
_so_features = ("WALBERLA",)

def required_keys(self):
return self.valid_keys() - self.default_params().keys()
Expand Down
29 changes: 20 additions & 9 deletions src/python/espressomd/lb.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ def validate_params(self, params):
pass

def valid_keys(self):
return {"agrid", "tau", "density", "ext_force_density",
"kinematic_viscosity", "lattice", "kT", "seed"}
return {"agrid", "tau", "lattice", "density", "ext_force_density",
"kinematic_viscosity", "kT", "seed", "blocks_per_mpi_rank"}

def required_keys(self):
return {"lattice", "density", "kinematic_viscosity", "tau"}
Expand Down Expand Up @@ -119,7 +119,7 @@ class LBFluidWalberla(HydrodynamicInteraction,

Parameters
----------
lattice : :obj:`espressomd.lb.LatticeWalberla <espressomd.detail.walberla.LatticeWalberla>`
lattice : :obj:`~espressomd.detail.walberla.LatticeWalberla`
Lattice object. If not provided, a default one will be constructed
using the ``agrid`` parameter.
agrid : :obj:`float`
Expand All @@ -141,6 +141,9 @@ class LBFluidWalberla(HydrodynamicInteraction,
Required for a thermalized fluid. Must be positive.
single_precision : :obj:`bool`, optional
Use single-precision floating-point arithmetic.
\\*\\*kwargs :
Additional parameters forwarded to the
:obj:`~espressomd.detail.walberla.LatticeWalberla` constructor.

Methods
-------
Expand Down Expand Up @@ -235,14 +238,21 @@ def __init__(self, *args, **kwargs):
def validate_params(self, params):
super().validate_params(params)

# extract lattice-specific parameters
lattice_params = {}
for key in LatticeWalberla.valid_keys():
if key in params:
lattice_params[key] = params.pop(key)

# construct default lattice if necessary
if params.get("lattice") is None:
if "agrid" not in params:
raise ValueError("missing argument 'lattice' or 'agrid'")
params["lattice"] = LatticeWalberla(
agrid=params.pop("agrid"), n_ghost_layers=1)
elif "agrid" in params:
raise ValueError("cannot provide both 'lattice' and 'agrid'")
for key in LatticeWalberla.required_keys():
if key not in lattice_params:
raise ValueError(f"missing argument 'lattice' or '{key}'")
params["lattice"] = LatticeWalberla(**lattice_params)
elif lattice_params:
any_key = list(lattice_params.keys())[0]
raise ValueError(f"cannot provide both 'lattice' and '{any_key}'")

utils.check_required_keys(self.required_keys(), params.keys())
utils.check_valid_keys(self.valid_keys(), params.keys())
Expand Down Expand Up @@ -660,6 +670,7 @@ class VTKOutput(VTKOutputBase):
_so_name = "walberla::LBVTKHandle"
_so_creation_policy = "GLOBAL"
_so_bind_methods = ("enable", "disable", "write")
_so_features = ("WALBERLA",)

def required_keys(self):
return self.valid_keys() - self.default_params().keys()
Expand Down
6 changes: 6 additions & 0 deletions src/script_interface/walberla/LBFluid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ void LBFluidGPU::make_instance(VariantMap const &params) {
auto const visc = get_value<double>(params, "kinematic_viscosity");
auto const dens = get_value<double>(params, "density");
auto const precision = get_value<bool>(params, "single_precision");
auto const blocks_per_mpi_rank = get_value<Utils::Vector3i>(
m_lattice->get_parameter("blocks_per_mpi_rank"));
if (blocks_per_mpi_rank != Utils::Vector3i{{1, 1, 1}}) {
throw std::runtime_error(
"Using more than one block per MPI rank is not supported for GPU LB");
}
jngrad marked this conversation as resolved.
Show resolved Hide resolved
auto const lb_lattice = m_lattice->lattice();
auto const lb_visc = m_conv_visc * visc;
auto const lb_dens = m_conv_dens * dens;
Expand Down
12 changes: 11 additions & 1 deletion src/script_interface/walberla/LatticeWalberla.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class LatticeWalberla : public AutoParameters<LatticeWalberla> {
std::shared_ptr<::LatticeWalberla> m_lattice;
double m_agrid;
Utils::Vector3d m_box_l;
Utils::Vector3i m_blocks_per_mpi_rank;

public:
LatticeWalberla() {
Expand All @@ -53,14 +54,20 @@ class LatticeWalberla : public AutoParameters<LatticeWalberla> {
{"shape", AutoParameter::read_only,
[this]() { return m_lattice->get_grid_dimensions(); }},
{"_box_l", AutoParameter::read_only, [this]() { return m_box_l; }},
{"blocks_per_mpi_rank", AutoParameter::read_only,
[this]() { return m_blocks_per_mpi_rank; }},
});
}

void do_construct(VariantMap const &args) override {
auto const &box_geo = *::System::get_system().box_geo;
m_agrid = get_value<double>(args, "agrid");
m_box_l = get_value_or<Utils::Vector3d>(args, "_box_l", box_geo.length());
m_blocks_per_mpi_rank =
get_value<Utils::Vector3i>(args, "blocks_per_mpi_rank");
auto const n_ghost_layers = get_value<int>(args, "n_ghost_layers");
auto const block_grid = Utils::hadamard_product(::communicator.node_grid,
m_blocks_per_mpi_rank);

context()->parallel_try_catch([&]() {
if (m_agrid <= 0.) {
Expand All @@ -69,10 +76,13 @@ class LatticeWalberla : public AutoParameters<LatticeWalberla> {
if (n_ghost_layers < 0) {
throw std::domain_error("Parameter 'n_ghost_layers' must be >= 0");
}
if (not(m_blocks_per_mpi_rank >= Utils::Vector3i::broadcast(1))) {
throw std::domain_error("Parameter 'blocks_per_mpi_rank' must be >= 1");
}
auto const grid_dim =
::LatticeWalberla::calc_grid_dimensions(m_box_l, m_agrid);
m_lattice = std::make_shared<::LatticeWalberla>(
grid_dim, ::communicator.node_grid,
grid_dim, ::communicator.node_grid, block_grid,
static_cast<unsigned int>(n_ghost_layers));
});
}
Expand Down
1 change: 0 additions & 1 deletion src/walberla_bridge/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ list(APPEND SKIP_CLANG_TIDY_CHECKS "-modernize-use-equals-delete")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-modernize-return-braced-init-list")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-bugprone-crtp-constructor-accessibility")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-bugprone-narrowing-conversions")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-bugprone-assert-side-effect")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-bugprone-exception-escape")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-bugprone-branch-clone")
if(WALBERLA_BUILD_WITH_CUDA)
Expand Down
Loading