-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #37 from ewanwm/feature_benchmarking
Feature benchmarking
- Loading branch information
Showing
5 changed files
with
271 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
name: Continuous Benchmarking | ||
|
||
on: | ||
push: | ||
branches: [ "main" ] | ||
|
||
pull_request: | ||
branches: [ "main" ] | ||
types: [opened, reopened, edited, synchronize] | ||
|
||
workflow_dispatch: | ||
|
||
env: | ||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) | ||
BUILD_TYPE: Release | ||
|
||
jobs: | ||
benchmark_pr_branch: | ||
name: Continuous Benchmarking PRs with Bencher | ||
# DO NOT REMOVE: For handling Fork PRs see Pull Requests from Forks | ||
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository | ||
permissions: | ||
pull-requests: write | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: bencherdev/bencher@main | ||
|
||
- name: Set up GCC | ||
uses: egor-tensin/setup-gcc@v1 | ||
with: | ||
version: 11 | ||
platform: x64 | ||
|
||
- name: Set Flags | ||
run: export USE_CUDA=0 | ||
|
||
- name: Install Protobuf | ||
run: sudo apt install protobuf-compiler | ||
|
||
- name: Install Python dependencies | ||
uses: py-actions/py-dependency-install@v4 | ||
with: | ||
path: "PyTorch_requirements.txt" | ||
|
||
- name: Make Build Directory | ||
run: mkdir build | ||
|
||
- name: Configure CMake | ||
working-directory: ${{github.workspace}}/build | ||
# Configure CMake with benchmarking option on | ||
run: | | ||
cmake -DNT_USE_PCH=ON -DNT_ENABLE_BENCHMARKING=ON -DCMAKE_PREFIX_PATH=`python3 -c 'import torch;print(torch.utils.cmake_prefix_path)'` -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} .. | ||
echo :::: Build directory post-CMake: | ||
ls | ||
echo | ||
echo :::: _deps directory: | ||
ls _deps | ||
echo | ||
echo :::: benchmark link file: | ||
cat benchmarks/CMakeFiles/benchmarks.dir/link.txt | ||
- name: Build | ||
working-directory: ${{github.workspace}}/build | ||
# Build your program with the given configuration | ||
run: make --trace #cmake --build ${{github.workspace}}/build | ||
|
||
- name: Track PR Benchmarks with Bencher | ||
working-directory: ${{github.workspace}}/build | ||
run: | | ||
ls | ||
bencher run \ | ||
--project nutens \ | ||
--token '${{ secrets.BENCHER_API_TOKEN }}' \ | ||
--branch '${{ github.head_ref }}' \ | ||
--branch-start-point '${{ github.base_ref }}' \ | ||
--branch-start-point-hash '${{ github.event.pull_request.base.sha }}' \ | ||
--testbed ubuntu-latest \ | ||
--adapter cpp_google \ | ||
--err \ | ||
--github-actions '${{ secrets.GITHUB_TOKEN }}' \ | ||
"./benchmarks/benchmarks --benchmark_format=json --benchmark_repetitions=16 --benchmark_min_warmup_time=60" \ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,8 +3,8 @@ set(CMAKE_CXX_STANDARD 17) | |
|
||
project(nuTens) | ||
|
||
# Need to add some special compile flags to check the code test coverage | ||
OPTION(NT_TEST_COVERAGE "produce code coverage reports when running tests" OFF) | ||
|
||
IF(NT_TEST_COVERAGE) | ||
message("Adding flags to check test coverage") | ||
add_compile_options("--coverage") | ||
|
@@ -15,11 +15,28 @@ ENDIF() | |
|
||
enable_testing() | ||
|
||
# add dependencies | ||
########################## | ||
#### add dependencies #### | ||
########################## | ||
|
||
include(cmake/CPM.cmake) | ||
|
||
CPMAddPackage("gh:gabime/[email protected]") | ||
|
||
# If user wants to enable benchmarking we need to set up google benchmark dependency | ||
OPTION(NT_ENABLE_BENCHMARKING "enable benchmarking using google benchmark" OFF) | ||
IF(NT_ENABLE_BENCHMARKING) | ||
message("Enabling benchmarking") | ||
CPMAddPackage( | ||
GITHUB_REPOSITORY "google/benchmark" | ||
VERSION 1.8.5 | ||
OPTIONS "BENCHMARK_DOWNLOAD_DEPENDENCIES ON" | ||
) | ||
ELSE() | ||
message("Won't benchmark") | ||
ENDIF() | ||
|
||
|
||
## check build times | ||
## have this optional as it's not supported on all CMake platforms | ||
OPTION(NT_BUILD_TIMING "output time to build each target" OFF) | ||
|
@@ -32,10 +49,19 @@ find_package(Protobuf REQUIRED) | |
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}") | ||
|
||
|
||
###################################### | ||
#### Go configure the actual code #### | ||
###################################### | ||
|
||
add_subdirectory(nuTens) | ||
add_subdirectory(tests) | ||
|
||
IF(NT_ENABLE_BENCHMARKING) | ||
add_subdirectory(benchmarks) | ||
ENDIF() | ||
|
||
|
||
# Print out a handy message to more easily see the config options | ||
message( STATUS "The following variables have been used to configure the build: " ) | ||
get_cmake_property(_variableNames VARIABLES) | ||
list (SORT _variableNames) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
|
||
add_executable(benchmarks benchmarks.cpp) | ||
target_link_libraries(benchmarks benchmark::benchmark benchmark::benchmark_main tensor propagator ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
|
||
#include <benchmark/benchmark.h> | ||
#include <nuTens/propagator/const-density-solver.hpp> | ||
#include <nuTens/propagator/propagator.hpp> | ||
#include <nuTens/tensors/tensor.hpp> | ||
|
||
Tensor buildPMNS(const Tensor &theta12, const Tensor &theta13, const Tensor &theta23, const Tensor &deltaCP) | ||
{ | ||
// set up the three matrices to build the PMNS matrix | ||
Tensor M1; | ||
Tensor M2; | ||
Tensor M3; | ||
M1.zeros({1, 3, 3}, NTdtypes::kComplexFloat).requiresGrad(false); | ||
M2.zeros({1, 3, 3}, NTdtypes::kComplexFloat).requiresGrad(false); | ||
M3.zeros({1, 3, 3}, NTdtypes::kComplexFloat).requiresGrad(false); | ||
|
||
M1.setValue({0, 0, 0}, 1.0); | ||
M1.setValue({0, 1, 1}, Tensor::cos(theta23)); | ||
M1.setValue({0, 1, 2}, Tensor::sin(theta23)); | ||
M1.setValue({0, 2, 1}, -Tensor::sin(theta23)); | ||
M1.setValue({0, 2, 2}, Tensor::cos(theta23)); | ||
M1.requiresGrad(true); | ||
|
||
M2.setValue({0, 1, 1}, 1.0); | ||
M2.setValue({0, 0, 0}, Tensor::cos(theta13)); | ||
M2.setValue({0, 0, 2}, Tensor::mul(Tensor::sin(theta13), Tensor::exp(Tensor::scale(deltaCP, -1.0J)))); | ||
M2.setValue({0, 2, 0}, -Tensor::mul(Tensor::sin(theta13), Tensor::exp(Tensor::scale(deltaCP, 1.0J)))); | ||
M2.setValue({0, 2, 2}, Tensor::cos(theta13)); | ||
M2.requiresGrad(true); | ||
|
||
M3.setValue({0, 2, 2}, 1.0); | ||
M3.setValue({0, 0, 0}, Tensor::cos(theta12)); | ||
M3.setValue({0, 0, 1}, Tensor::sin(theta12)); | ||
M3.setValue({0, 1, 0}, -Tensor::sin(theta12)); | ||
M3.setValue({0, 1, 1}, Tensor::cos(theta12)); | ||
M3.requiresGrad(true); | ||
|
||
// Build PMNS | ||
Tensor PMNS = Tensor::matmul(M1, Tensor::matmul(M2, M3)); | ||
PMNS.requiresGrad(true); | ||
|
||
return PMNS; | ||
} | ||
|
||
static void batchedOscProbs(const Propagator &prop, Tensor &energies, int batchSize, int nBatches) | ||
{ | ||
for (int _ = 0; _ < nBatches; _++) | ||
{ | ||
// set random energy values | ||
for (int i = 0; i < batchSize; i++) | ||
{ | ||
// set to random energy between 0 and 10000.0 MeV | ||
energies.setValue({i, 0}, ((float)std::rand() / (float)RAND_MAX) * 10000.0); | ||
} | ||
|
||
// calculate the osc probabilities | ||
// static_cast<void> to discard the return value that we're not supposed to discard :) | ||
static_cast<void>(prop.calculateProbs(energies).sum()); | ||
} | ||
} | ||
|
||
static void BM_vacuumOscillations(benchmark::State &state) | ||
{ | ||
|
||
// set up the inputs | ||
Tensor energies; | ||
energies.zeros({state.range(0), 1}, NTdtypes::kFloat).requiresGrad(false); | ||
|
||
Tensor masses; | ||
masses.ones({1, 3}, NTdtypes::kFloat).requiresGrad(false); | ||
masses.setValue({0, 0}, 0.1); | ||
masses.setValue({0, 1}, 0.2); | ||
masses.setValue({0, 2}, 0.3); | ||
|
||
Tensor theta23; | ||
Tensor theta13; | ||
Tensor theta12; | ||
Tensor deltaCP; | ||
theta23.ones({1}, NTdtypes::kComplexFloat).requiresGrad(false).setValue({0}, 0.23); | ||
theta13.ones({1}, NTdtypes::kComplexFloat).requiresGrad(false).setValue({0}, 0.13); | ||
theta12.ones({1}, NTdtypes::kComplexFloat).requiresGrad(false).setValue({0}, 0.12); | ||
deltaCP.ones({1}, NTdtypes::kComplexFloat).requiresGrad(false).setValue({0}, 0.5); | ||
|
||
Tensor PMNS = buildPMNS(theta12, theta13, theta23, deltaCP); | ||
|
||
// set up the propagator | ||
Propagator vacuumProp(3, 100.0); | ||
vacuumProp.setPMNS(PMNS); | ||
vacuumProp.setMasses(masses); | ||
|
||
// seed the random number generator for the energies | ||
std::srand(123); | ||
|
||
for (auto _ : state) | ||
{ | ||
// This code gets timed | ||
batchedOscProbs(vacuumProp, energies, state.range(0), state.range(1)); | ||
} | ||
} | ||
|
||
static void BM_constMatterOscillations(benchmark::State &state) | ||
{ | ||
|
||
// set up the inputs | ||
Tensor energies; | ||
energies.zeros({state.range(0), 1}, NTdtypes::kFloat).requiresGrad(false); | ||
|
||
Tensor masses; | ||
masses.ones({1, 3}, NTdtypes::kFloat).requiresGrad(false); | ||
masses.setValue({0, 0}, 0.1); | ||
masses.setValue({0, 1}, 0.2); | ||
masses.setValue({0, 2}, 0.3); | ||
|
||
Tensor theta23; | ||
Tensor theta13; | ||
Tensor theta12; | ||
Tensor deltaCP; | ||
theta23.ones({1}, NTdtypes::kComplexFloat).requiresGrad(false).setValue({0}, 0.23); | ||
theta13.ones({1}, NTdtypes::kComplexFloat).requiresGrad(false).setValue({0}, 0.13); | ||
theta12.ones({1}, NTdtypes::kComplexFloat).requiresGrad(false).setValue({0}, 0.12); | ||
deltaCP.ones({1}, NTdtypes::kComplexFloat).requiresGrad(false).setValue({0}, 0.5); | ||
|
||
Tensor PMNS = buildPMNS(theta12, theta13, theta23, deltaCP); | ||
|
||
// set up the propagator | ||
Propagator matterProp(3, 100.0); | ||
std::unique_ptr<BaseMatterSolver> matterSolver = std::make_unique<ConstDensityMatterSolver>(3, 2.6); | ||
matterProp.setPMNS(PMNS); | ||
matterProp.setMasses(masses); | ||
matterProp.setMatterSolver(matterSolver); | ||
|
||
// seed the random number generator for the energies | ||
std::srand(123); | ||
|
||
for (auto _ : state) | ||
{ | ||
// This code gets timed | ||
batchedOscProbs(matterProp, energies, state.range(0), state.range(1)); | ||
} | ||
} | ||
|
||
// Register the function as a benchmark | ||
BENCHMARK(BM_vacuumOscillations)->Name("Vacuul Oscillations")->Args({1 << 10, 1 << 10}); | ||
|
||
// Register the function as a benchmark | ||
BENCHMARK(BM_constMatterOscillations)->Name("Const Density Oscillations")->Args({1 << 10, 1 << 10}); | ||
|
||
// Run the benchmark | ||
BENCHMARK_MAIN(); |