526 lines
9.7 KiB
Markdown
526 lines
9.7 KiB
Markdown
# Advanced Systems Lab - Spring 2026
|
|
|
|
This is the GitLab repository of **Group 70**.
|
|
|
|
**Project topic:** Social Force Model for Pedestrian Dynamics
|
|
|
|
The goal of this project was to implement and optimize Helbing's social force model for pedestrian dynamics. The final report includes the implementation details, performance analysis, and results of the work.
|
|
|
|
This repository contains the C++ simulation code and Python visualization code used to generate and analyze the data.
|
|
|
|
---
|
|
|
|
## Requirements
|
|
|
|
The project uses a `Makefile` to simplify building, running, benchmarking, testing, and visualization.
|
|
|
|
Make sure `make` is installed:
|
|
|
|
```bash
|
|
make --version
|
|
```
|
|
|
|
You also need a C++ compiler. The Makefile automatically uses `g++` if available, otherwise it falls back to `clang++`.
|
|
|
|
Check your compiler with:
|
|
|
|
```bash
|
|
g++ --version
|
|
clang++ --version
|
|
```
|
|
|
|
The visualization script requires Python and the following packages:
|
|
|
|
```bash
|
|
python3 -m pip install numpy pandas matplotlib
|
|
```
|
|
|
|
To generate MP4 videos, `ffmpeg` must also be installed.
|
|
|
|
On Ubuntu/Debian:
|
|
|
|
```bash
|
|
sudo apt update
|
|
sudo apt install make g++ clang python3 python3-pip ffmpeg libgtest-dev
|
|
python3 -m pip install numpy pandas matplotlib
|
|
```
|
|
|
|
On macOS:
|
|
|
|
```bash
|
|
xcode-select --install
|
|
brew install ffmpeg googletest
|
|
python3 -m pip install numpy pandas matplotlib
|
|
```
|
|
|
|
---
|
|
|
|
## Makefile commands
|
|
|
|
The main commands are:
|
|
|
|
```bash
|
|
make run
|
|
```
|
|
|
|
Runs the simulation and writes pedestrian states to a CSV file.
|
|
|
|
```bash
|
|
make video
|
|
```
|
|
|
|
Runs the simulation and generates a visualization video.
|
|
|
|
```bash
|
|
make run-bench
|
|
```
|
|
|
|
Compiles and runs benchmark measurements.
|
|
|
|
All build commands accept a `VARIANT` parameter to select an optimization variant:
|
|
|
|
```bash
|
|
make run-bench VARIANT=v1_cutoff N_P=100 N_ITER=10000
|
|
```
|
|
|
|
The default is `VARIANT=baseline`. Each variant compiles its own binary (`main_baseline`, `main_v1_cutoff`, etc.).
|
|
|
|
```bash
|
|
make bench-suite
|
|
```
|
|
|
|
Compiles once and runs benchmarks across multiple pedestrian counts (default: 50, 100, 200, 500, 1000, 2000, 5000, 10000 with 1000 iterations each). Redirect output to save results:
|
|
|
|
```bash
|
|
make bench-suite > benchmarks/baseline.txt
|
|
make bench-suite VARIANT=v1_cutoff > benchmarks/v1_cutoff.txt
|
|
```
|
|
|
|
Both `BENCH_SIZES` and `BENCH_ITER` can be overridden:
|
|
|
|
```bash
|
|
make bench-suite BENCH_SIZES="100 500 1000" BENCH_ITER=500
|
|
```
|
|
|
|
```bash
|
|
make test
|
|
```
|
|
|
|
Compiles and runs all unit tests.
|
|
|
|
```bash
|
|
make asm
|
|
```
|
|
|
|
Generates assembly files.
|
|
|
|
```bash
|
|
make sizes
|
|
```
|
|
|
|
Compiles the helper executable used to inspect data-structure sizes.
|
|
|
|
```bash
|
|
make clean
|
|
```
|
|
|
|
Deletes generated build files.
|
|
|
|
```bash
|
|
make clean-all
|
|
```
|
|
|
|
Deletes generated build files and all `.csv` / `.mp4` outputs in the current directory.
|
|
|
|
**Warning:** `make clean-all` removes all CSV and MP4 files in the directory. Move any output files you want to keep before running it.
|
|
|
|
---
|
|
|
|
## Default parameters
|
|
|
|
The default simulation parameters are:
|
|
|
|
```text
|
|
N_P=60
|
|
N_ITER=4000
|
|
CSV=positions.csv
|
|
MP4=simulation.mp4
|
|
RANDOM_SEED=0
|
|
VARIANT=baseline
|
|
```
|
|
|
|
They can be overridden from the shell. Parameters can be provided selectively and in any order.
|
|
|
|
Run the simulation with custom parameters:
|
|
|
|
```bash
|
|
make run N_P=100 N_ITER=5000 CSV=my_positions.csv
|
|
```
|
|
|
|
Generate a video with custom output names:
|
|
|
|
```bash
|
|
make video N_P=100 N_ITER=5000 CSV=my_positions.csv MP4=my_simulation.mp4
|
|
```
|
|
|
|
Run benchmark measurements with custom parameters:
|
|
|
|
```bash
|
|
make run-bench N_P=100 N_ITER=5000
|
|
```
|
|
|
|
Use non-reproducible random initialization:
|
|
|
|
```bash
|
|
make run RANDOM_SEED=1
|
|
```
|
|
|
|
or:
|
|
|
|
```bash
|
|
make video RANDOM_SEED=1
|
|
```
|
|
|
|
By default, `RANDOM_SEED=0` uses a fixed seed for reproducible simulations and benchmarks.
|
|
|
|
---
|
|
|
|
## Building
|
|
|
|
To compile the main executable:
|
|
|
|
```bash
|
|
make main
|
|
```
|
|
|
|
This produces the executable:
|
|
|
|
```text
|
|
main_baseline (or main_<variant>)
|
|
```
|
|
|
|
The Makefile uses the following compiler flags:
|
|
|
|
```text
|
|
-O3 -march=native -std=c++23 -Wall -Wextra -flto
|
|
```
|
|
|
|
where:
|
|
|
|
- `-O3` enables high-level optimization.
|
|
- `-march=native` optimizes for the current machine.
|
|
- `-std=c++23` uses the C++23 standard.
|
|
- `-Wall -Wextra` enables useful compiler warnings.
|
|
- `-flto` enables link-time optimization across `.cpp` files, allowing cross-file optimizations such as function inlining.
|
|
|
|
---
|
|
|
|
## Running the simulation
|
|
|
|
The recommended way to run the simulation is:
|
|
|
|
```bash
|
|
make run
|
|
```
|
|
|
|
This compiles the code and runs the simulation with the default parameters. It produces a CSV file containing pedestrian states at each saved time step.
|
|
|
|
You can also run the executable manually after compiling:
|
|
|
|
```bash
|
|
./main_baseline <number_of_pedestrians> <number_of_iterations> [csv_output_path]
|
|
./main_<variant> <number_of_pedestrians> <number_of_iterations> [csv_output_path]
|
|
```
|
|
|
|
Example:
|
|
|
|
```bash
|
|
./main_baseline 60 4000 positions.csv
|
|
./main_<variant> 60 4000 positions.csv
|
|
|
|
```
|
|
|
|
The third argument is optional. If it is provided, simulation states are written to the given CSV file.
|
|
|
|
---
|
|
|
|
## CSV output
|
|
|
|
The CSV file contains the pedestrian states used for visualization.
|
|
|
|
The output columns are:
|
|
|
|
```text
|
|
time,id,x,y,p.e.x,p.e.y,color
|
|
```
|
|
|
|
where:
|
|
|
|
- `time` is the simulation time step.
|
|
- `id` is the pedestrian index.
|
|
- `x`, `y` are the pedestrian position coordinates.
|
|
- `p.e.x`, `p.e.y` are the components of the desired direction.
|
|
- `color` indicates the pedestrian group / walking direction.
|
|
|
|
---
|
|
|
|
## Visualization
|
|
|
|
To run the simulation and directly generate a video:
|
|
|
|
```bash
|
|
make video
|
|
```
|
|
|
|
This produces an MP4 file, by default:
|
|
|
|
```text
|
|
simulation.mp4
|
|
```
|
|
|
|
To visualize an existing CSV file manually:
|
|
|
|
```bash
|
|
python3 visualization.py <csv_file> <mp4_file>
|
|
```
|
|
|
|
Example:
|
|
|
|
```bash
|
|
python3 visualization.py positions.csv simulation.mp4
|
|
```
|
|
|
|
The generated video shows the pedestrian dynamics produced by the social force simulation.
|
|
|
|
---
|
|
|
|
## Benchmarking
|
|
|
|
Run:
|
|
|
|
```bash
|
|
make run-bench
|
|
```
|
|
|
|
This compiles the executable with benchmarking enabled and measures the simulation performance.
|
|
|
|
On ARM/AArch64 machines, the Makefile automatically prepends `sudo` for benchmark compilation and execution because access to PMU performance counters may require elevated privileges.
|
|
|
|
For reproducible benchmark results, keep:
|
|
|
|
```text
|
|
RANDOM_SEED=0
|
|
```
|
|
|
|
which is the default.
|
|
|
|
Example:
|
|
|
|
```bash
|
|
make run-bench N_P=100 N_ITER=5000
|
|
```
|
|
|
|
The benchmark output includes estimated work, operational intensity, measured cycles, and estimated performance in flops per cycle.
|
|
---
|
|
|
|
## Optimization Variants
|
|
|
|
The project supports multiple optimization variants through the `VARIANT` Makefile parameter. Each variant provides its own implementation of the force computations and simulation loop while sharing the same interface, benchmark harness, and test suite.
|
|
|
|
The default variant is `baseline`:
|
|
|
|
```bash
|
|
make run-bench # uses baseline
|
|
make run-bench VARIANT=baseline # equivalent
|
|
make run-bench VARIANT=v1_cutoff # uses a different variant
|
|
|
|
```
|
|
### File naming convention
|
|
Each variant consists of a single file in the project root:
|
|
|
|
```bash
|
|
variant_<name>.cpp # force computations and simulation loop
|
|
```
|
|
The file must implement the interfaces defined in `forces.hpp` and `social_force.hpp`. The baseline implementation is `variant_baseline.cpp`.
|
|
|
|
### Creating a new variant
|
|
1. Copy the baseline file:
|
|
```text
|
|
cp variant_baseline.cpp variant_v1_cutoff.cpp
|
|
```
|
|
2. Edit the new file with your optimization.
|
|
|
|
3. Build and test:
|
|
```bash
|
|
make test VARIANT=v1_cutoff
|
|
make run-bench VARIANT=v1_cutoff N_P=100 N_ITER=10000
|
|
```
|
|
### Verifying correctness
|
|
A reference CSV is stored in reference/baseline_n60_i4000.csv. To verify that a variant produces the same simulation output:
|
|
```bash
|
|
make run VARIANT=v1_cutoff N_P=60 N_ITER=4000 CSV=test_output.csv
|
|
diff reference/baseline_n60_i4000.csv test_output.csv
|
|
```
|
|
If the variant changes numerical results (e.g., distance cutoff skipping negligible forces), use a tolerance-based comparison instead of exact diff and justify the deviation.
|
|
|
|
|
|
---
|
|
## Tests
|
|
|
|
Run all unit tests with:
|
|
|
|
```bash
|
|
make test
|
|
```
|
|
|
|
The tests use GoogleTest, so `libgtest-dev` or an equivalent GoogleTest installation must be available.
|
|
|
|
The test target compiles and runs the unit tests for the simulation components.
|
|
|
|
---
|
|
|
|
## Assembly generation
|
|
|
|
To generate assembly files for the currently selected VARIANT:
|
|
|
|
```bash
|
|
make asm
|
|
```
|
|
|
|
This generates assembly output for the main source files, such as:
|
|
|
|
```text
|
|
main.s
|
|
forces.s
|
|
social_force_baseline.s
|
|
```
|
|
|
|
This can be useful for inspecting compiler optimizations and generated instructions.
|
|
|
|
---
|
|
|
|
## Structure-size helper
|
|
|
|
To compile the helper executable used to inspect data-structure sizes:
|
|
|
|
```bash
|
|
make sizes
|
|
```
|
|
|
|
This produces:
|
|
|
|
```text
|
|
sizes
|
|
```
|
|
|
|
Run it with:
|
|
|
|
```bash
|
|
./sizes
|
|
```
|
|
|
|
---
|
|
|
|
## Cleaning generated files
|
|
|
|
Remove generated build files:
|
|
|
|
```bash
|
|
make clean
|
|
```
|
|
|
|
This deletes files such as:
|
|
|
|
```text
|
|
main_*
|
|
sizes
|
|
run_tests
|
|
*.o
|
|
*.s
|
|
```
|
|
|
|
Remove build files and generated CSV/MP4 outputs:
|
|
|
|
```bash
|
|
make clean-all
|
|
```
|
|
|
|
This deletes:
|
|
|
|
```text
|
|
main_*
|
|
sizes
|
|
run_tests
|
|
*.o
|
|
*.s
|
|
*.csv
|
|
*.mp4
|
|
```
|
|
|
|
**Warning:** `make clean-all` deletes all `.csv` and `.mp4` files in the current directory. Move any files you want to keep before running it.
|
|
|
|
---
|
|
|
|
## Notes on reproducibility
|
|
|
|
By default, the simulation uses a fixed random seed:
|
|
|
|
```text
|
|
SEED=42
|
|
```
|
|
|
|
This makes simulation runs reproducible.
|
|
|
|
To use non-reproducible initialization, run:
|
|
|
|
```bash
|
|
make run RANDOM_SEED=1
|
|
```
|
|
|
|
or:
|
|
|
|
```bash
|
|
make video RANDOM_SEED=1
|
|
```
|
|
|
|
For benchmarking, reproducible initialization is recommended, so the default `RANDOM_SEED=0` should normally be kept.
|
|
|
|
---
|
|
|
|
## Example workflow
|
|
|
|
Compile and run the simulation:
|
|
|
|
```bash
|
|
make run
|
|
```
|
|
|
|
Generate a video:
|
|
|
|
```bash
|
|
make video
|
|
```
|
|
|
|
Run tests:
|
|
|
|
```bash
|
|
make test
|
|
```
|
|
|
|
Run benchmark measurements:
|
|
|
|
```bash
|
|
make run-bench
|
|
```
|
|
|
|
Clean generated build files:
|
|
|
|
```bash
|
|
make clean
|
|
```
|
|
|
|
Clean everything generated, including CSV and MP4 outputs:
|
|
|
|
```bash
|
|
make clean-all
|
|
``` |