Skip to content

Commit

Permalink
Merge pull request #141 from matsim-vsp/library-updates
Browse files Browse the repository at this point in the history
Library updates
  • Loading branch information
paulheinr authored Nov 28, 2024
2 parents a48dc40 + b68e29d commit 919fa2b
Show file tree
Hide file tree
Showing 19 changed files with 741 additions and 334 deletions.
739 changes: 495 additions & 244 deletions Cargo.lock

Large diffs are not rendered by default.

21 changes: 11 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,43 @@ edition = "2021"
[dependencies]
serde = { version = "1.0.137", features = ["derive"] }
serde_json = "1.0.93"
# sticking with quick-xml 0.23.0 because the serialization API changed: https://github.com/tafia/quick-xml/issues/499
# since the new API would need an adapter from std::fmt::Write to std::io::Write, we stick with the old API
quick-xml = { version = "0.23.0", features = ["serialize"] }
flate2 = { version = "1.0.24" }
rand = "0.8.5"
metis = "0.1.2"
flexi_logger = { version = "0.22", features = ["async"] }
metis = "0.2.2"
flexi_logger = { version = "0.29.6", features = ["async"] }
clap = { version = "4.0.29", features = ["derive"] }
# point to the github repo directly because we need a more recent version of bindgen. Otherwise the build fails
# due to some incompatibility starting with macOs 13.6
mpi = { git = "https://github.com/rsmpi/rsmpi", rev = "1622101c9fc3a78620e9649f7f895616289d3558" }
mpi = "0.8.0"
# dependencies for serialization with protobuf
prost = "0.11.5"
prost = "0.13.3"
# bytes replaces the signature of std::io::Cursor to implemnt Buf somehow...
bytes = "1.3.0"
serial_test = "2.0.0"
serial_test = "3.2.0"
wait-timeout = "0.2.0"
tracing = "0.1"
tracing-subscriber = { version = "0.3.0", features = ["json", "fmt", "std", "registry"] }
tracing-appender = "0.2"
itertools = "0.10.5"
itertools = "0.13.0"
assert_approx_eq = "1.1.0"
nohash-hasher = "0.2.0"
rand_distr = "0.4.3"
serde_path_to_error = "0.1.14"
geo = "0.26.0"
geo = "0.29.1"
ahash = "0.8.6"
keyed_priority_queue = "0.4.1"
xml = "0.8.10"
lz4_flex = "0.11.1"
typetag = "0.2.13"
typetag = "0.2.18"
serde_yaml = "0.9.27"

[build-dependencies]
# generates types based on .proto files
prost-build = "0.11"
# provides the protoc compiler - this makes the build slow but one doesn't need to
# install the protoc compiler as prerequisite.
# updating to 2.1.0 causes huge compile times (https://github.com/MaterializeInc/rust-protobuf-native/issues/24). Maybe we should switch to another crate.
protobuf-src = "1.1.0"

[profile.bench]
Expand Down
87 changes: 66 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The most recent release can be cited with the following reference
[![DOI](https://zenodo.org/badge/498376436.svg)](https://zenodo.org/doi/10.5281/zenodo.13928119)

The project is described in two conference papers, which were presented at ISPDC 24 in Chur, Switzerland, July 2024:

- [High-Performance Simulations for Urban Planning: Implementing Parallel Distributed Multi-Agent Systems in MATSim](https://doi.org/10.1109/ISPDC62236.2024.10705395)
- [Real-Time Routing in Traffic Simulations: A Distributed Event Processing Approach](https://doi.org/10.1109/ISPDC62236.2024.10705399)

Expand All @@ -16,8 +17,8 @@ The project is described in two conference papers, which were presented at ISPDC
Install Rust for your operating system as described [here](https://www.rust-lang.org/tools/install). For WSL this would
be

```
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

## Set Up Prerequisites
Expand All @@ -28,8 +29,8 @@ compiled with the project, but need to be present on the operating system.
### METIS

The project uses the [metis](https://crates.io/crates/metis) crate as a dependency which
is a wrapper for the [METIS C Library](https://github.com/KarypisLab/METIS). The C-Library is
expected to be present on the machine. Also, the `metis` crate requires `libclang` on the machine
is a wrapper for the [METIS C Library](https://github.com/KarypisLab/METIS). The C-Library is
expected to be present on the machine. Also, the `metis` crate requires `libclang` on the machine
this project is built on.

### MPI
Expand All @@ -51,61 +52,105 @@ The dependencies named above need to be installed before the project can be buit

Install dev versions of required packages because dev stuff is required during compilation

```
$ sudo apt -y install libclang-dev llvm-dev libmetis-dev libopenmpi-dev
```shell
sudo apt -y install libclang-dev llvm-dev libmetis-dev libopenmpi-dev
```

#### MacOs

The dependencies are available via [homebrew](https://brew.sh/) on macOS.

```
$ brew install metis open-mpi
```shell
brew install metis open-mpi
```

The project contains a `config.toml` which tries to set the `CPATH` and the `RUSTFLAGS` environment variable. In case
this doesn't work, they need to be set like the following:
```
$ export CPATH=$HOMEBREW_PREFIX/include
$ export RUSTFLAGS="-L$HOMEBREW_PREFIX/lib"

```shell
export CPATH=$HOMEBREW_PREFIX/include
export RUSTFLAGS="-L$HOMEBREW_PREFIX/lib"
```

Both variables are necessary to compile the METIS and MPI wrapper libraries.

#### Math Cluster

The math cluster has all dependencies installed. They need to be enabled via the module system:

```shell
module load metis-5.1 ompi/gcc/4.1.2
```
$ module load metis-5.1 ompi/gcc/4.1.2
```

#### HLRN

The HLRN cluster has all dependencies installed. They need to be enabled via the module system:
##### Setup conda

Unfortunately, there is no `libclang` dependency installed. You need to install it yourself via `conda`. If you use it
for the first time, load the conda module and initialize it, such that it is available in your shell whenever you login:

```shell
module load anaconda3/2023.09
conda init bash
```

Then create your own environment and install `libclang`:

```shell
conda create -n your_env_name
conda activate your_env_name
conda install libclang
```

##### Load dependencies

The HLRN cluster has **some** dependencies installed. They need to be enabled via the module system:

```shell
module load intel/2024.2 openmpi/gcc/5.0.3
```
$ module load gcc/9.3.0 llvm/9.0.0 openmpi/gcc.9/4.1.4 metis/5.1.0

So, before you run the project, you need to activate the environment:

```shell
conda activate your_env_name
```

The activation automatically updates the environment variables such that `libclang` files can be found by the compiler.

Source: https://nhr-zib.atlassian.net/wiki/spaces/PUB/pages/430343/Anaconda+conda+and+Mamba

## Run the project

The project is built using cargo.

```
$ cargo build --release
```shell
cargo build --release
```

Then a simulation can be started like the following:
```
$ mpirun -np 2 ./target/release/mpi_qsim --config-path /path/to/config.yml

```shell
mpirun -np 2 ./target/release/mpi_qsim --config-path /path/to/config.yml
```

It is also possible to execute a build before running by executing the following. This is way, one doesn't
forget to re-compile before running.
```
$ cargo mpirun --np 2 --release --bin mpi_qsim -- --config-path /path/to/config.yaml

```shell
cargo mpirun --np 2 --release --bin mpi_qsim -- --config-path /path/to/config.yaml
```

We also have a

### Test

Run `$ cargo test` to execute all tests. To have immediate output use `$ cargo test -- --nocapture`

## Create input files

You need to create protobuf files from the xml files. This can be done with the following command:

```shell
cargo run --bin convert_to_binary --release -- --network network.xml --population population.xml --vehicles vehicles.xml --output-dir output --run-id run
```
91 changes: 77 additions & 14 deletions assets/adhoc_routing/with_updates/network.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,86 @@
<!DOCTYPE network SYSTEM "http://www.matsim.org/files/dtd/network_v2.dtd">
<network>
<nodes>
<node id="node0" x="-100.0" y="0.0"/>
<node id="node1" x="0.0" y="0.0"/>
<node id="node2" x="100.0" y="0.0"/>
<node id="node3" x="1100.0" y="0.0"/>
<node id="node4" x="1200.0" y="0.0" />
<node id="node5" x="1300.0" y="0.0" />
<node id="node6" x="600.0" y="300.0" />
<node id="node0" x="-100.0" y="0.0">
<attributes>
<attribute name="partition" class="java.lang.Integer">1</attribute>
</attributes>
</node>
<node id="node1" x="0.0" y="0.0">
<attributes>
<attribute name="partition" class="java.lang.Integer">1</attribute>
</attributes>
</node>
<node id="node2" x="100.0" y="0.0">
<attributes>
<attribute name="partition" class="java.lang.Integer">1</attribute>
</attributes>
</node>
<node id="node3" x="1100.0" y="0.0">
<attributes>
<attribute name="partition" class="java.lang.Integer">0</attribute>
</attributes>
</node>
<node id="node4" x="1200.0" y="0.0">
<attributes>
<attribute name="partition" class="java.lang.Integer">0</attribute>
</attributes>
</node>
<node id="node5" x="1300.0" y="0.0">
<attributes>
<attribute name="partition" class="java.lang.Integer">0</attribute>
</attributes>
</node>
<node id="node6" x="600.0" y="300.0">
<attributes>
<attribute name="partition" class="java.lang.Integer">1</attribute>
</attributes>
</node>
</nodes>
<links capperiod="01:00:00" effectivecellsize="7.5" effectivelanewidth="3.75">
<link id="0" from="node0" to="node1" length="100" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1" modes="bike,car" />
<link id="1" from="node1" to="node2" length="100" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1" modes="bike,car" />
<link id="2" from="node2" to="node3" length="1000" freespeed="10" capacity="3.0" permlanes="1.0" oneway="1" modes="bike,car" />
<link id="3" from="node3" to="node4" length="100" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1" modes="bike,car" />
<link id="4" from="node4" to="node5" length="100" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1" modes="bike,car"/>
<link id="0" from="node0" to="node1" length="100" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1"
modes="bike,car">
<attributes>
<attribute name="partition" class="java.lang.Integer">1</attribute>
</attributes>
</link>
<link id="1" from="node1" to="node2" length="100" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1"
modes="bike,car">
<attributes>
<attribute name="partition" class="java.lang.Integer">1</attribute>
</attributes>
</link>
<link id="2" from="node2" to="node3" length="1000" freespeed="10" capacity="3.0" permlanes="1.0" oneway="1"
modes="bike,car">
<attributes>
<attribute name="partition" class="java.lang.Integer">0</attribute>
</attributes>
</link>
<link id="3" from="node3" to="node4" length="100" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1"
modes="bike,car">
<attributes>
<attribute name="partition" class="java.lang.Integer">0</attribute>
</attributes>
</link>
<link id="4" from="node4" to="node5" length="100" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1"
modes="bike,car">
<attributes>
<attribute name="partition" class="java.lang.Integer">0</attribute>
</attributes>
</link>

<link id="5" from="node2" to="node6" length="1000" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1" modes="bike,car"/>
<link id="6" from="node6" to="node3" length="1000" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1" modes="bike,car"/>
<link id="5" from="node2" to="node6" length="1000" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1"
modes="bike,car">
<attributes>
<attribute name="partition" class="java.lang.Integer">1</attribute>
</attributes>
</link>
<link id="6" from="node6" to="node3" length="1000" freespeed="10" capacity="100.0" permlanes="1.0" oneway="1"
modes="bike,car">
<attributes>
<attribute name="partition" class="java.lang.Integer">0</attribute>
</attributes>
</link>

</links>
</network>
27 changes: 27 additions & 0 deletions assets/rvr-1pct.config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
modules:
protofiles:
type: ProtoFiles
network: /Users/paulheinrich/Nextcloud/Shared/RustQSim/scenarios/rvr/input/rvr-1pct/rvr-1pct.network.binpb
population: /Users/paulheinrich/Nextcloud/Shared/RustQSim/scenarios/rvr/input/rvr-1pct/rvr-1pct.plans.binpb
vehicles: /Users/paulheinrich/Nextcloud/Shared/RustQSim/scenarios/rvr/input/rvr-1pct/rvr-1pct.vehicles.binpb
ids: /Users/paulheinrich/Nextcloud/Shared/RustQSim/scenarios/rvr/input/rvr-1pct/rvr-1pct.ids.binpb
partitioning:
type: Partitioning
num_parts: 0
method: !Metis
vertex_weight:
- PreComputed
output:
type: Output
output_dir: ./assets/rvr-1pct/size
profiling: !CSV
level: INFO
routing:
type: Routing
mode: UsePlans
simulation:
type: Simulation
start_time: 0
end_time: 129600
sample_size: 0.01
stuck_threshold: 30
3 changes: 0 additions & 3 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
# use nighly build because rust road router need experimental features.
[toolchain]
# due to https://github.com/intellij-rust/intellij-rust/issues/10427
#channel = "nightly-2023-05-01"
channel = "stable"
11 changes: 7 additions & 4 deletions src/simulation/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,16 @@ pub fn run_channel() {
pub fn run_mpi() {
let universe = mpi::initialize().unwrap();
let world = universe.world();
let size = world.size();
let rank = world.rank();

let comm = MpiSimCommunicator {
mpi_communicator: world,
};

let mut args = CommandLineArgs::parse();
// override the num part argument, with the number of processes mpi has started.
args.num_parts = Some(world.size() as u32);
args.num_parts = Some(size as u32);
let config = Config::from_file(&args);

let _guards = logging::init_logging(&config, &args.config_path, comm.rank());
Expand All @@ -77,9 +80,9 @@ pub fn run_mpi() {
);
execute_partition(comm, &args);

info!("#{} at barrier.", world.rank());
info!("#{} at barrier.", rank);
universe.world().barrier();
info!("Process #{} finishing.", world.rank());
info!("Process #{} finishing.", rank);
}

fn execute_partition<C: SimCommunicator + 'static>(comm: C, args: &CommandLineArgs) {
Expand Down Expand Up @@ -230,7 +233,7 @@ pub fn get_numbered_output_filename(output_dir: &Path, input_file: &Path, part:
insert_number_in_proto_filename(&out, part)
}

fn create_output_filename(output_dir: &Path, input_file: &Path) -> PathBuf {
pub fn create_output_filename(output_dir: &Path, input_file: &Path) -> PathBuf {
let filename = input_file.file_name().unwrap();
output_dir.join(filename)
}
Expand Down
Loading

0 comments on commit 919fa2b

Please sign in to comment.