From 628f57dcaf665aa92cc15cf1f100f80558363986 Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Mon, 9 Oct 2023 19:39:01 +0200 Subject: [PATCH 1/3] 01_02_infrastructure_resources: added example Cmake lib, exe, tests with Catch2 --- 01_02_infrastructure_resources/CMakeLists.txt | 4 +- .../code/cpp-example/.gitignore | 3 + .../code/cpp-example/CMakeLists.txt | 35 ++++ .../cpp-example/MathFunctions/CMakeLists.txt | 25 +++ .../MathFunctions/MathFunctions.cxx | 12 ++ .../cpp-example/MathFunctions/MathFunctions.h | 6 + .../MathFunctions/test_MathFunctions.cxx | 11 ++ .../code/cpp-example/README.md | 13 ++ .../code/cpp-example/TutorialConfig.h.in | 3 + .../cmake/ECMEnableSanitizers.cmake | 167 ++++++++++++++++++ .../code/cpp-example/tutorial.cxx | 26 +++ 11 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 01_02_infrastructure_resources/code/cpp-example/.gitignore create mode 100644 01_02_infrastructure_resources/code/cpp-example/CMakeLists.txt create mode 100644 01_02_infrastructure_resources/code/cpp-example/MathFunctions/CMakeLists.txt create mode 100644 01_02_infrastructure_resources/code/cpp-example/MathFunctions/MathFunctions.cxx create mode 100644 01_02_infrastructure_resources/code/cpp-example/MathFunctions/MathFunctions.h create mode 100644 01_02_infrastructure_resources/code/cpp-example/MathFunctions/test_MathFunctions.cxx create mode 100644 01_02_infrastructure_resources/code/cpp-example/README.md create mode 100644 01_02_infrastructure_resources/code/cpp-example/TutorialConfig.h.in create mode 100644 01_02_infrastructure_resources/code/cpp-example/cmake/ECMEnableSanitizers.cmake create mode 100644 01_02_infrastructure_resources/code/cpp-example/tutorial.cxx diff --git a/01_02_infrastructure_resources/CMakeLists.txt b/01_02_infrastructure_resources/CMakeLists.txt index 27692aa..7c92ad6 100644 --- a/01_02_infrastructure_resources/CMakeLists.txt +++ b/01_02_infrastructure_resources/CMakeLists.txt @@ -1,3 +1,5 @@ if (${CPP_COURSE_BUILD_SLIDES}) add_marp_slides(01_02_infrastructure_resources infrastructure_resources.md) -endif() \ No newline at end of file +endif() + +add_subdirectory(code/cpp-example) diff --git a/01_02_infrastructure_resources/code/cpp-example/.gitignore b/01_02_infrastructure_resources/code/cpp-example/.gitignore new file mode 100644 index 0000000..a66f477 --- /dev/null +++ b/01_02_infrastructure_resources/code/cpp-example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +/.cache +/build diff --git a/01_02_infrastructure_resources/code/cpp-example/CMakeLists.txt b/01_02_infrastructure_resources/code/cpp-example/CMakeLists.txt new file mode 100644 index 0000000..a92e8ae --- /dev/null +++ b/01_02_infrastructure_resources/code/cpp-example/CMakeLists.txt @@ -0,0 +1,35 @@ +# TODO 1: Update the minimum required version to 3.15 + +cmake_minimum_required(VERSION 3.10) + +# set the project name and version +project(Tutorial VERSION 1.0) + +# specify the C++ standard +add_library(tutorial_compiler_flags INTERFACE) +target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_17) + +set(gcc_like_cxx "$") +set(msvc_cxx "$") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$>" + "$<${msvc_cxx}:$>" +) + +# configure a header file to pass some of the CMake settings +# to the source code +configure_file(TutorialConfig.h.in TutorialConfig.h) + +# add the MathFunctions library +add_subdirectory(MathFunctions) + +# add the executable +add_executable(Tutorial tutorial.cxx) + +target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags) + +# add the binary tree to the search path for include files +# so that we will find TutorialConfig.h +target_include_directories(Tutorial PUBLIC + "${PROJECT_BINARY_DIR}" + ) diff --git a/01_02_infrastructure_resources/code/cpp-example/MathFunctions/CMakeLists.txt b/01_02_infrastructure_resources/code/cpp-example/MathFunctions/CMakeLists.txt new file mode 100644 index 0000000..48e2432 --- /dev/null +++ b/01_02_infrastructure_resources/code/cpp-example/MathFunctions/CMakeLists.txt @@ -0,0 +1,25 @@ +Include(FetchContent) + +FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v3.4.0 # or a later release +) + +FetchContent_MakeAvailable(Catch2) + +# create the MathFunctions library +add_library(MathFunctions MathFunctions.cxx) + +# state that anybody linking to us needs to include the current source dir +# to find MathFunctions.h, while we don't. +target_include_directories(MathFunctions + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + ) + +# link our compiler flags interface library +target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) + +add_executable(testmathfunctions test_MathFunctions.cxx) +target_link_libraries(testmathfunctions PUBLIC MathFunctions tutorial_compiler_flags) +target_link_libraries(testmathfunctions PRIVATE Catch2::Catch2WithMain) diff --git a/01_02_infrastructure_resources/code/cpp-example/MathFunctions/MathFunctions.cxx b/01_02_infrastructure_resources/code/cpp-example/MathFunctions/MathFunctions.cxx new file mode 100644 index 0000000..d791df2 --- /dev/null +++ b/01_02_infrastructure_resources/code/cpp-example/MathFunctions/MathFunctions.cxx @@ -0,0 +1,12 @@ +#include "MathFunctions.h" + +#include + +namespace mathfunctions { +double sqrt(double x) { return std::sqrt(x); } + +unsigned int Factorial(unsigned int number) { + return number <= 1 ? number : Factorial(number - 1) * number; +} + +} // namespace mathfunctions diff --git a/01_02_infrastructure_resources/code/cpp-example/MathFunctions/MathFunctions.h b/01_02_infrastructure_resources/code/cpp-example/MathFunctions/MathFunctions.h new file mode 100644 index 0000000..52e34b5 --- /dev/null +++ b/01_02_infrastructure_resources/code/cpp-example/MathFunctions/MathFunctions.h @@ -0,0 +1,6 @@ +#pragma once + +namespace mathfunctions { +double sqrt(double x); +unsigned int Factorial( unsigned int number ); +} diff --git a/01_02_infrastructure_resources/code/cpp-example/MathFunctions/test_MathFunctions.cxx b/01_02_infrastructure_resources/code/cpp-example/MathFunctions/test_MathFunctions.cxx new file mode 100644 index 0000000..c1acc44 --- /dev/null +++ b/01_02_infrastructure_resources/code/cpp-example/MathFunctions/test_MathFunctions.cxx @@ -0,0 +1,11 @@ +#include +#include "MathFunctions.h" + +using mathfunctions::Factorial; + +TEST_CASE( "Factorials are computed", "[factorial]" ) { + REQUIRE( Factorial(1) == 1 ); + REQUIRE( Factorial(2) == 2 ); + REQUIRE( Factorial(3) == 6 ); + REQUIRE( Factorial(10) == 3628800 ); +} \ No newline at end of file diff --git a/01_02_infrastructure_resources/code/cpp-example/README.md b/01_02_infrastructure_resources/code/cpp-example/README.md new file mode 100644 index 0000000..aad19ea --- /dev/null +++ b/01_02_infrastructure_resources/code/cpp-example/README.md @@ -0,0 +1,13 @@ +# Sample project with tests using Catch2 + +Setup with: +```bash +cmake -S . -B build -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=1 +if [ ! -e compile_commands.json ]; then + ln -s build/compile_commands.json . +fi +``` +run with +```bash +cmake --build build +``` diff --git a/01_02_infrastructure_resources/code/cpp-example/TutorialConfig.h.in b/01_02_infrastructure_resources/code/cpp-example/TutorialConfig.h.in new file mode 100644 index 0000000..7e4d7fa --- /dev/null +++ b/01_02_infrastructure_resources/code/cpp-example/TutorialConfig.h.in @@ -0,0 +1,3 @@ +// the configured options and settings for Tutorial +#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ +#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ diff --git a/01_02_infrastructure_resources/code/cpp-example/cmake/ECMEnableSanitizers.cmake b/01_02_infrastructure_resources/code/cpp-example/cmake/ECMEnableSanitizers.cmake new file mode 100644 index 0000000..cc88929 --- /dev/null +++ b/01_02_infrastructure_resources/code/cpp-example/cmake/ECMEnableSanitizers.cmake @@ -0,0 +1,167 @@ +# SPDX-FileCopyrightText: 2014 Mathieu Tarral +# +# SPDX-License-Identifier: BSD-3-Clause + +#[=======================================================================[.rst: +ECMEnableSanitizers +------------------- + +Enable compiler sanitizer flags. + +The following sanitizers are supported: + +- Address Sanitizer +- Memory Sanitizer +- Thread Sanitizer +- Leak Sanitizer +- Undefined Behaviour Sanitizer + +All of them are implemented in Clang, depending on your version, and +there is an work in progress in GCC, where some of them are currently +implemented. + +This module will check your current compiler version to see if it +supports the sanitizers that you want to enable + +Usage +===== + +Simply add:: + + include(ECMEnableSanitizers) + +to your ``CMakeLists.txt``. Note that this module is included in +:kde-module:`KDECompilerSettings`, so projects using that module do not need to also +include this one. + +The sanitizers are not enabled by default. Instead, you must set +``ECM_ENABLE_SANITIZERS`` (either in your ``CMakeLists.txt`` or on the +command line) to a semicolon-separated list of sanitizers you wish to enable. +The options are: + +- address +- memory +- thread +- leak +- undefined +- fuzzer + +The sanitizers "address", "memory" and "thread" are mutually exclusive. You +cannot enable two of them in the same build. + +"leak" requires the "address" sanitizer. + +.. note:: + + To reduce the overhead induced by the instrumentation of the sanitizers, it + is advised to enable compiler optimizations (``-O1`` or higher). + +Example +======= + +This is an example of usage:: + + mkdir build + cd build + cmake -DECM_ENABLE_SANITIZERS='address;leak;undefined' .. + +.. note:: + + Most of the sanitizers will require Clang. To enable it, use:: + + -DCMAKE_CXX_COMPILER=clang++ + +Since 1.3.0. +#]=======================================================================] + +# MACRO check_compiler_version +#----------------------------- +macro (check_compiler_version gcc_required_version clang_required_version msvc_required_version) + if ( + ( + CMAKE_CXX_COMPILER_ID MATCHES "GNU" + AND + CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${gcc_required_version} + ) + OR + ( + CMAKE_CXX_COMPILER_ID MATCHES "Clang" + AND + CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${clang_required_version} + ) + OR + ( + CMAKE_CXX_COMPILER_ID MATCHES "MSVC" + AND + CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${msvc_required_version} + ) + ) + # error ! + message(FATAL_ERROR "You ask to enable the sanitizer ${CUR_SANITIZER}, + but your compiler ${CMAKE_CXX_COMPILER_ID} version ${CMAKE_CXX_COMPILER_VERSION} + does not support it ! + You should use at least GCC ${gcc_required_version}, Clang ${clang_required_version} + or MSVC ${msvc_required_version} + (99.99 means not implemented yet)") + endif () +endmacro () + +# MACRO check_compiler_support +#------------------------------ +macro (enable_sanitizer_flags sanitize_option) + if (${sanitize_option} MATCHES "address") + check_compiler_version("4.8" "3.1" "19.28") + if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + set(XSAN_COMPILE_FLAGS "-fsanitize=address") + else() + set(XSAN_COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls") + set(XSAN_LINKER_FLAGS "asan") + endif() + elseif (${sanitize_option} MATCHES "thread") + check_compiler_version("4.8" "3.1" "99.99") + set(XSAN_COMPILE_FLAGS "-fsanitize=thread") + set(XSAN_LINKER_FLAGS "tsan") + elseif (${sanitize_option} MATCHES "memory") + check_compiler_version("99.99" "3.1" "99.99") + set(XSAN_COMPILE_FLAGS "-fsanitize=memory") + elseif (${sanitize_option} MATCHES "leak") + check_compiler_version("4.9" "3.4" "99.99") + set(XSAN_COMPILE_FLAGS "-fsanitize=leak") + set(XSAN_LINKER_FLAGS "lsan") + elseif (${sanitize_option} MATCHES "undefined") + check_compiler_version("4.9" "3.1" "99.99") + set(XSAN_COMPILE_FLAGS "-fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls") + elseif (${sanitize_option} MATCHES "fuzzer") + check_compiler_version("99.99" "6.0" "99.99") + set(XSAN_COMPILE_FLAGS "-fsanitize=fuzzer") + else () + message(FATAL_ERROR "Compiler sanitizer option \"${sanitize_option}\" not supported.") + endif () +endmacro () + +if (ECM_ENABLE_SANITIZERS) + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + # for each element of the ECM_ENABLE_SANITIZERS list + foreach ( CUR_SANITIZER ${ECM_ENABLE_SANITIZERS} ) + # lowercase filter + string(TOLOWER ${CUR_SANITIZER} CUR_SANITIZER) + # check option and enable appropriate flags + enable_sanitizer_flags ( ${CUR_SANITIZER} ) + # TODO: GCC will not link pthread library if enabled ASan + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${XSAN_COMPILE_FLAGS}" ) + endif() + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${XSAN_COMPILE_FLAGS}" ) + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + link_libraries(${XSAN_LINKER_FLAGS}) + endif() + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + string(REPLACE "-Wl,--no-undefined" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") + endif () + endforeach() + else() + message(STATUS "Tried to enable sanitizers (-DECM_ENABLE_SANITIZERS=${ECM_ENABLE_SANITIZERS}), \ +but compiler (${CMAKE_CXX_COMPILER_ID}) does not have sanitizer support") + endif() +endif() diff --git a/01_02_infrastructure_resources/code/cpp-example/tutorial.cxx b/01_02_infrastructure_resources/code/cpp-example/tutorial.cxx new file mode 100644 index 0000000..0d3ec8d --- /dev/null +++ b/01_02_infrastructure_resources/code/cpp-example/tutorial.cxx @@ -0,0 +1,26 @@ +// A simple program that computes the square root of a number +#include +#include +#include + +#include "MathFunctions.h" +#include "TutorialConfig.h" + +int main(int argc, char *argv[]) { + if (argc < 2) { + // report version + std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." + << Tutorial_VERSION_MINOR << std::endl; + std::cout << "Usage: " << argv[0] << " number" << std::endl; + return 1; + } + + // convert input to double + const double inputValue = std::stod(argv[1]); + + const double outputValue = mathfunctions::sqrt(inputValue); + + std::cout << "The square root of " << inputValue << " is " << outputValue + << std::endl; + return 0; +} From d89cfc887e15bcc3e254f5b6f431bb0b6346eaa4 Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Wed, 11 Oct 2023 14:08:13 +0200 Subject: [PATCH 2/3] addedn data oriented tips --- 03_01_data_oriented_design/CMakeLists.txt | 1 + .../data_oriented_tips.md | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 03_01_data_oriented_design/data_oriented_tips.md diff --git a/03_01_data_oriented_design/CMakeLists.txt b/03_01_data_oriented_design/CMakeLists.txt index a73fec5..bbf8472 100644 --- a/03_01_data_oriented_design/CMakeLists.txt +++ b/03_01_data_oriented_design/CMakeLists.txt @@ -1,5 +1,6 @@ if (${CPP_COURSE_BUILD_SLIDES}) add_marp_slides(03_01_data_oriented_design data_oriented_design.md) + add_marp_slides(03_01_data_oriented_design data_oriented_tips.md) endif() diff --git a/03_01_data_oriented_design/data_oriented_tips.md b/03_01_data_oriented_design/data_oriented_tips.md new file mode 100644 index 0000000..1f75c8e --- /dev/null +++ b/03_01_data_oriented_design/data_oriented_tips.md @@ -0,0 +1,35 @@ +--- +marp: true +theme: cscs +# class: lead +paginate: true +backgroundColor: #fff +backgroundImage: url('../slides-support/common/4k-slide-bg-white.png') +size: 16:9 +--- +# General Hints +* Minimize memory usage + * pack, use smaller types + * in some cases even compression can help + * but beware of alignement +* Bools and enums in structures + * try to avoid if/case in the element operation + * separate elements by types +* Centralize handling + * move memory management into a centralized system (system, environment,...) + * Operate on bunch of elements, not on the single element + * amortize load cost on several similar operations, ideally working on close by memory + * global optimizations are easier to do +* Think about a SoA (Struct of Arrays) instead of AoS (Arrays of struct) +* prefer Handles/indexes to pointers when referring to elements + +--- +# References + +- Handles are the better pointers +https://floooh.github.io/2018/06/17/handles-vs-pointers.html +- Andrew Kelly [Practical DOD](https://vimeo.com/649009599) +- CppCon 2014: Mike Acton "Data-Oriented Design and C++": [youtube.com/watch?v=rX0ItVEVjHc](https://youtube.com/watch?v=rX0ItVEVjHc) +- Richard Fabian, 'Data-Oriented Design': [dataorienteddesign.com/dodbook/](https://www.dataorienteddesign.com/dodbook/) +- IT Hare, 'Infographics: Operation Costs in CPU Clock Cycles': [ithare.com/infographics-operation-costs-in-cpu-clock-cycles/](http://ithare.com/infographics-operation-costs-in-cpu-clock-cycles/) +- The Brain Dump, 'Handles are the better pointers': [floooh.github.io/2018/06/17/handles-vs-pointers.html](https://floooh.github.io/2018/06/17/handles-vs-pointers.html) \ No newline at end of file From 098f55064d0df0a867499ddd7fe0c8df97a1e68c Mon Sep 17 00:00:00 2001 From: Hannes Vogt Date: Thu, 12 Oct 2023 10:11:12 +0200 Subject: [PATCH 3/3] Update CMakeLists.txt --- 03_01_data_oriented_design/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/03_01_data_oriented_design/CMakeLists.txt b/03_01_data_oriented_design/CMakeLists.txt index bbf8472..b8d7641 100644 --- a/03_01_data_oriented_design/CMakeLists.txt +++ b/03_01_data_oriented_design/CMakeLists.txt @@ -1,6 +1,6 @@ if (${CPP_COURSE_BUILD_SLIDES}) add_marp_slides(03_01_data_oriented_design data_oriented_design.md) - add_marp_slides(03_01_data_oriented_design data_oriented_tips.md) + add_marp_slides(03_01_data_oriented_tips data_oriented_tips.md) endif() @@ -21,4 +21,4 @@ add_executable(03_01_cache_false_sharing code/cache_false_sharing.cpp ) -add_subdirectory(code/nbody) \ No newline at end of file +add_subdirectory(code/nbody)