Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
4c27b0f
Implemented shared memory parallelization for shot range loop
hidekb May 30, 2025
393c23f
Formatting
hidekb May 30, 2025
19f021e
Corrected branching by macro variables
hidekb May 30, 2025
85b9e2b
Formatting
hidekb May 30, 2025
3277279
For checking scalability
hidekb Jun 4, 2025
6e87b84
Implemented VerletList by Cabana
hidekb Jun 10, 2025
e2b4b5d
Formatting
hidekb Jun 10, 2025
33a9ebb
Corrected macro variable
hidekb Jun 10, 2025
21e6e94
Corrected the case for without SHAREDMEMORY
hidekb Jun 11, 2025
0232ef4
Slightly modified the creation of VerletList
hidekb Jun 11, 2025
bd7bc1d
Formatting
hidekb Jun 11, 2025
76cbc59
Fixed bug
hidekb Jun 11, 2025
c168def
Formatting
hidekb Jun 11, 2025
91b9531
Modified core/CMakeLists.txt due to warning from cabana and kokkos
hidekb Jun 12, 2025
b96a9f5
Formatting
hidekb Jun 12, 2025
80e8e25
Added comments
hidekb Jun 12, 2025
fc5e46d
Formatting
hidekb Jun 12, 2025
ddd553c
Improved computation rate
hidekb Jun 12, 2025
835c236
Formatting
hidekb Jun 12, 2025
c466a17
Removed empty cell from calculations
hidekb Jun 12, 2025
2085860
Formatting
hidekb Jun 12, 2025
61f84f0
Modified rebuild_flag
hidekb Jun 14, 2025
e6b9f7e
Small refactoring and Fixed rebuild_flag
hidekb Jun 15, 2025
a5e5741
Small refactoring
hidekb Jun 16, 2025
3104bd7
Formatting
hidekb Jun 16, 2025
31ca6a9
Ingnored modernize-use-nullptr in Cabana_Parallel.hpp
hidekb Jun 16, 2025
75bada7
Formatting
hidekb Jun 16, 2025
f40d4f5
Corrected CMakeLists.txt
hidekb Jun 16, 2025
970bbaa
Formatting
hidekb Jun 16, 2025
e6afa56
Modified ifdef in forces_inline
hidekb Jun 17, 2025
01160e0
Fixed compiling Kokkos with clang_tidy
hidekb Jun 17, 2025
be95f0a
Formatting
hidekb Jun 17, 2025
6f3ecf3
Fixed warning: modernize-use-nullptr in Kokkos
hidekb Jun 17, 2025
c5d43d3
Refactoring
hidekb Jun 20, 2025
01cc1d8
Formatting
hidekb Jun 20, 2025
97a4405
Deleted some variables
hidekb Jun 25, 2025
528e51d
Modified write_particles()
hidekb Jun 25, 2025
f688de4
Formatting
hidekb Jun 25, 2025
a798066
Implemented optimizing max_counts for VerletList
hidekb Jun 28, 2025
3fc4140
Modified creation of VerletList
hidekb Jun 30, 2025
e344e6e
Formatting
hidekb Jun 30, 2025
dee9d20
Added load balancing for verlet list
hidekb Jul 1, 2025
87dc452
Formatting
hidekb Jul 1, 2025
3a1d94c
Added addNeighborNonAtomic
hidekb Jul 3, 2025
74d65fa
Added new function in custom_verlet_list.hpp
hidekb Jul 3, 2025
78b11ea
Formatting
hidekb Jul 3, 2025
3dc6b79
Modifed addNeighbor
hidekb Jul 4, 2025
73ef5d7
Formatting
hidekb Jul 4, 2025
dca72ed
Modified verlet_list_loop
hidekb Jul 7, 2025
1763d69
Experiment for computational rate
hidekb Jul 9, 2025
3e2d669
Improved computation rate
hidekb Jul 11, 2025
802def7
Formatting
hidekb Jul 11, 2025
2897213
Fixed warning
hidekb Jul 14, 2025
ce581ab
Formatting
hidekb Jul 14, 2025
5758065
Fixed a bug
hidekb Jul 15, 2025
251f993
Improved computation rate
hidekb Jul 17, 2025
7d0b60e
Formatting
hidekb Jul 17, 2025
592f407
Implemented practical max_counts
hidekb Jul 18, 2025
1b8fb35
Fixed bugs
hidekb Jul 21, 2025
97be7d7
Formatting
hidekb Jul 21, 2025
932510b
Small refactoring
hidekb Jul 24, 2025
2a6753a
Formatting
hidekb Jul 24, 2025
3130c28
Implemented non-Atomic Add for Verlet List
hidekb Jul 24, 2025
8cb8de2
Formatting and add new header of functor for force calc
hidekb Jul 24, 2025
98dce63
Formatting
hidekb Jul 24, 2025
3344aeb
Small refactoring
hidekb Jul 28, 2025
cdafecf
Formatting
hidekb Jul 28, 2025
9e36c08
Refactoring
hidekb Aug 1, 2025
aac680c
Formatting
hidekb Aug 1, 2025
1774c9a
Formatting
hidekb Aug 1, 2025
30b9b67
Fixed warnings
hidekb Aug 1, 2025
f51269f
Fixed warnings
hidekb Aug 1, 2025
e9617f8
Fixed warnings
hidekb Aug 1, 2025
855185b
Merge remote-tracking branch 'upstream/python' into shared_memory_par…
jngrad Aug 5, 2025
d5ad314
Sort out ifdefs
jngrad Aug 5, 2025
a0c0ba7
Refactoring
hidekb Aug 5, 2025
3f88658
Formatting
hidekb Aug 5, 2025
95ace64
Fixed missing hpp file
hidekb Aug 5, 2025
30704ab
Fixed bugs
hidekb Aug 5, 2025
f94cd6c
Formatting
hidekb Aug 5, 2025
2c20418
Deleted unnecessary comments
hidekb Aug 6, 2025
9d4310c
Refactor
jngrad Aug 6, 2025
78c1fb3
Merge remote-tracking branch 'upstream/python' into shared_memory_par…
jngrad Aug 6, 2025
28a9a73
Refactor
jngrad Aug 6, 2025
c4406fb
Fix regressions
jngrad Aug 6, 2025
b78db8e
Fix regressions
jngrad Aug 6, 2025
082d467
Avoid copies
jngrad Aug 7, 2025
b6492c9
Fixed bug for NPT with P3M
hidekb Aug 7, 2025
63477c1
Formatting
hidekb Aug 7, 2025
2a55a71
Apply SOLID principles
jngrad Aug 8, 2025
73eeaa5
Merge remote-tracking branch 'upstream/python' into shared_memory_par…
jngrad Aug 8, 2025
65e699b
style
jngrad Aug 8, 2025
a86731c
disable test with instrumentation
jngrad Aug 8, 2025
422d559
Fix regression
jngrad Aug 8, 2025
0ac9c6e
Fix error message
jngrad Aug 8, 2025
5593a76
Fix npt test
jngrad Aug 8, 2025
910c06d
fixup
jngrad Aug 8, 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
12 changes: 11 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,11 @@ if(ESPRESSO_BUILD_WITH_SHARED_MEMORY_PARALLELISM)
set(CMAKE_SHARED_LIBRARY_PREFIX "lib")
set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "")
set(Kokkos_ENABLE_OPENMP ON CACHE BOOL "")
set(Kokkos_ENABLE_IMPL_VIEW_LEGACY ON CACHE BOOL "")
set(Kokkos_ENABLE_COMPLEX_ALIGN ON CACHE BOOL "")
set(Kokkos_ENABLE_AGGRESSIVE_VECTORIZATION ON CACHE BOOL "")
set(Kokkos_ENABLE_HWLOC ON CACHE BOOL "")
set(Kokkos_ARCH_NATIVE ON CACHE BOOL "")
FetchContent_MakeAvailable(kokkos)
set(BUILD_SHARED_LIBS ${ESPRESSO_BUILD_SHARED_LIBS_DEFAULT})
set(CMAKE_SHARED_LIBRARY_PREFIX "${ESPRESSO_SHARED_LIBRARY_PREFIX}")
Expand All @@ -604,7 +609,7 @@ if(ESPRESSO_BUILD_WITH_SHARED_MEMORY_PARALLELISM)
FetchContent_Declare(
cabana
GIT_REPOSITORY https://github.com/ECP-copa/Cabana.git
GIT_TAG ebfaa51 # 0.7.0 with patches
GIT_TAG e76c1a1 # 0.7.0 with patches
PATCH_COMMAND patch -p0 < ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cabana.patch
)
# cmake-format: on
Expand All @@ -628,6 +633,7 @@ if(ESPRESSO_BUILD_WITH_SHARED_MEMORY_PARALLELISM)
list(APPEND SKIP_CLANG_TIDY_CHECKS "-modernize-use-bool-literals")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-modernize-use-equals-delete")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-modernize-use-equals-default")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-modernize-use-nullptr")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-modernize-pass-by-value")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-modernize-loop-convert")
list(APPEND SKIP_CLANG_TIDY_CHECKS "-modernize-return-braced-init-list")
Expand All @@ -636,6 +642,10 @@ if(ESPRESSO_BUILD_WITH_SHARED_MEMORY_PARALLELISM)
list(APPEND SKIP_CLANG_TIDY_CHECKS "-readability-simplify-boolean-expr")
list(APPEND SKIP_CLANG_TIDY_CHECKS
"-readability-avoid-const-params-in-decls")
list(APPEND SKIP_CLANG_TIDY_CHECKS
"-clang-analyzer-optin.performance.Padding")
list(APPEND SKIP_CLANG_TIDY_CHECKS
"-clang-analyzer-security.insecureAPI.strcpy")
espresso_override_clang_tidy_checks(
ESPRESSO_CABANA_CXX_CLANG_TIDY "${SKIP_CLANG_TIDY_CHECKS}"
"${SKIP_CLANG_TIDY_CHECKS_CXX}")
Expand Down
34 changes: 34 additions & 0 deletions src/core/BoxGeometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,40 @@ class BoxGeometry {
get_mi_coord(a[2], b[2], 2)};
}

/**
* @brief Get the minimum-image vector between two coordinates.
*
* @tparam T Floating point type.
*
* @param a0 x element of the terminal point.
* @param a1 y element of the terminal point.
* @param a2 z element of the terminal point.
* @param b0 x element of the initial point.
* @param b1 y element of the initial point.
* @param b2 z element of the initial point.
* @return Vector from @p b to @p a that minimizes the distance across
* periodic images, i.e. <tt>a - b</tt>.
*/
template <typename T>
Utils::Vector<T, 3> get_mi_vector(T const &a0, T const &a1, T const &a2,
T const &b0, T const &b1,
T const &b2) const {
if (type() == BoxType::LEES_EDWARDS) {
auto const shear_plane_normal = lees_edwards_bc().shear_plane_normal;
auto a_tmp = Utils::Vector<T, 3>{a0, a1, a2};
auto b_tmp = Utils::Vector<T, 3>{b0, b1, b2};
a_tmp[shear_plane_normal] = Algorithm::periodic_fold(
a_tmp[shear_plane_normal], m_length[shear_plane_normal]);
b_tmp[shear_plane_normal] = Algorithm::periodic_fold(
b_tmp[shear_plane_normal], m_length[shear_plane_normal]);
return lees_edwards_bc().distance(a_tmp - b_tmp, m_length, m_length_half,
m_length_inv, m_periodic);
}
assert(type() == BoxType::CUBOID);
return {get_mi_coord(a0, b0, 0), get_mi_coord(a1, b1, 1),
get_mi_coord(a2, b2, 2)};
}

BoxType type() const { return m_type; }
void set_type(BoxType type) { m_type = type; }

Expand Down
41 changes: 41 additions & 0 deletions src/core/aosoa_pack.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2025 The ESPResSo project
*
* This file is part of ESPResSo.
*
* ESPResSo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ESPResSo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#ifdef SHARED_MEMORY_PARALLELISM

#include "cell_system/CellStructure.hpp"

#include <Cabana_Core.hpp>

struct CellStructure::AoSoA_pack {
CellStructure::AoSoAType::member_slice_type<0> position;
CellStructure::AoSoAType::member_slice_type<1> charge;
CellStructure::AoSoAType::member_slice_type<2> id;
CellStructure::AoSoAType::member_slice_type<3> type;

AoSoA_pack() = default;

AoSoA_pack(CellStructure::AoSoAType &aosoa)
: position(Cabana::slice<0>(aosoa)), charge(Cabana::slice<1>(aosoa)),
id(Cabana::slice<2>(aosoa)), type(Cabana::slice<3>(aosoa)) {}
};

#endif // SHARED_MEMORY_PARALLELISM
134 changes: 134 additions & 0 deletions src/core/cell_system/CellStructure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@
#include "cell_system/CellStructureType.hpp"
#include "communication.hpp"
#include "lees_edwards/lees_edwards.hpp"
#include "particle_enumeration.hpp"
#include "particle_reduction.hpp"
#include "system/System.hpp"

#include <utils/Vector.hpp>
#include <utils/contains.hpp>
#include <utils/math/int_pow.hpp>
#include <utils/math/sqr.hpp>

#include <boost/mpi/collectives/all_reduce.hpp>
Expand All @@ -56,9 +58,139 @@
#include <vector>

#ifdef SHARED_MEMORY_PARALLELISM
#include "aosoa_pack.hpp"
#include "custom_verlet_list.hpp"
#include <Cabana_Core.hpp>
#include <Cabana_NeighborList.hpp>
#include <Kokkos_Core.hpp>
#endif

CellStructure::~CellStructure() {
#ifdef SHARED_MEMORY_PARALLELISM
if (m_local_force) {
m_local_force.reset();
}
#ifdef ROTATION
if (m_local_torque) {
m_local_torque.reset();
}
#endif
#ifdef NPT
if (m_local_virial) {
m_local_virial.reset();
}
#endif
if (m_aosoa) {
m_aosoa.reset();
}
if (m_particle_storage) {
m_particle_storage.reset();
}
if (m_verlet_list_cabana) {
m_verlet_list_cabana.reset();
}
// Kokkos handle can be freed after all Cabana containers have been freed
m_kokkos_handle.reset();
#endif
}

#ifdef SHARED_MEMORY_PARALLELISM

void CellStructure::set_kokkos_handle(
std::shared_ptr<Communication::KokkosHandle> handle) {
m_kokkos_handle = std::move(handle);
}

static auto estimate_max_counts(int max_prefactor, double pair_cutoff,
std::size_t number_of_unique_particles) {
if (std::isinf(pair_cutoff)) {
return number_of_unique_particles;
}
if (pair_cutoff < 0.) {
pair_cutoff = 0.;
}
auto const volume = Utils::int_pow<3>(pair_cutoff);
auto max_counts = static_cast<std::size_t>(
std::ceil(static_cast<double>(max_prefactor) * volume));
#ifdef COLLISION_DETECTION
std::size_t constexpr threshold_num = 64;
#else
std::size_t constexpr threshold_num = 16;
#endif
if (max_counts < threshold_num) {
max_counts = std::min(threshold_num, number_of_unique_particles);
}
return max_counts;
}

void CellStructure::rebuild_local_properties(std::size_t const num_threads,
double const pair_cutoff) {
assert(m_kokkos_handle);
auto const num_part = get_unique_particles().size();
m_local_force =
std::make_unique<ForceType>("local_force", num_part, num_threads);
#ifdef ROTATION
m_local_torque =
std::make_unique<ForceType>("local_torque", num_part, num_threads);
#endif
#ifdef NPT
m_local_virial = std::make_unique<VirialType>("local_virial", num_threads);
#endif
m_particle_storage = std::make_unique<AoSoAType>("particles", num_part);
m_particle_storage->resize(num_part);
// particle properties are defined in aosoa_pack.hpp
m_aosoa = std::make_unique<AoSoA_pack>(*m_particle_storage);

auto max_counts = estimate_max_counts(m_max_prefactor, pair_cutoff, num_part);
m_verlet_list_cabana = std::make_unique<ListType>(0ul, num_part, max_counts);
}

void CellStructure::reset_local_properties() {
Kokkos::deep_copy(get_local_force(), 0);
#ifdef ROTATION
Kokkos::deep_copy(get_local_torque(), 0);
#endif
#ifdef NPT
Kokkos::deep_copy(get_local_virial(), 0);
#endif
}

void CellStructure::set_index_map() {
auto &unique_particles = m_unique_particles;
unique_particles.clear();
unique_particles.resize(count_local_particles());
std::unordered_set<int> registered_index{};
using execution_space = Kokkos::DefaultExecutionSpace;
int n_threads = execution_space().concurrency();
std::vector<int> max_ids(n_threads);
enumerate_local_particles(
*this, [&unique_particles, &max_ids](std::size_t index, Particle &p) {
unique_particles[index] = &p;
const int thread_num = omp_get_thread_num();
max_ids[thread_num] = std::max(p.id(), max_ids[thread_num]);
});
int max_id = *(std::max_element(max_ids.begin(), max_ids.end()));
for (auto &p : ghost_particles()) {
auto const *local_particle = get_local_particle(p.id());
if (not local_particle) {
continue;
}
if (not local_particle->is_ghost()) {
continue;
}
if (registered_index.contains(p.id())) {
continue;
}
registered_index.insert(p.id());
unique_particles.emplace_back(&p);
max_id = std::max(p.id(), max_id);
}
registered_index.clear();
m_cached_max_local_particle_id = max_id;
}

#endif // SHARED_MEMORY_PARALLELISM

CellStructure::CellStructure(BoxGeometry const &box)
: m_decomposition{std::make_unique<AtomDecomposition>(box)} {}

Expand Down Expand Up @@ -236,6 +368,7 @@ void CellStructure::resort_particles(bool global_flag) {

auto const &lebc = get_system().box_geo->lees_edwards_bc();
m_rebuild_verlet_list = true;
m_rebuild_verlet_list_cabana = true;
m_le_pos_offset_at_last_resort = lebc.pos_offset;

#ifdef ADDITIONAL_CHECKS
Expand Down Expand Up @@ -285,6 +418,7 @@ void CellStructure::set_verlet_skin(double value) {
assert(value >= 0.);
m_verlet_skin = value;
m_verlet_skin_set = true;
m_rebuild_verlet_list_cabana = true;
get_system().on_verlet_skin_change();
}

Expand Down
Loading