Baseline Flop Count Update, New Float Baseline See merge request course-asl-fastcode26/team70!28
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:
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:
g++ --version
clang++ --version
The visualization script requires Python and the following packages:
python3 -m pip install numpy pandas matplotlib
To generate MP4 videos, ffmpeg must also be installed.
On Ubuntu/Debian:
sudo apt update
sudo apt install make g++ clang python3 python3-pip ffmpeg libgtest-dev
python3 -m pip install numpy pandas matplotlib
On macOS:
xcode-select --install
brew install ffmpeg googletest
python3 -m pip install numpy pandas matplotlib
Makefile commands
The main commands are:
make run
Runs the simulation and writes pedestrian states to a CSV file.
make video
Runs the simulation and generates a visualization video.
make run-bench
Compiles and runs benchmark measurements.
All build commands accept a VARIANT parameter to select an optimization variant:
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.).
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:
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:
make bench-suite BENCH_SIZES="100 500 1000" BENCH_ITER=500
make test
Compiles and runs all unit tests.
make verify
Runs the simulation with the reference parameters and compares the output to reference/baseline_n60_i4000.csv using verify.py. Useful to check that a variant gives the same result as the baseline:
make verify VARIANT=v1_cutoff
make asm
Generates assembly files.
make sizes
Compiles the helper executable used to inspect data-structure sizes.
make clean
Deletes generated build files.
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:
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:
make run N_P=100 N_ITER=5000 CSV=my_positions.csv
Generate a video with custom output names:
make video N_P=100 N_ITER=5000 CSV=my_positions.csv MP4=my_simulation.mp4
Run benchmark measurements with custom parameters:
make run-bench N_P=100 N_ITER=5000
Use non-reproducible random initialization:
make run RANDOM_SEED=1
or:
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:
make main
This produces the executable:
main_baseline (or main_<variant>)
The Makefile uses the following compiler flags:
-O3 -march=native -std=c++23 -Wall -Wextra -flto
where:
-O3enables high-level optimization.-march=nativeoptimizes for the current machine.-std=c++23uses the C++23 standard.-Wall -Wextraenables useful compiler warnings.-fltoenables link-time optimization across.cppfiles, allowing cross-file optimizations such as function inlining.
Running the simulation
The recommended way to run the simulation is:
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:
./main_baseline <number_of_pedestrians> <number_of_iterations> [csv_output_path]
./main_<variant> <number_of_pedestrians> <number_of_iterations> [csv_output_path]
Example:
./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:
time,id,x,y,p.e.x,p.e.y,color
where:
timeis the simulation time step.idis the pedestrian index.x,yare the pedestrian position coordinates.p.e.x,p.e.yare the components of the desired direction.colorindicates the pedestrian group / walking direction.
Visualization
To run the simulation and directly generate a video:
make video
This produces an MP4 file, by default:
simulation.mp4
To visualize an existing CSV file manually:
python3 visualization.py <csv_file> <mp4_file>
Example:
python3 visualization.py positions.csv simulation.mp4
The generated video shows the pedestrian dynamics produced by the social force simulation.
Benchmarking
Run:
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:
RANDOM_SEED=0
which is the default.
Example:
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:
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:
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
- Copy the baseline file:
cp variant_baseline.cpp variant_v1_cutoff.cpp
-
Edit the new file with your optimization.
-
Build and test:
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 check that a variant produces the same simulation output, run:
make verify VARIANT=v1_cutoff
If the variant changes numerical results (e.g., distance cutoff skipping negligible forces), use a tolerance-based comparison (use the python script with a third argument (tolerance)) instead of exact diff and justify the deviation.
Tests
Run all unit tests with:
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:
make asm
This generates assembly output for the main source files, such as:
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:
make sizes
This produces:
sizes
Run it with:
./sizes
Cleaning generated files
Remove generated build files:
make clean
This deletes files such as:
main_*
sizes
run_tests
*.o
*.s
Remove build files and generated CSV/MP4 outputs:
make clean-all
This deletes:
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:
SEED=42
This makes simulation runs reproducible.
To use non-reproducible initialization, run:
make run RANDOM_SEED=1
or:
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:
make run
Generate a video:
make video
Run tests:
make test
Run benchmark measurements:
make run-bench
Clean generated build files:
make clean
Clean everything generated, including CSV and MP4 outputs:
make clean-all