Commit f445e5a9 authored by David Frank's avatar David Frank Committed by Tobias Lasser
Browse files

Add benchmark folder to clang-format check; Add target build-examples; Add...

Add benchmark folder to clang-format check; Add target build-examples; Add targets for building benchmarks and examples to CI pipeline
parent e9e16bf0
Pipeline #316442 passed with stages
in 29 minutes and 50 seconds
......@@ -64,15 +64,19 @@ variables:
script: &buildjob_clang
- mkdir -p build
- cd build
- cmake .. -GNinja -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="-lc++abi"
- cmake .. -GNinja -DELSA_BENCHMARKS=ON -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="-lc++abi"
- ninja
- ninja build-benchmarks
- ninja build-examples
.buildjob_script_normal:
script: &buildjob_normal
- mkdir -p build
- cd build
- cmake .. -GNinja
- cmake .. -GNinja -DELSA_BENCHMARKS=ON
- ninja
- ninja build-benchmarks
- ninja build-examples
.job_template: &test_job_artifact
<<: *run_always
......@@ -154,8 +158,10 @@ build-gpu-only:
script:
- mkdir -p build
- cd build
- cmake .. -GNinja -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="-lc++abi" -DELSA_CUDA_VECTOR=ON
- cmake .. -GNinja -DELSA_BENCHMARKS=ON -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="-lc++abi" -DELSA_CUDA_VECTOR=ON
- ninja
- ninja build-benchmarks
- ninja build-examples
tags:
- linux
- elsa
......
......@@ -132,7 +132,6 @@ if(NOT ELSA_MASTER_PROJECT)
endif(NOT ELSA_MASTER_PROJECT)
if(ELSA_TESTING OR ELSA_BENCHMARKS)
enable_testing()
add_subdirectory(thirdparty/Catch2)
......@@ -142,8 +141,11 @@ if(ELSA_TESTING OR ELSA_BENCHMARKS)
if(ELSA_TESTING)
message(STATUS "elsa testing is enabled")
# Run ctest to run all unit tests
# All tests are includes ass dependencies to this target, such that they get build
# schedule randomly that we don't start depending on some test order
add_custom_target(tests
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure --schedule-random
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
USES_TERMINAL
COMMENT "Build and run all the tests.")
......@@ -159,12 +161,6 @@ if(ELSA_TESTING OR ELSA_BENCHMARKS)
message(STATUS "elsa test coverage is disabled")
endif(ELSA_COVERAGE)
endif(ELSA_TESTING)
if (ELSA_BENCHMARKS)
message(STATUS "elsa benchmarks are enabled")
add_subdirectory(benchmarks)
endif(ELSA_BENCHMARKS)
else(ELSA_TESTING OR ELSA_BENCHMARKS)
message(STATUS " elsa testing is disabled")
endif(ELSA_TESTING OR ELSA_BENCHMARKS)
......@@ -193,6 +189,12 @@ if(ELSA_BUILD_EXAMPLES)
# the examples
add_subdirectory(examples EXCLUDE_FROM_ALL)
endif(ELSA_BUILD_EXAMPLES)
# Add benchmarks after elsa code, such that CUDA is detected correctly and we just add it in the benchmarks
if (ELSA_BENCHMARKS)
message(STATUS "elsa benchmarks are enabled")
add_subdirectory(benchmarks)
endif(ELSA_BENCHMARKS)
# ------------ setup installation ------
......
......@@ -4,6 +4,8 @@ cmake_minimum_required(VERSION 3.9)
include(CTest)
include(Catch)
add_custom_target(build-benchmarks)
macro(ELSA_BENCHMARK NAME)
# Add source to all sources, so we can create a common target to build and run the benchmarks
SET(BENCHMARK_SOURCES ${BENCHMARK_SOURCES} bench_${NAME}.cpp)
......@@ -12,18 +14,29 @@ macro(ELSA_BENCHMARK NAME)
add_executable(bench_${NAME} EXCLUDE_FROM_ALL bench_${NAME}.cpp bench_main.cpp)
# add catch and the corresponding elsa library
target_link_libraries(bench_${NAME} PRIVATE Catch2::Catch2 elsa::all)
if (CMAKE_CUDA_COMPILER)
enable_language(CUDA)
find_library(CUDART_LIBRARY cudart ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
target_include_directories(bench_${NAME}
PUBLIC ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
endif()
# enable C++17
target_compile_features(bench_${NAME} PUBLIC cxx_std_17)
# include helpers
target_include_directories(bench_${NAME} PRIVATE ${CMAKE_SOURCE_DIR}/elsa/test_routines/)
# discover test for CMake and CTest
catch_discover_tests(bench_${NAME} TEST_SPEC "" )
# Add benchmark to build-benchmarks
add_dependencies(build-benchmarks bench_${NAME})
endmacro(ELSA_BENCHMARK)
ELSA_BENCHMARK(RayGenerationBench)
ELSA_BENCHMARK(Projectors)
ELSA_BENCHMARK(Intersection)
ELSA_BENCHMARK(DataContainerConstruction)
ELSA_BENCHMARK(ExpressionTemplates)
# Add a single executable for all benchmarks, as CTest removes a lot of the output
add_executable(bench_all EXCLUDE_FROM_ALL bench_main.cpp ${BENCHMARK_SOURCES})
# add catch and the corresponding elsa library
......@@ -34,9 +47,9 @@ target_compile_features(bench_all PUBLIC cxx_std_17)
target_include_directories(bench_all PRIVATE ${CMAKE_SOURCE_DIR}/elsa/test_routines/)
# Add the custom target to run all the benchmarks
add_custom_target(benchmarks
add_custom_target(run-benchmarks
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/bench_all
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
USES_TERMINAL
COMMENT "Run benchmarks")
add_dependencies(benchmarks bench_all)
add_dependencies(run-benchmarks bench_all)
......@@ -35,11 +35,12 @@ void runProjector2D(index_t coeffsPerDim)
// generate circular trajectory
index_t noAngles{180}, arc{360};
auto [geometry, sinoDescriptor] = CircleTrajectoryGenerator::createTrajectory(
auto sinoDescriptor = CircleTrajectoryGenerator::createTrajectory(
noAngles, phantom.getDataDescriptor(), arc, 20, 20);
// setup operator for 2d X-ray transform
Projector projector(phantom.getDataDescriptor(), *sinoDescriptor, geometry);
Projector projector(dynamic_cast<const VolumeDescriptor&>(phantom.getDataDescriptor()),
*sinoDescriptor);
DataContainer_t sinogram(*sinoDescriptor);
BENCHMARK("Forward projection")
......@@ -65,11 +66,12 @@ void runProjector3D(index_t coeffsPerDim)
// generate circular trajectory
index_t noAngles{180}, arc{360};
auto [geometry, sinoDescriptor] = CircleTrajectoryGenerator::createTrajectory(
auto sinoDescriptor = CircleTrajectoryGenerator::createTrajectory(
noAngles, phantom.getDataDescriptor(), arc, 20, 20);
// setup operator for 2d X-ray transform
Projector projector(phantom.getDataDescriptor(), *sinoDescriptor, geometry);
Projector projector(dynamic_cast<const VolumeDescriptor&>(phantom.getDataDescriptor()),
*sinoDescriptor);
DataContainer_t sinogram(*sinoDescriptor);
BENCHMARK("Forward projection")
......
......@@ -10,6 +10,7 @@
#include <catch2/catch.hpp>
#include "VolumeDescriptor.h"
#include "PlanarDetectorDescriptor.h"
#include "Geometry.h"
#include <string>
#include <cstdlib>
......@@ -17,30 +18,28 @@
using namespace elsa;
using namespace elsa::geometry;
static const index_t dimension = 2;
void iterate2D(const Geometry& geo)
void iterate2D(const DetectorDescriptor& descriptor)
{
for (real_t detPixel : std::initializer_list<real_t>{0.5, 2.5, 4.5}) {
RealVector_t pixel(1);
pixel << detPixel;
for (auto detPixel : {0, 2, 4}) {
IndexVector_t pixel(2);
pixel << detPixel, 0; // 2nd dim is 0, as we access the 0th geometry pose
BENCHMARK("Ray for detector at pixel " + std::to_string(detPixel))
{
return geo.computeRayTo(pixel);
return descriptor.computeRayFromDetectorCoord(pixel);
};
}
}
void iterate3D(const Geometry& geo)
void iterate3D(const DetectorDescriptor& descriptor)
{
for (real_t detPixel1 : std::initializer_list<real_t>{0.5, 2.5, 4.5}) {
for (real_t detPixel2 : std::initializer_list<real_t>{0.5, 2.5, 4.5}) {
RealVector_t pixel(2);
pixel << detPixel1, detPixel2;
for (auto detPixel1 : {0, 2, 4}) {
for (auto detPixel2 : {0, 2, 4}) {
IndexVector_t pixel(3);
pixel << detPixel1, detPixel2, 0; // same as for 2d, last dim is for geometry access
BENCHMARK("Ray for detector at pixel " + std::to_string(detPixel1) + "/"
+ std::to_string(detPixel2))
{
return geo.computeRayTo(pixel);
return descriptor.computeRayFromDetectorCoord(pixel);
};
}
}
......@@ -64,27 +63,30 @@ TEST_CASE("Ray generation for 2D")
{
Geometry g(SourceToCenterOfRotation{s2c}, CenterOfRotationToDetector{c2d}, Degree{0},
std::move(volData), std::move(sinoData));
PlanarDetectorDescriptor descriptor(detCoeff, {g});
// test outer + central pixels
iterate2D(g);
iterate2D(descriptor);
}
GIVEN("Geometry with offset but no rotation")
{
Geometry g(SourceToCenterOfRotation{s2c}, CenterOfRotationToDetector{c2d}, Degree{0},
std::move(volData), std::move(sinoData), PrincipalPointOffset{2});
PlanarDetectorDescriptor descriptor(detCoeff, {g});
// test outer + central pixels
iterate2D(g);
iterate2D(descriptor);
}
GIVEN("Geometry at 90°, but no offset")
{
Geometry g(SourceToCenterOfRotation{s2c}, CenterOfRotationToDetector{c2d}, Degree{90},
std::move(volData), std::move(sinoData));
PlanarDetectorDescriptor descriptor(detCoeff, {g});
// test outer + central pixels
iterate2D(g);
iterate2D(descriptor);
}
GIVEN("Geometry at 45° with offset")
......@@ -92,9 +94,10 @@ TEST_CASE("Ray generation for 2D")
Geometry g(SourceToCenterOfRotation{s2c}, CenterOfRotationToDetector{c2d}, Degree{45},
std::move(volData), std::move(sinoData), PrincipalPointOffset{0},
RotationOffset2D{-1, 2});
PlanarDetectorDescriptor descriptor(detCoeff, {g});
// test outer + central pixels
iterate2D(g);
iterate2D(descriptor);
}
}
......@@ -118,9 +121,10 @@ TEST_CASE("Ray generation for 3D")
{
Geometry g(SourceToCenterOfRotation{s2c}, CenterOfRotationToDetector{c2d},
std::move(volData), std::move(sinoData), RotationAngles3D{Gamma(0)});
PlanarDetectorDescriptor descriptor(detCoeff, {g});
// test outer + central pixels
iterate3D(g);
iterate3D(descriptor);
}
GIVEN("Geometry with offset but no rotation")
......@@ -128,18 +132,20 @@ TEST_CASE("Ray generation for 3D")
Geometry g(SourceToCenterOfRotation{s2c}, CenterOfRotationToDetector{c2d},
std::move(volData), std::move(sinoData), RotationAngles3D{Gamma{0}},
PrincipalPointOffset2D{0, 0}, RotationOffset3D{-1, 3, 0});
PlanarDetectorDescriptor descriptor(detCoeff, {g});
// test outer + central pixels
iterate3D(g);
iterate3D(descriptor);
}
GIVEN("Geometry at 90°, but no offset")
{
Geometry g(SourceToCenterOfRotation{s2c}, CenterOfRotationToDetector{c2d},
std::move(volData), std::move(sinoData), RotationAngles3D{Gamma{pi_t / 2}});
PlanarDetectorDescriptor descriptor(detCoeff, {g});
// test outer + central pixels
iterate3D(g);
iterate3D(descriptor);
}
GIVEN("Geometry at 45°/22.5 with offset")
......@@ -151,8 +157,10 @@ TEST_CASE("Ray generation for 3D")
std::move(volData), std::move(sinoData),
RotationAngles3D{Gamma{angle1}, Beta{angle2}}, PrincipalPointOffset2D{0, 0},
RotationOffset3D{1, -2, -1});
PlanarDetectorDescriptor descriptor(detCoeff, {g});
// test outer + central pixels
iterate3D(g);
iterate3D(descriptor);
}
GIVEN("Geometry at 45/22.5/12.25 with offset")
......@@ -177,7 +185,9 @@ TEST_CASE("Ray generation for 3D")
Geometry g(s2c, c2d, ddVol, ddDet, R);
PlanarDetectorDescriptor descriptor(detCoeff, {g});
// test outer + central pixels
iterate3D(g);
iterate3D(descriptor);
}
}
......@@ -42,6 +42,9 @@ namespace elsa
auto dim = getNumberOfDimensions();
// Assume dimension of coord is equal to dimension of descriptor
assert(dim == coord.size());
// Cast to real_t and shift to center of pixel
auto detectorCoord = coord.head(dim - 1).template cast<real_t>().array() + 0.5;
......
......@@ -18,8 +18,3 @@ ELSA_TEST(ExpressionTemplates)
ELSA_TEST(Geometry)
ELSA_TEST(StrongTypes)
ELSA_TEST(PlanarDetectorDescriptor)
if(ELSA_BENCHMARKS)
ELSA_TEST(BenchmarkExpressionTemplates)
ELSA_TEST(BenchmarkDataContainerConstruction)
endif()
cmake_minimum_required(VERSION 3.9)
# define a target for all examples
add_custom_target(examples)
add_custom_target(build-examples)
# build the 2d example program
add_executable(example2d example2d.cpp)
target_link_libraries(example2d elsa::all)
target_compile_features(example2d PUBLIC cxx_std_17)
add_dependencies(examples example2d)
add_dependencies(build-examples example2d)
if(ELSA_BUILD_CUDA_PROJECTORS)
include(CheckLanguage)
check_language(CUDA)
if(CMAKE_CUDA_COMPILER)
enable_language(CUDA)
......@@ -19,12 +19,12 @@ if(ELSA_BUILD_CUDA_PROJECTORS)
add_executable(example3d example3d.cpp)
target_link_libraries(example3d elsa::all)
target_compile_features(example3d PUBLIC cxx_std_17)
add_dependencies(examples example3d)
add_dependencies(build-examples example3d)
# build the GPU projector speed test program
add_executable(speed_test speed_test.cpp)
target_link_libraries(speed_test elsa::all)
target_compile_features(speed_test PUBLIC cxx_std_17)
add_dependencies(examples speed_test)
add_dependencies(build-examples speed_test)
endif()
endif()
......@@ -23,6 +23,7 @@ echo
# perform clang-format on all cpp-files
find elsa/ -name '*.h' -or -name '*.hpp' -or -name '*.cpp' -or -name '*.cu' -or -name '*.cuh' | xargs clang-format-8 -i -style=file $1
find benchmarks/ -name '*.h' -or -name '*.hpp' -or -name '*.cpp' -or -name '*.cu' -or -name '*.cuh' | xargs clang-format-8 -i -style=file $1
find examples/ -name '*.h' -or -name '*.hpp' -or -name '*.cpp' -or -name '*.cu' -or -name '*.cuh' | xargs clang-format-8 -i -style=file $1
# check if something was modified
notcorrectlist=`git status --porcelain | grep '^ M' | cut -c4-`
......@@ -38,6 +39,7 @@ else
echo
echo "find elsa/ -name '*.h' -or -name '*.hpp' -or -name '*.cpp' -or -name '*.cu' -or -name '*.cuh' | xargs clang-format-8 -i -style=file $1"
echo "find benchmarks/ -name '*.h' -or -name '*.hpp' -or -name '*.cpp' -or -name '*.cu' -or -name '*.cuh' | xargs clang-format -i -style=file $1"
echo "find examples/ -name '*.h' -or -name '*.hpp' -or -name '*.cpp' -or -name '*.cu' -or -name '*.cuh' | xargs clang-format -i -style=file $1"
echo
echo "to solve the issue."
# cleanup changes in git
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment