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

Parallel tree #4

Merged
merged 42 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
8a13a8d
WIP: Partitioning
tbetcke Sep 11, 2024
b39e69e
Partitioning is working.
tbetcke Sep 12, 2024
f990424
Better testing of parallel code.
tbetcke Sep 12, 2024
902f08a
WIP: Parallel tree generation
tbetcke Sep 12, 2024
59e3f9a
WIP: Testing block partitioning
tbetcke Sep 12, 2024
d86abf4
WIP: Block coarsening
tbetcke Sep 12, 2024
695239f
Testing the coarse partitioning.
tbetcke Sep 13, 2024
0cb3c77
Fix in coarse partitioning
tbetcke Sep 13, 2024
6532b49
Testing block partitioning
tbetcke Sep 13, 2024
ce53f8c
WIP: Block partitioning
tbetcke Sep 14, 2024
6d4c14e
WIP: Block partitioning
tbetcke Sep 14, 2024
7b684ff
Block partitioning works.
tbetcke Sep 15, 2024
2946e6b
Implementing finest out subblocks
tbetcke Sep 16, 2024
805666b
Added outer key generation
tbetcke Sep 16, 2024
be5d083
WIP: Refactor and cleanup
tbetcke Sep 17, 2024
301156c
WIP: Refactor
tbetcke Sep 17, 2024
8f0a5e8
WIP: Refactor
tbetcke Sep 20, 2024
44372e3
WIP: Parallel tests
tbetcke Sep 21, 2024
fc8e63d
WIP: distribute_complete_tree_test
tbetcke Sep 21, 2024
25c0e84
WIP: Test complete tree
tbetcke Sep 21, 2024
ccb8be5
WIP: Better binning
tbetcke Sep 22, 2024
8a3d6e5
Custom min max for MPI
tbetcke Sep 22, 2024
4eed598
WIP: Fixing global min max
tbetcke Sep 22, 2024
a6a2cb7
Specialised parsort for Morton keys
tbetcke Sep 22, 2024
2c2ed17
Fixed warnings
tbetcke Sep 22, 2024
f354653
More cleanup
tbetcke Sep 22, 2024
d4ebe77
WIP: Better testing
tbetcke Sep 22, 2024
c2db50b
WIP: Tests involving coarse tree
tbetcke Sep 22, 2024
887dfcf
WIP: distributed balanced tree
tbetcke Sep 22, 2024
a39ef8e
Balancing implemented
tbetcke Sep 22, 2024
5a8a8b7
Added distribution of points to correct ranks.
tbetcke Sep 23, 2024
a9caa55
Interior node topology
tbetcke Sep 24, 2024
31765db
WIP: Ghosts
tbetcke Sep 25, 2024
17d44c6
WIP: Neighbour keys
tbetcke Oct 1, 2024
baa5bb9
Testing creation of all keys.
tbetcke Oct 3, 2024
6f01f6c
Testing parallel octree
tbetcke Oct 4, 2024
5edcfb0
Dealing with neighbours
tbetcke Oct 4, 2024
de1b130
Fixed doc bugs
tbetcke Oct 4, 2024
ff8ecfe
Removed unnecessary dependency
tbetcke Oct 4, 2024
70eebe7
Removed bytemuck
tbetcke Oct 4, 2024
c8e5ac7
Fixed error
tbetcke Oct 4, 2024
eacb848
Deleted coarse tree example
tbetcke Oct 4, 2024
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
13 changes: 8 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ battleship = []
name = "bempp-octree"
version = "0.0.1-dev"
edition = "2021"
authors = ["Srinath Kailasa <[email protected]>, Timo Betcke <[email protected]>"]
authors = [
"Srinath Kailasa <[email protected]>, Timo Betcke <[email protected]>",
]
description = "A library to create Octrees"
license = "BSD-3-Clause"
homepage = "https://github.com/bempp/octree"
Expand All @@ -22,14 +24,15 @@ crate-type = ["cdylib", "lib"]

[dependencies]
itertools = "0.13.*"
rand = "0.8.5"
bytemuck = "1.*"
rand = { version = "0.8.5", features = ["alloc"] }
rand_chacha = "0.3.*"
num = "0.4.*"
vtkio = "0.6.*"
mpi = {version = "0.8.*", features = ["derive", "user-operations"] }
mpi = { version = "0.8.*", features = ["derive", "user-operations"] }

[profile.release]
debug = 1

[dev-dependencies]
rand_distr = "0.4.3"
#criterion = { version = "0.5.*", features = ["html_reports"]}
Expand Down
2 changes: 1 addition & 1 deletion examples/battleship.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use std::time::Instant;

#[cfg(feature = "battleship")]
use bempp_octree::octree::Octree;
use bempp_octree::serial::Octree;
#[cfg(feature = "battleship")]
use vtkio::model::*;

Expand Down
95 changes: 95 additions & 0 deletions examples/mpi_complete_tree.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//! Test the computation of a complete octree.

use bempp_octree::{
morton::MortonKey,
octree::{is_complete_linear_and_balanced, KeyType, Octree},
tools::{gather_to_all, generate_random_points},
};
use itertools::Itertools;
use mpi::traits::Communicator;
use rand::prelude::*;
use rand_chacha::ChaCha8Rng;

pub fn main() {
// Initialise MPI
let universe = mpi::initialize().unwrap();

// Get the world communicator
let comm = universe.world();

// Initialise a seeded Rng.
let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);

// Create `npoints` per rank.
let npoints = 10000;

// Generate random points.

let points = generate_random_points(npoints, &mut rng, &comm);

let tree = Octree::new(&points, 15, 50, &comm);

// We now check that each node of the tree has all its neighbors available.

let leaf_tree = tree.leaf_tree();
let all_keys = tree.all_keys();

assert!(is_complete_linear_and_balanced(leaf_tree, &comm));
for &key in leaf_tree {
// We only check interior keys. Leaf keys may not have a neighbor
// on the same level.
let mut parent = key.parent();
while parent.level() > 0 {
// Check that the key itself is there.
assert!(all_keys.contains_key(&key));
// Check that all its neighbours are there.
for neighbor in parent.neighbours().iter().filter(|&key| key.is_valid()) {
assert!(all_keys.contains_key(neighbor));
}
parent = parent.parent();
// Check that the parent is there.
assert!(all_keys.contains_key(&parent));
}
}

// At the end check that the root of the tree is also contained.
assert!(all_keys.contains_key(&MortonKey::root()));

// Count the number of ghosts on each rank
// Count the number of global keys on each rank.

// Assert that all ghosts are from a different rank and count them.

let nghosts = all_keys
.iter()
.filter_map(|(_, &value)| {
if let KeyType::Ghost(rank) = value {
assert!(rank != comm.size() as usize);
Some(rank)
} else {
None
}
})
.count();

if comm.size() == 1 {
assert_eq!(nghosts, 0);
} else {
assert!(nghosts > 0);
}

let nglobal = all_keys
.iter()
.filter(|(_, &value)| matches!(value, KeyType::Global))
.count();

// Assert that all globals across all ranks have the same count.

let nglobals = gather_to_all(std::slice::from_ref(&nglobal), &comm);

assert_eq!(nglobals.iter().unique().count(), 1);

if comm.rank() == 0 {
println!("Distributed tree is complete and linear.");
}
}
62 changes: 62 additions & 0 deletions examples/mpi_cumsum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//! Test the computation of a global bounding box across MPI ranks.

use bempp_octree::tools::{gather_to_root, global_inclusive_cumsum};
use itertools::{izip, Itertools};
use mpi::traits::Communicator;
use rand::prelude::*;
use rand_chacha::ChaCha8Rng;

pub fn main() {
// Initialise MPI
let universe = mpi::initialize().unwrap();

// Get the world communicator
let comm = universe.world();

// Initialise a seeded Rng.
let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);

// Create `npoints` per rank.
let nelems = 10;

// Generate random numbers

let mut elems = Vec::<usize>::with_capacity(nelems);

for _ in 0..nelems {
elems.push(rng.gen_range(0..100));
}

// Compute the cumulative sum.

let global_cum_sum = global_inclusive_cumsum(&elems, &comm);

// Copy array to root and compare with inclusive scan there.

if let (Some(cum_sum_root), Some(original_array)) = (
gather_to_root(&global_cum_sum, &comm),
gather_to_root(&elems, &comm),
) {
// Scan on root

let expected_cum_sum = original_array
.iter()
.scan(0, |state, x| {
*state += *x;
Some(*state)
})
.collect_vec();

// Check that the first element is not modified (inclusive cumsum)
assert_eq!(
original_array.first().unwrap(),
cum_sum_root.first().unwrap()
);

for (actual, expected) in izip!(cum_sum_root.iter(), expected_cum_sum.iter()) {
assert_eq!(*actual, *expected);
}

println!("Cumulative sum computed.");
}
}
40 changes: 40 additions & 0 deletions examples/mpi_global_bounding_box.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//! Test the computation of a global bounding box across MPI ranks.

use bempp_octree::{
geometry::PhysicalBox,
octree::compute_global_bounding_box,
tools::{gather_to_root, generate_random_points},
};
use rand::prelude::*;
use rand_chacha::ChaCha8Rng;

pub fn main() {
// Initialise MPI
let universe = mpi::initialize().unwrap();

// Get the world communicator
let comm = universe.world();

// Initialise a seeded Rng.
let mut rng = ChaCha8Rng::seed_from_u64(2);

// Create `npoints` per rank.
let npoints = 10;

// Generate random points.

let points = generate_random_points(npoints, &mut rng, &comm);

// Compute the distributed bounding box.

let bounding_box = compute_global_bounding_box(&points, &comm);

// Copy all points to root and compare local bounding box there.

if let Some(points_root) = gather_to_root(&points, &comm) {
// Compute the bounding box on root.

let expected = PhysicalBox::from_points(&points_root);
assert_eq!(expected.coordinates(), bounding_box.coordinates());
}
}
30 changes: 9 additions & 21 deletions examples/parsort.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,25 @@
//! Testing the hyksort component.
use bempp_octree::parsort::{array_to_root, parsort};
use itertools::Itertools;
use bempp_octree::{
parsort::parsort,
tools::{generate_random_keys, is_sorted_array},
};
use mpi::traits::Communicator;
use rand::prelude::*;

pub fn main() {
let universe = mpi::initialize().unwrap();
let world = universe.world();
let rank = world.rank() as u64;
let n_per_rank = 1000;

let mut rng = rand::rngs::StdRng::seed_from_u64(0);

let mut arr = Vec::<u64>::new();
let keys = generate_random_keys(n_per_rank, &mut rng);

for _ in 0..n_per_rank {
arr.push(rng.gen());
}

// let splitters = get_splitters(&arr, &world, &mut rng);

// let bin_displs = get_bin_displacements(&arr, &splitters);

let arr = parsort(&arr, &world, &mut rng);
let arr = array_to_root(&arr, &world);
let arr = parsort(&keys, &world, &mut rng);

if rank == 0 {
let arr = arr.unwrap();
assert!(is_sorted_array(&arr, &world));

for (elem1, elem2) in arr.iter().tuple_windows() {
assert!(elem1 <= elem2);
}
println!("Sorted {} elements.", arr.len());
println!("Finished.");
if world.rank() == 0 {
println!("Array is sorted.");
}
}
38 changes: 29 additions & 9 deletions src/geometry.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,33 @@
//! Geometry information

use bytemuck;
use mpi::traits::Equivalence;

use crate::constants::DEEPEST_LEVEL;

/// Definition of a point.
#[derive(Clone, Copy, Equivalence)]
pub struct Point {
coords: [f64; 3],
global_id: usize,
}

impl Point {
/// Create a new point from coordinates and global id.
pub fn new(coords: [f64; 3], global_id: usize) -> Self {
Self { coords, global_id }
}

/// Return the coordintes of a point.
pub fn coords(&self) -> [f64; 3] {
self.coords
}

/// Return the global id of the point.
pub fn global_id(&self) -> usize {
self.global_id
}
}

/// A bounding box describes geometry in which an Octree lives.
pub struct PhysicalBox {
coords: [f64; 6],
Expand All @@ -18,11 +42,7 @@ impl PhysicalBox {
}

/// Give a slice of points. Compute an associated bounding box.
pub fn from_points(points: &[f64]) -> PhysicalBox {
assert_eq!(points.len() % 3, 0);

let points: &[[f64; 3]] = bytemuck::cast_slice(points);

pub fn from_points(points: &[Point]) -> PhysicalBox {
let mut xmin = f64::MAX;
let mut xmax = f64::MIN;

Expand All @@ -33,9 +53,9 @@ impl PhysicalBox {
let mut zmax = f64::MIN;

for point in points {
let x = point[0];
let y = point[1];
let z = point[2];
let x = point.coords()[0];
let y = point.coords()[1];
let z = point.coords()[2];

xmin = f64::min(xmin, x);
xmax = f64::max(xmax, x);
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ pub mod geometry;
pub mod morton;
pub mod octree;
pub mod parsort;
pub mod serial;
pub mod tools;
pub mod types;
Loading
Loading