diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..0822db5d --- /dev/null +++ b/.clang-format @@ -0,0 +1,225 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAfterAttributes: Never +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseTab: Never +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +... + diff --git a/.github/workflows/build-no-mpi.yml b/.github/workflows/build-no-mpi.yml deleted file mode 100644 index 3c7f57ff..00000000 --- a/.github/workflows/build-no-mpi.yml +++ /dev/null @@ -1,82 +0,0 @@ -# ------------------------------------------------------------------------------ -# (c) Crown copyright 2024 Met Office. All rights reserved. -# The file LICENCE, distributed with this code, contains details of the terms -# under which the code may be used. -# ------------------------------------------------------------------------------ -name: Build and Test without MPI - -on: - workflow_dispatch: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Debug - -jobs: - build: - # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. - # You can convert this to a matrix build if you need cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - compiler: [ - {c: gcc-10, cpp: g++-10, fortran: gfortran-10}, - {c: clang-12, cpp: clang++-12, fortran: gfortran-10} - ] - - steps: - - uses: actions/checkout@v3 - - - name: Install libomp-devel - # Ensure that the OpenMP development libraries are installed. - run: | - sudo apt update - sudo apt install -y libomp-12-dev - - - name: Check versions - # Print the version number of installed libraries - run: | - gcc --version - $ echo |cpp -fopenmp -dM |grep -i open - - - name: Configure CMake - # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. - # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: > - cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - -DCMAKE_C_COMPILER=${{ matrix.compiler.c }} - -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cpp }} - -DCMAKE_Fortran_COMPILER=${{ matrix.compiler.fortran }} - -DBUILD_TESTS=ON - -DBUILD_FORTRAN_TESTS=OFF - -DINCLUDE_GTEST=ON - -DWARNINGS_AS_ERRORS=ON - -DUSE_SANITIZERS=ON - -DENABLE_DOXYGEN=OFF - -DBUILD_DOCS=OFF - -DENABLE_MPI=NO - - - name: Build - # Build your program with the given configuration - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - # Run tests on a single thread - - name: "Test (1 thread)" - env: - OMP_NUM_THREADS: 1 - working-directory: ${{github.workspace}}/build - run: ctest -VV -C ${{env.BUILD_TYPE}} - - # Run tests on 4 threads - - name: "Test (4 threads)" - env: - OMP_NUM_THREADS: 4 - working-directory: ${{github.workspace}}/build - run: ctest -VV -C ${{env.BUILD_TYPE}} - diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0a286c50..80b7a0f8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,17 +18,19 @@ env: jobs: build: - # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. + # The CMake configure and build commands are platform-agnostic and should work equally well on Windows or Mac. # You can convert this to a matrix build if you need cross-platform coverage. # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: + mpi_enabled: [ON, OFF] compiler: [ {c: gcc-10, cpp: g++-10, fortran: gfortran-10}, {c: clang-12, cpp: clang++-12, fortran: gfortran-10} ] + name: Compiler ${{ matrix.compiler.cpp }} with MPI ${{matrix.mpi_enabled}} steps: - uses: actions/checkout@v3 @@ -62,6 +64,7 @@ jobs: -DUSE_SANITIZERS=ON -DENABLE_DOXYGEN=OFF -DBUILD_DOCS=OFF + -DENABLE_MPI=${{ matrix.mpi_enabled }} - name: Build # Build your program with the given configuration diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 10e650e6..588e166d 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -12,7 +12,7 @@ on: paths: - 'src/**.h' - 'src/**.cpp' - - 'documentation/**.md' + - 'documentation/**' - '.github/workflows/documentation.yml' env: diff --git a/.github/workflows/format-check.yml b/.github/workflows/format-check.yml new file mode 100644 index 00000000..d7165a31 --- /dev/null +++ b/.github/workflows/format-check.yml @@ -0,0 +1,19 @@ +name: Format Check +on: + pull_request: + branches: [ main ] + +jobs: + check: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + + - name: Check style with clang-format + # Use clang-format to check all C++ files for code style errors. + # The .clang-format file was created using clang-format 16, not all + # checks are available in earlier versions so the --Wno-error=unknown flag + # is used. Users should use clang-format 16 or later if possible. + run: > + find ${{github.workspace}} -iname '*.cpp' -o -iname '*.h' | xargs + clang-format --dry-run --Werror --Wno-error=unknown 2>&1 diff --git a/CMakeLists.txt b/CMakeLists.txt index baa8bc48..1698d236 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,11 +46,6 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) include(cmake/Doxygen.cmake) include(cmake/Sphinx.cmake) - # Make sphinx target depend on builing doxygen docs first - if(ENABLE_SPHINX) - add_dependencies(sphinxdocs doxygendocs) - endif() - # Include option to build with/without OpenMP include(cmake/BuildOptions.cmake) diff --git a/documentation/Sphinx/_static/MO_SQUARE_black_mono_for_light_backg_RBG.png b/documentation/Sphinx/_static/MO_SQUARE_black_mono_for_light_backg_RBG.png new file mode 100755 index 00000000..371795ca Binary files /dev/null and b/documentation/Sphinx/_static/MO_SQUARE_black_mono_for_light_backg_RBG.png differ diff --git a/documentation/Sphinx/_static/MO_SQUARE_for_dark_backg_RBG.png b/documentation/Sphinx/_static/MO_SQUARE_for_dark_backg_RBG.png new file mode 100755 index 00000000..81001378 Binary files /dev/null and b/documentation/Sphinx/_static/MO_SQUARE_for_dark_backg_RBG.png differ diff --git a/documentation/Sphinx/_static/custom.css b/documentation/Sphinx/_static/custom.css new file mode 100644 index 00000000..e00ce087 --- /dev/null +++ b/documentation/Sphinx/_static/custom.css @@ -0,0 +1,26 @@ +/* import the standard theme css */ +@import url("styles/theme.css"); +@import url("basic.css"); + +/* Office Science Colours */ +html[data-theme="light"] { + --pst-color-primary: #0f79be; + --pst-color-secondary: #e2a022; + --pst-color-accent: #e2a022; +} + +html[data-theme="dark"] { + --pst-color-primary: #359bc0; + --pst-color-secondary: #eac45f; + --pst-color-accent: #eac45f; + + /* Overwrite visited colour to be AAA contrast compliant */ + a:visited { + color: #be90ea; + } + + /* Reset the overridden hover colour */ + a:visited:hover { + color: var(--pst-color-link-hover); + } +} \ No newline at end of file diff --git a/documentation/Sphinx/conf.py b/documentation/Sphinx/conf.py index c5ad9117..3fdf6d19 100644 --- a/documentation/Sphinx/conf.py +++ b/documentation/Sphinx/conf.py @@ -17,11 +17,15 @@ # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here. -extensions = ["sphinx_sitemap"] +extensions = ["sphinx_sitemap", + "sphinx_design"] # Add any paths that contain templates here. templates_path = ['_templates'] +html_static_path = ["_static"] +html_css_files = ["custom.css"] + # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] @@ -52,8 +56,18 @@ "name": "GitHub", "url": "https://github.com/MetOffice/vernier", "icon": "fa-brands fa-github" + }, + { + "name": "GitHub Discussions", + "url": "https://github.com/MetOffice/lfric_core/discussions", + "icon": "far fa-comments", } ], + "logo": { + "text": "LFRic Core", + "image_light": "_static/MO_SQUARE_black_mono_for_light_backg_RBG.png", + "image_dark": "_static/MO_SQUARE_for_dark_backg_RBG.png", + }, "secondary_sidebar_items": { "**/*": ["page-toc", "edit-this-page"], "index": [], diff --git a/documentation/Sphinx/dev-corner/index.rst b/documentation/Sphinx/developer_guide/index.rst similarity index 54% rename from documentation/Sphinx/dev-corner/index.rst rename to documentation/Sphinx/developer_guide/index.rst index 1b3834cd..70b61261 100644 --- a/documentation/Sphinx/dev-corner/index.rst +++ b/documentation/Sphinx/developer_guide/index.rst @@ -1,5 +1,13 @@ -Developer Corner -================ +.. ----------------------------------------------------------------------------- + (c) Crown copyright 2024 Met Office. All rights reserved. + The file LICENCE, distributed with this code, contains details of the terms + under which the code may be used. + ----------------------------------------------------------------------------- + +.. _developer_guide_index: + +Developer Guide +=============== Here you can find information relevant to developers who wish to contribute to Vernier. diff --git a/documentation/Sphinx/dev-corner/testing.rst b/documentation/Sphinx/developer_guide/testing.rst similarity index 51% rename from documentation/Sphinx/dev-corner/testing.rst rename to documentation/Sphinx/developer_guide/testing.rst index c8bfe3cf..abd7c47f 100644 --- a/documentation/Sphinx/dev-corner/testing.rst +++ b/documentation/Sphinx/developer_guide/testing.rst @@ -1,3 +1,9 @@ +.. ----------------------------------------------------------------------------- + (c) Crown copyright 2024 Met Office. All rights reserved. + The file LICENCE, distributed with this code, contains details of the terms + under which the code may be used. + ----------------------------------------------------------------------------- + Testing ======= diff --git a/documentation/Sphinx/index.rst b/documentation/Sphinx/index.rst index 9325ed61..08b5d4b5 100644 --- a/documentation/Sphinx/index.rst +++ b/documentation/Sphinx/index.rst @@ -1,3 +1,9 @@ +.. ----------------------------------------------------------------------------- + (c) Crown copyright 2024 Met Office. All rights reserved. + The file LICENCE, distributed with this code, contains details of the terms + under which the code may be used. + ----------------------------------------------------------------------------- + :html_theme.sidebar_secondary.remove: true Vernier Documentation @@ -6,8 +12,39 @@ Vernier Documentation Vernier is a calliper-based profiling tool for scientific code on HPC platforms, primarily designed for use within the various Met Office models and frameworks. +.. grid:: 2 + + .. grid-item-card:: + :text-align: center + + Guide on the code for users and developers + + +++ + .. button-ref:: user_guide_index + :ref-type: ref + :color: primary + :outline: + :expand: + + User Guide + + .. grid-item-card:: + :text-align: center + + Guide on details of the development process + + +++ + .. button-ref:: developer_guide_index + :ref-type: ref + :color: primary + :outline: + :expand: + + Developer Guide + .. toctree:: :maxdepth: 2 + :hidden: - user-manual/index - dev-corner/index + user_guide/index + developer_guide/index diff --git a/documentation/Sphinx/user-manual/index.rst b/documentation/Sphinx/user-manual/index.rst deleted file mode 100644 index 8a5cba64..00000000 --- a/documentation/Sphinx/user-manual/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -User Manual -=========== - -.. toctree:: - - build-guide - setting-up - api - output - post-processing \ No newline at end of file diff --git a/documentation/Sphinx/user-manual/api.rst b/documentation/Sphinx/user_guide/api.rst similarity index 80% rename from documentation/Sphinx/user-manual/api.rst rename to documentation/Sphinx/user_guide/api.rst index 0c582f53..2794a902 100644 --- a/documentation/Sphinx/user-manual/api.rst +++ b/documentation/Sphinx/user_guide/api.rst @@ -1,3 +1,9 @@ +.. ----------------------------------------------------------------------------- + (c) Crown copyright 2024 Met Office. All rights reserved. + The file LICENCE, distributed with this code, contains details of the terms + under which the code may be used. + ----------------------------------------------------------------------------- + API --- diff --git a/documentation/Sphinx/user-manual/build-guide.rst b/documentation/Sphinx/user_guide/build-guide.rst similarity index 91% rename from documentation/Sphinx/user-manual/build-guide.rst rename to documentation/Sphinx/user_guide/build-guide.rst index 5e0ca3d6..16fa8215 100644 --- a/documentation/Sphinx/user-manual/build-guide.rst +++ b/documentation/Sphinx/user_guide/build-guide.rst @@ -1,3 +1,9 @@ +.. ----------------------------------------------------------------------------- + (c) Crown copyright 2024 Met Office. All rights reserved. + The file LICENCE, distributed with this code, contains details of the terms + under which the code may be used. + ----------------------------------------------------------------------------- + Build Guide =========== diff --git a/documentation/Sphinx/user_guide/index.rst b/documentation/Sphinx/user_guide/index.rst new file mode 100644 index 00000000..4aa2dc66 --- /dev/null +++ b/documentation/Sphinx/user_guide/index.rst @@ -0,0 +1,16 @@ +.. ----------------------------------------------------------------------------- + (c) Crown copyright 2024 Met Office. All rights reserved. + The file LICENCE, distributed with this code, contains details of the terms + under which the code may be used. + ----------------------------------------------------------------------------- +.. _user_guide_index: + +User Guide +========== + +.. toctree:: + + build-guide + setting-up + api + output \ No newline at end of file diff --git a/documentation/Sphinx/user-manual/output.rst b/documentation/Sphinx/user_guide/output.rst similarity index 91% rename from documentation/Sphinx/user-manual/output.rst rename to documentation/Sphinx/user_guide/output.rst index 073b9790..acba3bcf 100644 --- a/documentation/Sphinx/user-manual/output.rst +++ b/documentation/Sphinx/user_guide/output.rst @@ -1,3 +1,9 @@ +.. ----------------------------------------------------------------------------- + (c) Crown copyright 2024 Met Office. All rights reserved. + The file LICENCE, distributed with this code, contains details of the terms + under which the code may be used. + ----------------------------------------------------------------------------- + Interpreting Output ------------------- diff --git a/documentation/Sphinx/user-manual/setting-up.rst b/documentation/Sphinx/user_guide/setting-up.rst similarity index 90% rename from documentation/Sphinx/user-manual/setting-up.rst rename to documentation/Sphinx/user_guide/setting-up.rst index 2e88dcc5..ac22ede6 100644 --- a/documentation/Sphinx/user-manual/setting-up.rst +++ b/documentation/Sphinx/user_guide/setting-up.rst @@ -1,3 +1,9 @@ +.. ----------------------------------------------------------------------------- + (c) Crown copyright 2024 Met Office. All rights reserved. + The file LICENCE, distributed with this code, contains details of the terms + under which the code may be used. + ----------------------------------------------------------------------------- + .. _settingup: Setting Up diff --git a/etc/conda/vernier-env.lock b/etc/conda/vernier-env.lock index c313dc42..f5540c57 100644 --- a/etc/conda/vernier-env.lock +++ b/etc/conda/vernier-env.lock @@ -1,63 +1,67 @@ +# Generated by conda-lock. # This file may be used to create an environment using: # $ conda create --name --file # platform: linux-64 +# input_hash: 0301cb4c1e31ae7dbe7bddf44232aa0648d9123fb5880216e88c248b89e8bcfd +# File created using conda-lock (conda-lock --kind explicit -f vernier-env.yml -p linux-64) @EXPLICIT -https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 -https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda -https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda -https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_5.conda -https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda -https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda -https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_5.conda -https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 -https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda -https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda -https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda -https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 -https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda -https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda -https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda -https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda -https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4.20240210-h59595ed_0.conda -https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_1.conda -https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 -https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda -https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda -https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda -https://conda.anaconda.org/conda-forge/linux-64/python-3.12.2-hab00c5b_0_cpython.conda -https://conda.anaconda.org/conda-forge/noarch/alabaster-0.7.16-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py312h30efb56_1.conda -https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 -https://conda.anaconda.org/conda-forge/linux-64/docutils-0.20.1-py312h7900ff3_3.conda -https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/imagesize-1.4.1-pyhd8ed1ab_0.tar.bz2 -https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py312h98912ed_0.conda -https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 -https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 -https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-2.2.0-pyhd8ed1ab_0.tar.bz2 -https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda -https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jsmath-1.0.1-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda -https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/accessible-pygments-0.0.4-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/babel-2.14.0-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.12.3-pyha770c72_0.conda -https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda -https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.10.0-hd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/pydata-sphinx-theme-0.15.2-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/sphinx-sitemap-2.5.1-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-1.0.8-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-1.0.6-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.0.5-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-qthelp-1.0.7-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/sphinx-7.2.6-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-1.1.10-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2#d7c89558ba9fa0495403155b64376d81 +https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.6.2-hbcca054_0.conda#847c3c2905cc467cea52c24f9cfa8080 +https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-hf3520f5_2.conda#61b0bd5219ce7192b4e3633521a78975 +https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-hc0a3c3a_7.conda#53ebd4c833fa01cb2c6353e99f905406 +https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda#dccc2d142812964fcc6abdc97b672dff +https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda#161081fc7cec0bfda0d86d7cb595f8d8 +https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h77fa898_7.conda#abf3fec87c2563697defa759dec3d639 +https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2#73aaf86a425cc6e73fcf236a5a46396d +https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h77fa898_7.conda#72ec1b1b04c4d15d4204ece1ecea5978 +https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda#69b8b6202a07720f448be700e300ccf4 +https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda#e7ba12deb7020dd080c6c70e7b6f6a3d +https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2#d645c6d2ac96843a2bfaccd2d62b3ac3 +https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda#30fd6e37fe21f86f4bd26d6ee73eeec7 +https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda#40b61aab5c7ba9ff276c41cfffe6b80b +https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda#5aa797f8787fe7a17d1b0821485b5adc +https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda#57d7dc60e9325e3de37ff8dffd18e814 +https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h59595ed_0.conda#fcea371545eda051b6deafb24889fc69 +https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.1-h4ab18f5_0.conda#a41fa0e391cc9e0d6b78ac69ca047a6c +https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2#2161070d867d1b1204ea749c8eec4ef0 +https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.3-h2797004_0.conda#b3316cbe90249da4f8e84cd66e1cc55b +https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda#47d31b792659ce70f470b5c82fdfb7a4 +https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda#d453b98d9c83e71da0741bb0ff4d76bc +https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda#2540b74d304f71d3e89c81209db4db84 +https://conda.anaconda.org/conda-forge/noarch/alabaster-0.7.16-pyhd8ed1ab_0.conda#def531a3ac77b7fb8c21d17bb5d0badb +https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py312h30efb56_1.conda#45801a89533d3336a365284d93298e36 +https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda#0876280e409658fc6f9e75d035960333 +https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda#7f4a9e3fcff3f6356ae99244a014da6a +https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2#3faab06a954c2a04039983f2c4a50d99 +https://conda.anaconda.org/conda-forge/noarch/docutils-0.21.2-pyhd8ed1ab_0.conda#e8cd5d629f65bdf0f3bb312cde14659e +https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda#c0cc1420498b17414d8617d0b9f506ca +https://conda.anaconda.org/conda-forge/noarch/imagesize-1.4.1-pyhd8ed1ab_0.tar.bz2#7de5386c8fea29e76b303f37dde4c352 +https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py312h98912ed_0.conda#6ff0b9582da2d4a74a1f9ae1f9ce2af6 +https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda#248f521b64ce055e7feae3105e7abeb8 +https://conda.anaconda.org/conda-forge/noarch/pygments-2.18.0-pyhd8ed1ab_0.conda#b7f5c092b8f9800150d998a71b76d5a1 +https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2#2a7de29fb590ca14b5243c4c812c8025 +https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda#3eeeeb9e4827ace8c0c1419c85d590ad +https://conda.anaconda.org/conda-forge/noarch/setuptools-70.0.0-pyhd8ed1ab_0.conda#c8ddb4f34a208df4dd42509a0f6a1c89 +https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2#e5f25f8dbc060e9a8d912e432202afc2 +https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-2.2.0-pyhd8ed1ab_0.tar.bz2#4d22a9315e78c6827f806065957d566e +https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda#3f144b2c34f8cb5a9abd9ed23a39c561 +https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jsmath-1.0.1-pyhd8ed1ab_0.conda#da1d979339e2714c30a8e806a33ec087 +https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2#5844808ffab9ebdb694585b50ba02a96 +https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.12.1-pyha770c72_0.conda#26d7ee34132362115093717c706c384c +https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda#2e4d6bc0b14e10f895fc6791a7d9b26a +https://conda.anaconda.org/conda-forge/noarch/accessible-pygments-0.0.4-pyhd8ed1ab_0.conda#46a2e6e3dfa718ce3492018d5a110dd6 +https://conda.anaconda.org/conda-forge/noarch/babel-2.14.0-pyhd8ed1ab_0.conda#9669586875baeced8fc30c0826c3270e +https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.12.3-pyha770c72_0.conda#332493000404d8411859539a5a630865 +https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda#0896606848b2dc5cebdf111b6543aa04 +https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.4-pyhd8ed1ab_0.conda#7b86ecb7d3557821c649b3c31e3eb9f2 +https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda#08807a87fa7af10754d46f63b368e016 +https://conda.anaconda.org/conda-forge/noarch/requests-2.32.3-pyhd8ed1ab_0.conda#5ede4753180c7a550a443c430dc8ab52 +https://conda.anaconda.org/conda-forge/noarch/pydata-sphinx-theme-0.15.3-pyhd8ed1ab_0.conda#55e445f4fcb07f2471fb0e1102d36488 +https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.5.0-pyhd8ed1ab_0.conda#264b3c697fa9cdade87eb0abe4440d54 +https://conda.anaconda.org/conda-forge/noarch/sphinx-sitemap-2.5.1-pyhd8ed1ab_0.conda#16180a676b0dbbb83f67326d01408f64 +https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-1.0.8-pyhd8ed1ab_0.conda#611a35a27914fac3aa37611a6fe40bb5 +https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-1.0.6-pyhd8ed1ab_0.conda#d7e4954df0d3aea2eacc7835ad12671d +https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.0.5-pyhd8ed1ab_0.conda#7e1e7437273682ada2ed5e9e9714b140 +https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-qthelp-1.0.7-pyhd8ed1ab_0.conda#26acae54b06f178681bfb551760f5dd1 +https://conda.anaconda.org/conda-forge/noarch/sphinx-7.3.7-pyhd8ed1ab_0.conda#7b1465205e28d75d2c0e1a868ee00a67 +https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-1.1.10-pyhd8ed1ab_0.conda#e507335cb4ca9cff4c3d0fa9cdab255e diff --git a/etc/conda/vernier-env.yml b/etc/conda/vernier-env.yml index b462980d..5b99a2bb 100644 --- a/etc/conda/vernier-env.yml +++ b/etc/conda/vernier-env.yml @@ -7,3 +7,4 @@ dependencies: - sphinx - pydata-sphinx-theme - sphinx-sitemap + - sphinx-design diff --git a/src/c++/error_handler.cpp b/src/c++/error_handler.cpp index 38c5c436..acd47992 100644 --- a/src/c++/error_handler.cpp +++ b/src/c++/error_handler.cpp @@ -1,12 +1,12 @@ /* ----------------------------------------------------------------------------- -* (c) Crown copyright 2024 Met Office. All rights reserved. -* The file LICENCE, distributed with this code, contains details of the terms -* under which the code may be used. -* ----------------------------------------------------------------------------- -*/ + * (c) Crown copyright 2024 Met Office. All rights reserved. + * The file LICENCE, distributed with this code, contains details of the terms + * under which the code may be used. + * ----------------------------------------------------------------------------- + */ -#include #include +#include #include "error_handler.h" #include "vernier_mpi.h" @@ -18,9 +18,9 @@ * @param [in] errorCode The code for the error */ -meto::error_handler::error_handler (const std::string &customError, int errorCode) -{ - MPI_Comm comm = MPI_COMM_WORLD; - std::cerr << customError << "\n"; - MPI_Abort(comm, errorCode); +meto::error_handler::error_handler(const std::string &customError, + int errorCode) { + MPI_Comm comm = MPI_COMM_WORLD; + std::cerr << customError << "\n"; + MPI_Abort(comm, errorCode); } diff --git a/src/c++/error_handler.h b/src/c++/error_handler.h index 9ba4b0eb..a0d71ef1 100644 --- a/src/c++/error_handler.h +++ b/src/c++/error_handler.h @@ -1,9 +1,9 @@ /* ----------------------------------------------------------------------------- -* (c) Crown copyright 2024 Met Office. All rights reserved. -* The file LICENCE, distributed with this code, contains details of the terms -* under which the code may be used. -* ----------------------------------------------------------------------------- -*/ + * (c) Crown copyright 2024 Met Office. All rights reserved. + * The file LICENCE, distributed with this code, contains details of the terms + * under which the code may be used. + * ----------------------------------------------------------------------------- + */ #include #include @@ -13,20 +13,19 @@ * @file error_handler().h * @brief Header file for error_handler.cpp * - * + * */ #ifndef ERROR_HANDLER_H #define ERROR_HANDLER_H -namespace meto -{ - //Class prototypes - class error_handler - { +namespace meto { +// Class prototypes +class error_handler { - public: - explicit error_handler (const std::string &customError= "", int errorCode= 0); - }; -} // End meto namespace +public: + explicit error_handler(const std::string &customError = "", + int errorCode = 0); +}; +} // namespace meto #endif diff --git a/src/c++/formatter.cpp b/src/c++/formatter.cpp index a492c1ee..4830258d 100644 --- a/src/c++/formatter.cpp +++ b/src/c++/formatter.cpp @@ -1,15 +1,15 @@ /* ----------------------------------------------------------------------------- -* (c) Crown copyright 2021 Met Office. All rights reserved. -* The file LICENCE, distributed with this code, contains details of the terms -* under which the code may be used. -* ----------------------------------------------------------------------------- -*/ + * (c) Crown copyright 2021 Met Office. All rights reserved. + * The file LICENCE, distributed with this code, contains details of the terms + * under which the code may be used. + * ----------------------------------------------------------------------------- + */ #include "formatter.h" #include "error_handler.h" -#include #include +#include /** * @brief Formatter constructor @@ -17,101 +17,88 @@ * PROF_OUTPUT_FORMAT. */ -meto::Formatter::Formatter() -{ +meto::Formatter::Formatter() { - std::string format = "drhook"; + std::string format = "drhook"; - char const* env_format = std::getenv("VERNIER_OUTPUT_FORMAT"); - if(env_format){ format = env_format; } - - if ( format == "threads") - { - format_ = &Formatter::threads; - } - else if (format == "drhook") - { - format_ = &Formatter::drhook; + char const *env_format = std::getenv("VERNIER_OUTPUT_FORMAT"); + if (env_format) { + format = env_format; } - else - { - std::string error_msg = "Invalid Vernier output format choice. Expected 'threads' or 'drhook'. Currently set to '" - + format - + "'."; + + if (format == "threads") { + format_ = &Formatter::threads; + } else if (format == "drhook") { + format_ = &Formatter::drhook; + } else { + std::string error_msg = "Invalid Vernier output format choice. Expected " + "'threads' or 'drhook'. Currently set to '" + + format + "'."; error_handler(error_msg, EXIT_FAILURE); } } /** * @brief Executes the format_ method to write the data. - * + * * @param[in] os Output stream that the format method will write to * @param[in] hashvec Vector of data that the format method will operate on */ -void meto::Formatter::execute_format(std::ofstream& os, hashvec_t hashvec) -{ - (this->*format_)(os, hashvec); +void meto::Formatter::execute_format(std::ofstream &os, hashvec_t hashvec) { + (this->*format_)(os, hashvec); } /** * @brief Per-thread timing output. - * + * * @param[in] os Output stream to write to * @param[in] hashvec Vector containing all the necessary data */ -void meto::Formatter::threads(std::ofstream& os, hashvec_t hashvec) -{ +void meto::Formatter::threads(std::ofstream &os, hashvec_t hashvec) { // Write key os << "\n"; - os << "region_name@thread_id" << "\n" - << "Self time : Time accrued by region itself. (Exclusive time.)" << "\n" - << "Total time: Time including cost of child routines and profiling overheads. (Inclusive time.)" << "\n" - << "Overhead : Profiling overhead incurred through direct child routine calls only." << "\n" - << "Calls : Number of times the region is called." << "\n"; + os << "region_name@thread_id\n" + << "Self time : Time accrued by region itself. (Exclusive time.)\n" + << "Total time: Time including cost of child routines and profiling " + "overheads. (Inclusive time.)\n" + << "Overhead : Profiling overhead incurred through direct child routine " + "calls only.\n" + << "Calls : Number of times the region is called.\n"; // Write headings os << "\n"; - os - << std::setw(40) << std::left << "Region" << " " - << std::setw(15) << std::right << "Self (s)" << " " - << std::setw(15) << std::right << "Total (s)" << " " - << std::setw(15) << std::right << "Overhead (s)" << " " - << std::setw(10) << std::right << "Calls" << "\n"; + os << std::setw(40) << std::left << "Region " << std::setw(15) << std::right + << "Self (s) " << std::setw(15) << std::right << "Total (s) " + << std::setw(15) << std::right << "Overhead (s) " << std::setw(10) + << std::right << "Calls\n"; os << std::setfill('-'); - os - << std::setw(40) << "-" << " " - << std::setw(15) << "-" << " " - << std::setw(15) << "-" << " " - << std::setw(15) << "-" << " " - << std::setw(10) << "-" << "\n"; + os << std::setw(40) << "- " << std::setw(15) << "- " << std::setw(15) << "- " + << std::setw(15) << "- " << std::setw(10) << "- \n"; os << std::setfill(' '); // Data entries - for (auto const& record : hashvec) { - os - << std::setw(40) << std::left << record.decorated_region_name_ << " " - << std::setw(15) << std::right << record.self_walltime_.count() << " " - << std::setw(15) << std::right << record.total_walltime_.count() << " " - << std::setw(15) << std::right << record.overhead_walltime_.count() << " " - << std::setw(10) << std::right << record.call_count_ << "\n"; + for (auto const &record : hashvec) { + os << std::setw(40) << std::left << record.decorated_region_name_ << " " + << std::setw(15) << std::right << record.self_walltime_.count() << " " + << std::setw(15) << std::right << record.total_walltime_.count() << " " + << std::setw(15) << std::right << record.overhead_walltime_.count() + << " " << std::setw(10) << std::right << record.call_count_ << "\n"; } - } /** * @brief Drhook-style output format, important for using the same post * processing tools - * + * * @param[in] os Output stream to write to * @param[in] hashvec Vector containing all the necessary data */ -void meto::Formatter::drhook(std::ofstream& os, hashvec_t hashvec) -{ +void meto::Formatter::drhook(std::ofstream &os, hashvec_t hashvec) { int num_threads = 1; #ifdef _OPENMP @@ -120,82 +107,65 @@ void meto::Formatter::drhook(std::ofstream& os, hashvec_t hashvec) // Preliminary info os << "Profiling on " << num_threads << " thread(s).\n"; - + // Table Headers os << "\n"; - os - << " " - << std::setw(3) << std::left << "#" - << std::setw(7) << std::left << "% Time" - << std::setw(13) << std::right << "Cumul" - << std::setw(13) << std::right << "Self" - << std::setw(13) << std::right << "Total" - << std::setw(15) << std::right << "# of calls" - << std::setw(12) << std::right << "Self" - << std::setw(12) << std::right << "Total" << " " - << "Routine@" << "\n"; - os - << " " - << std::setw(73) << "" - << "(Size; Size/sec; Size/call; MinSize; MaxSize)" << "\n"; - + os << " " << std::setw(3) << std::left << "#" << std::setw(7) << std::left + << "% Time" << std::setw(13) << std::right << "Cumul" << std::setw(13) + << std::right << "Self" << std::setw(13) << std::right << "Total" + << std::setw(15) << std::right << "# of calls" << std::setw(12) + << std::right << "Self" << std::setw(12) << std::right << "Total " + << "Routine@\n"; + os << " " << std::setw(73) << "" + << "(Size; Size/sec; Size/call; MinSize; MaxSize)\n"; + // Subheaders - os - << " " - << std::setw(3) << std::left << "" - << std::setw(7) << std::right << "(self)" - << std::setw(13) << std::right << "(sec)" - << std::setw(13) << std::right << "(sec)" - << std::setw(13) << std::right << "(sec)" - << std::setw(15) << std::right << "" - << std::setw(12) << std::right << "ms/call" - << std::setw(12) << std::right << "ms/call" - << "\n\n"; + os << " " << std::setw(3) << std::left << "" << std::setw(7) << std::right + << "(self)" << std::setw(13) << std::right << "(sec)" << std::setw(13) + << std::right << "(sec)" << std::setw(13) << std::right << "(sec)" + << std::setw(15) << std::right << "" << std::setw(12) << std::right + << "ms/call" << std::setw(12) << std::right << "ms/call\n\n"; // Find the highest walltime in table_, which should be the total runtime of // the program. This is used later when calculating '% Time'. - double top_walltime = std::max_element - ( - std::begin(hashvec), std::end(hashvec), - [] (auto a, auto b) { - return a.total_walltime_ < b.total_walltime_; - } - )->total_walltime_.count(); + double top_walltime = + std::max_element( + std::begin(hashvec), std::end(hashvec), + [](auto a, auto b) { return a.total_walltime_ < b.total_walltime_; }) + ->total_walltime_.count(); // Declare any variables external to RegionRecord - int region_number = 0; - double percent_time; + int region_number = 0; + double percent_time; time_duration_t cumul_walltime = time_duration_t::zero(); - double self_per_call; - double total_per_call; - - // + double self_per_call; + double total_per_call; + + // // Write data to file - // + // os << std::fixed << std::showpoint << std::setprecision(3); - for (auto const& record : hashvec) { + for (auto const &record : hashvec) { // Calculate non-RegionRecord data region_number++; - percent_time = 100.0 * ( record.self_walltime_.count() / top_walltime ); + percent_time = 100.0 * (record.self_walltime_.count() / top_walltime); cumul_walltime += record.self_walltime_; - self_per_call = 1000.0 * ( record.self_walltime_.count() / static_cast(record.call_count_) ); - total_per_call = 1000.0 * ( record.total_walltime_.count() / static_cast(record.call_count_) ); - - // Write everything out - os - << " " - << std::setw(3) << std::left << region_number - << std::setw(7) << std::right << percent_time - << std::setw(13) << std::right << cumul_walltime.count() - << std::setw(13) << std::right << record.self_walltime_.count() - << std::setw(13) << std::right << record.total_walltime_.count() - << std::setw(15) << std::right << record.call_count_ - << std::setw(12) << std::right << self_per_call - << std::setw(12) << std::right << total_per_call << " " - << record.decorated_region_name_ << "\n"; + self_per_call = 1000.0 * (record.self_walltime_.count() / + static_cast(record.call_count_)); + total_per_call = 1000.0 * (record.total_walltime_.count() / + static_cast(record.call_count_)); + + // Write everything out + os << " " << std::setw(3) << std::left << region_number << std::setw(7) + << std::right << percent_time << std::setw(13) << std::right + << cumul_walltime.count() << std::setw(13) << std::right + << record.self_walltime_.count() << std::setw(13) << std::right + << record.total_walltime_.count() << std::setw(15) << std::right + << record.call_count_ << std::setw(12) << std::right << self_per_call + << std::setw(12) << std::right << total_per_call << " " + << record.decorated_region_name_ << "\n"; } - } diff --git a/src/c++/formatter.h b/src/c++/formatter.h index 36274f7b..41e203fe 100644 --- a/src/c++/formatter.h +++ b/src/c++/formatter.h @@ -18,13 +18,12 @@ #include #ifdef _OPENMP - #include +#include #endif #include "hashvec.h" -namespace meto -{ +namespace meto { /** * @brief Formatter class. Methods write profile data. @@ -35,26 +34,22 @@ namespace meto class Formatter { - private: +private: + // Format method + void (Formatter::*format_)(std::ofstream &, hashvec_t); - // Format method - void (Formatter::*format_)(std::ofstream&, hashvec_t); + // Individual formatter functions + void threads(std::ofstream &os, hashvec_t); + void drhook(std::ofstream &os, hashvec_t); - // Individual formatter functions - void threads(std::ofstream& os, hashvec_t); - void drhook (std::ofstream& os, hashvec_t); +public: + // Constructor + explicit Formatter(); - public: - - // Constructor - explicit Formatter(); - - // Execute the format method - void execute_format(std::ofstream& os, hashvec_t); - + // Execute the format method + void execute_format(std::ofstream &os, hashvec_t); }; -} // End meto namespace +} // namespace meto #endif - diff --git a/src/c++/hashtable.cpp b/src/c++/hashtable.cpp index 6ce38af3..0c7c74fa 100644 --- a/src/c++/hashtable.cpp +++ b/src/c++/hashtable.cpp @@ -5,15 +5,14 @@ \*----------------------------------------------------------------------------*/ #include "hashtable.h" -#include "hashvec_handler.h" #include "error_handler.h" +#include "hashvec_handler.h" #include #include +#include #include #include -#include -#include #define PROF_HASHVEC_RESERVE_SIZE 1000 #define PROF_STRING_BUFFER_LENGTH 100 @@ -24,9 +23,7 @@ * */ -meto::HashTable::HashTable(int const tid) - : tid_(tid) -{ +meto::HashTable::HashTable(int const tid) : tid_(tid) { // Reserve enough places in hashvec_ hashvec_.reserve(PROF_HASHVEC_RESERVE_SIZE); @@ -35,50 +32,48 @@ meto::HashTable::HashTable(int const tid) // Insert special entry for the profiler overhead time. query_insert(profiler_name, tid, profiler_hash_, profiler_index_); - } /** * @brief Decorates a region name with the thread ID and computes the * corresponding hash. - * + * * @param [in] region_name The code region name. * @param [in] tid The thread ID * - * @returns Returns a hash based on the input arguments. - * + * @returns Returns a hash based on the input arguments. + * * @note The integer thread ID is not converted to a string before it is * appended to the hash string. This is a performance measure. * Conversions to strings are expensive and not strictly necessary. * Since the physical bit pattern is unique for each integer, that * will do the job. The hash function input does not need to be * human-readable. - * + * */ -size_t meto::HashTable::compute_hash(std::string_view region_name, int tid) -{ +size_t meto::HashTable::compute_hash(std::string_view region_name, int tid) { // Get the bit-pattern of the thread ID. std::array tid_bytes; std::memcpy(tid_bytes.data(), &tid, sizeof(tid)); - [[maybe_unused]] int const* tid_back = reinterpret_cast(tid_bytes.data()); - assert (*tid_back == tid); + [[maybe_unused]] int const *tid_back = + reinterpret_cast(tid_bytes.data()); + assert(*tid_back == tid); - // Extra bytes to accommodate the thread ID. + // Extra bytes to accommodate the thread ID. unsigned int constexpr num_extra_bytes = sizeof(tid); // Avoid dynamic memory allocation for performance reasons. Instead, fix the // size of the buffer and perform a runtime check that we're not exceeding it. - std::array new_chars; + std::array new_chars; new_chars.fill('\0'); if (region_name.length() + num_extra_bytes > new_chars.size()) { error_handler("Internal error: character buffer exhausted.", EXIT_FAILURE); } - // Get iterator to the start of the string buffer. auto new_chars_iterator = new_chars.begin(); @@ -92,16 +87,16 @@ size_t meto::HashTable::compute_hash(std::string_view region_name, int tid) // Compute the length of the character array based on the current position of // the iterator. - auto new_chars_size = std::distance(new_chars.begin(), new_chars_iterator); + auto new_chars_size = std::distance(new_chars.begin(), new_chars_iterator); // Check that the character string is the length which were expecting. - [[maybe_unused]] auto const expected_size = - static_cast(region_name.length()) + num_extra_bytes; - assert (new_chars_size == expected_size); - - return hash_function_(std::string_view(new_chars.data(), - static_cast(new_chars_size))); + [[maybe_unused]] auto const expected_size = + static_cast(region_name.length()) + num_extra_bytes; + assert(new_chars_size == expected_size); + return hash_function_(std::string_view( + new_chars.data(), + static_cast(new_chars_size))); } /** @@ -113,56 +108,49 @@ size_t meto::HashTable::compute_hash(std::string_view region_name, int tid) * */ -void meto::HashTable::query_insert(std::string_view const region_name, - int tid, - size_t& hash, - record_index_t& record_index) noexcept -{ +void meto::HashTable::query_insert(std::string_view const region_name, int tid, + size_t &hash, + record_index_t &record_index) noexcept { // Compute the hash hash = compute_hash(region_name, tid); // Does the entry exist already? - if (auto search = lookup_table_.find(hash); search != lookup_table_.end()) - { + if (auto search = lookup_table_.find(hash); search != lookup_table_.end()) { record_index = search->second; } - + // If not, create new entry. - else - { + else { // Insert this region into the thread's hash table. hashvec_.emplace_back(hash, region_name, tid); - record_index = hashvec_.size()-1; + record_index = hashvec_.size() - 1; lookup_table_.emplace(hash, record_index); - assert (lookup_table_.count(hash) > 0); + assert(lookup_table_.count(hash) > 0); } } /** - * @brief Updates the total walltime and call count for the specified region. + * @brief Updates the total walltime and call count for the specified region. * @param [in] record_index The index in hashvec_ corresponding to the * profiled region. * @param [in] time_delta The time increment to add. */ void meto::HashTable::update(record_index_t const record_index, - time_duration_t const time_delta) -{ + time_duration_t const time_delta) { - auto& record = hashvec_[record_index]; + auto &record = hashvec_[record_index]; // Increment the walltime for this hash entry. If this region has been called // recursively, directly or indirectly, the time goes into a different bucket. - if (record.recursion_level_ > 0){ + if (record.recursion_level_ > 0) { record.recursion_total_walltime_ += time_delta; - } - else{ + } else { record.total_walltime_ += time_delta; } // Update the number of times this region has been called ++record.call_count_; - } /** @@ -170,20 +158,20 @@ void meto::HashTable::update(record_index_t const record_index, * @param [in] record_index The index corresponding to the region record. */ -void meto::HashTable::increment_recursion_level(record_index_t const record_index) -{ - auto& record = hashvec_[record_index]; +void meto::HashTable::increment_recursion_level( + record_index_t const record_index) { + auto &record = hashvec_[record_index]; ++record.recursion_level_; } /** - * @brief Decrements by 1 the recursion level in a region record. + * @brief Decrements by 1 the recursion level in a region record. * @param [in] record_index The index corresponding to the region record. */ -void meto::HashTable::decrement_recursion_level(record_index_t const record_index) -{ - auto& record = hashvec_[record_index]; +void meto::HashTable::decrement_recursion_level( + record_index_t const record_index) { + auto &record = hashvec_[record_index]; --record.recursion_level_; } @@ -198,11 +186,9 @@ void meto::HashTable::decrement_recursion_level(record_index_t const record_inde */ void meto::HashTable::add_child_time_to_parent( - record_index_t const parent_index, - time_duration_t const child_walltime, - time_duration_t*& overhead_time_ptr) -{ - auto& record = hashvec_[parent_index]; + record_index_t const parent_index, time_duration_t const child_walltime, + time_duration_t *&overhead_time_ptr) { + auto &record = hashvec_[parent_index]; record.child_walltime_ += child_walltime; overhead_time_ptr = &record.overhead_walltime_; } @@ -217,8 +203,8 @@ void meto::HashTable::add_child_time_to_parent( * calls. */ -void meto::HashTable::add_profiler_call(time_duration_t*& overhead_time_ptr) { - auto& record = hashvec_[profiler_index_]; +void meto::HashTable::add_profiler_call(time_duration_t *&overhead_time_ptr) { + auto &record = hashvec_[profiler_index_]; ++record.call_count_; overhead_time_ptr = &record.total_walltime_; } @@ -228,17 +214,15 @@ void meto::HashTable::add_profiler_call(time_duration_t*& overhead_time_ptr) { * and updates the hashtable with the new indices. */ -void meto::HashTable::sort_records() -{ +void meto::HashTable::sort_records() { // Sort the entries according to self walltime. std::sort(begin(hashvec_), end(hashvec_), - [](auto a, auto b) { return a.self_walltime_ > b.self_walltime_;}); + [](auto a, auto b) { return a.self_walltime_ > b.self_walltime_; }); // Need to re-store the indices in the lookup table, since they will have all // moved around as a result of the above sort. sync_lookup(); - } /** @@ -250,15 +234,12 @@ void meto::HashTable::sort_records() * @param [inout] record The region record to compute. */ -void meto::HashTable::prepare_computed_times(RegionRecord& record) -{ +void meto::HashTable::prepare_computed_times(RegionRecord &record) { // Self time - record.self_walltime_ = record.total_walltime_ - + record.recursion_total_walltime_ - - record.child_walltime_ - - record.overhead_walltime_; - + record.self_walltime_ = record.total_walltime_ + + record.recursion_total_walltime_ - + record.child_walltime_ - record.overhead_walltime_; } /** @@ -266,14 +247,12 @@ void meto::HashTable::prepare_computed_times(RegionRecord& record) * code regions. */ -void meto::HashTable::prepare_computed_times_all() -{ +void meto::HashTable::prepare_computed_times_all() { // Loop over entries in the hashtable. - for (auto& [hash, index] : lookup_table_) { + for (auto &[hash, index] : lookup_table_) { prepare_computed_times(hash2record(hash)); } - } /** @@ -281,41 +260,38 @@ void meto::HashTable::prepare_computed_times_all() * */ -std::vector meto::HashTable::list_keys() -{ +std::vector meto::HashTable::list_keys() { std::vector keys; - for (auto const& key : lookup_table_) - { + for (auto const &key : lookup_table_) { keys.push_back(key.first); } return keys; } /** - * @brief Appends table_ onto the end of an input hashvec. + * @brief Appends table_ onto the end of an input hashvec. * @param[inout] hashvec_handler HashVecHandler object containing the * hashvec to amend. - * + * */ -void meto::HashTable::append_to(HashVecHandler& hashvec_handler) -{ +void meto::HashTable::append_to(HashVecHandler &hashvec_handler) { // Compute overhead and self times before appending prepare_computed_times_all(); // Loop over entries in the hashtable. - for (auto& [hash, index] : lookup_table_) { + for (auto &[hash, index] : lookup_table_) { prepare_computed_times(hash2record(hash)); } // Erase profiler entry if call count is zero. - if(hash2record(profiler_hash_).call_count_ == 0) { + if (hash2record(profiler_hash_).call_count_ == 0) { erase_record(profiler_hash_); } // Sync-up the lookup table and hashvec. sync_lookup(); - + // Append hashvec to that passed through the argument list. hashvec_handler.append(hashvec_); } @@ -326,21 +302,19 @@ void meto::HashTable::append_to(HashVecHandler& hashvec_handler) * */ -void meto::HashTable::erase_record(size_t const hash) -{ +void meto::HashTable::erase_record(size_t const hash) { // Find the lookup table (hashtable) iterator. - auto iterator = lookup_table_.find(hash); + auto iterator = lookup_table_.find(hash); auto const index = lookup_table_.at(hash); // Get the hashvec iterator from the index auto record_iterator = begin(hashvec_); - std::advance( record_iterator, index); + std::advance(record_iterator, index); // Erase from both the hashvec and the lookup table. hashvec_.erase(record_iterator); lookup_table_.erase(iterator); - } /** @@ -348,13 +322,13 @@ void meto::HashTable::erase_record(size_t const hash) * */ -void meto::HashTable::sync_lookup() -{ +void meto::HashTable::sync_lookup() { // Need to re-store the indices in the lookup table, since there will be a gap // as a result of the erase(). for (auto it = begin(hashvec_); it != end(hashvec_); ++it) { auto current_index = it - hashvec_.begin(); - lookup_table_[it->region_hash_] = static_cast(current_index); + lookup_table_[it->region_hash_] = + static_cast(current_index); } } @@ -365,35 +339,33 @@ void meto::HashTable::sync_lookup() * */ -double meto::HashTable::get_total_walltime(size_t const hash) const -{ - auto& record = hash2record(hash); +double meto::HashTable::get_total_walltime(size_t const hash) const { + auto &record = hash2record(hash); return record.total_walltime_.count(); } /** * @brief Get the profiling overhead time for a specified region, as incurred - * by calling direct children. + * by calling direct children. * @param [in] hash The hash corresponding to the region. */ -double meto::HashTable::get_overhead_walltime(size_t const hash) const -{ - auto& record = hash2record(hash); +double meto::HashTable::get_overhead_walltime(size_t const hash) const { + auto &record = hash2record(hash); return record.overhead_walltime_.count(); } /** - * @brief Get the profiler self (exclusive) time corresponding to the input hash. + * @brief Get the profiler self (exclusive) time corresponding to the input + * hash. * @param [in] hash The hash corresponding to the region. * @note This time is derived from other measured times, therefore a to - * `prepare_computed_times` is need to update its value. + * `prepare_computed_times` is need to update its value. */ -double meto::HashTable::get_self_walltime(size_t const hash) -{ - auto& record = hash2record(hash); +double meto::HashTable::get_self_walltime(size_t const hash) { + auto &record = hash2record(hash); prepare_computed_times(record); return record.self_walltime_.count(); } @@ -402,12 +374,11 @@ double meto::HashTable::get_self_walltime(size_t const hash) * @brief Get the child time corresponding to the input hash. * @param [in] hash The hash corresponding to the region. * @note This time is derived from other measured times, therefore a to - * `prepare_computed_times` is need to update its value. + * `prepare_computed_times` is need to update its value. */ -double meto::HashTable::get_child_walltime(size_t const hash) const -{ - auto& record = hash2record(hash); +double meto::HashTable::get_child_walltime(size_t const hash) const { + auto &record = hash2record(hash); return record.child_walltime_.count(); } @@ -416,9 +387,9 @@ double meto::HashTable::get_child_walltime(size_t const hash) const * @param [in] hash The hash corresponding to the region. */ -std::string meto::HashTable::get_decorated_region_name(size_t const hash) const -{ - auto& record = hash2record(hash); +std::string +meto::HashTable::get_decorated_region_name(size_t const hash) const { + auto &record = hash2record(hash); return record.decorated_region_name_; } @@ -432,9 +403,9 @@ std::string meto::HashTable::get_decorated_region_name(size_t const hash) const * */ -unsigned long long int meto::HashTable::get_call_count(size_t const hash) const -{ - auto& record = hash2record(hash); +unsigned long long int +meto::HashTable::get_call_count(size_t const hash) const { + auto &record = hash2record(hash); return record.call_count_; } @@ -442,15 +413,14 @@ unsigned long long int meto::HashTable::get_call_count(size_t const hash) const * @brief Get the number of calliper pairs called. * * @returns Returns an integer corresponding to the number of the times pairs - * of callipers have been called. - * + * of callipers have been called. + * */ -unsigned long long int meto::HashTable::get_prof_call_count() const -{ - auto& record = hash2record(profiler_hash_); - assert (lookup_table_.count(profiler_hash_) > 0); - return record.call_count_; +unsigned long long int meto::HashTable::get_prof_call_count() const { + auto &record = hash2record(profiler_hash_); + assert(lookup_table_.count(profiler_hash_) > 0); + return record.call_count_; } /** @@ -460,8 +430,7 @@ unsigned long long int meto::HashTable::get_prof_call_count() const * */ -meto::RegionRecord& meto::HashTable::hash2record(size_t const hash) -{ +meto::RegionRecord &meto::HashTable::hash2record(size_t const hash) { return hashvec_[lookup_table_.at(hash)]; } @@ -473,9 +442,7 @@ meto::RegionRecord& meto::HashTable::hash2record(size_t const hash) * */ -meto::RegionRecord const& meto::HashTable::hash2record(size_t const hash) const -{ +meto::RegionRecord const & +meto::HashTable::hash2record(size_t const hash) const { return hashvec_[lookup_table_.at(hash)]; } - - diff --git a/src/c++/hashtable.h b/src/c++/hashtable.h index 7c534a01..a3a3cfd7 100644 --- a/src/c++/hashtable.h +++ b/src/c++/hashtable.h @@ -28,8 +28,7 @@ #include "hashvec.h" #include "vernier_gettime.h" -namespace meto -{ +namespace meto { // Forward declarations class HashVecHandler; @@ -42,9 +41,7 @@ class HashVecHandler; */ struct NullHashFunction { - std::size_t operator()(std::size_t const& key) const { - return key; - } + std::size_t operator()(std::size_t const &key) const { return key; } }; /** @@ -55,68 +52,66 @@ struct NullHashFunction { * */ -class HashTable{ - - private: - - // Members - int tid_; - size_t profiler_hash_; - record_index_t profiler_index_; - - // Hash function - std::hash hash_function_; - - // Hashtable containing locations of region records. - std::unordered_map lookup_table_; - - // Vector of region records. - hashvec_t hashvec_; - - // Private member functions - void prepare_computed_times(RegionRecord&); - void prepare_computed_times_all(); - void sort_records(); - void erase_record(size_t const); - void sync_lookup(); - RegionRecord& hash2record(size_t const); - RegionRecord const& hash2record(size_t const) const; - - public: - - // Constructors - HashTable() = delete; - HashTable(int); - - // Prototypes - size_t compute_hash(std::string_view, int); - void query_insert(std::string_view const, int, size_t&, record_index_t&) noexcept; - void update(record_index_t const, time_duration_t const); - - // Member functions - std::vector list_keys(); - - void add_child_time_to_parent(record_index_t const, time_duration_t const, time_duration_t*&); - void add_profiler_call(time_duration_t*&); - - void compute_self_times(); - void append_to(HashVecHandler&); - - // Getters - double get_total_walltime(size_t const hash) const; - double get_overhead_walltime(size_t const hash) const; - double get_self_walltime(size_t const hash); - double get_child_walltime(size_t const hash) const; - std::string get_decorated_region_name(size_t const hash) const; - unsigned long long int get_call_count(size_t const hash) const; - unsigned long long int get_prof_call_count() const; - - void increment_recursion_level(record_index_t const); - void decrement_recursion_level(record_index_t const); - +class HashTable { + +private: + // Members + int tid_; + size_t profiler_hash_; + record_index_t profiler_index_; + + // Hash function + std::hash hash_function_; + + // Hashtable containing locations of region records. + std::unordered_map lookup_table_; + + // Vector of region records. + hashvec_t hashvec_; + + // Private member functions + void prepare_computed_times(RegionRecord &); + void prepare_computed_times_all(); + void sort_records(); + void erase_record(size_t const); + void sync_lookup(); + RegionRecord &hash2record(size_t const); + RegionRecord const &hash2record(size_t const) const; + +public: + // Constructors + HashTable() = delete; + HashTable(int); + + // Prototypes + size_t compute_hash(std::string_view, int); + void query_insert(std::string_view const, int, size_t &, + record_index_t &) noexcept; + void update(record_index_t const, time_duration_t const); + + // Member functions + std::vector list_keys(); + + void add_child_time_to_parent(record_index_t const, time_duration_t const, + time_duration_t *&); + void add_profiler_call(time_duration_t *&); + + void compute_self_times(); + void append_to(HashVecHandler &); + + // Getters + double get_total_walltime(size_t const hash) const; + double get_overhead_walltime(size_t const hash) const; + double get_self_walltime(size_t const hash); + double get_child_walltime(size_t const hash) const; + std::string get_decorated_region_name(size_t const hash) const; + unsigned long long int get_call_count(size_t const hash) const; + unsigned long long int get_prof_call_count() const; + + void increment_recursion_level(record_index_t const); + void decrement_recursion_level(record_index_t const); }; -} // End meto namespace +} // namespace meto #endif - diff --git a/src/c++/hashvec.cpp b/src/c++/hashvec.cpp index ed2ec0a2..2c28f116 100644 --- a/src/c++/hashvec.cpp +++ b/src/c++/hashvec.cpp @@ -14,20 +14,15 @@ */ meto::RegionRecord::RegionRecord(size_t const region_hash, - std::string_view const region_name, - int tid) -: region_hash_(region_hash) -, region_name_(region_name) -, total_walltime_ (time_duration_t::zero()) -, recursion_total_walltime_ (time_duration_t::zero()) -, self_walltime_ (time_duration_t::zero()) -, child_walltime_ (time_duration_t::zero()) -, overhead_walltime_ (time_duration_t::zero()) -, call_count_(0) -, recursion_level_(0) -{ + std::string_view const region_name, int tid) + : region_hash_(region_hash), region_name_(region_name), + total_walltime_(time_duration_t::zero()), + recursion_total_walltime_(time_duration_t::zero()), + self_walltime_(time_duration_t::zero()), + child_walltime_(time_duration_t::zero()), + overhead_walltime_(time_duration_t::zero()), call_count_(0), + recursion_level_(0) { decorated_region_name_ = region_name_; decorated_region_name_ += '@'; decorated_region_name_ += std::to_string(tid); } - diff --git a/src/c++/hashvec.h b/src/c++/hashvec.h index 7e9a53da..b9c53b8e 100644 --- a/src/c++/hashvec.h +++ b/src/c++/hashvec.h @@ -19,8 +19,7 @@ #include "vernier_gettime.h" -namespace meto -{ +namespace meto { /** * @brief Structure to hold information for a particular region. @@ -30,24 +29,22 @@ namespace meto */ struct RegionRecord { - public: - - // Constructor - RegionRecord() = delete; - explicit RegionRecord(size_t const, std::string_view const, int); - - // Data members - size_t region_hash_; - std::string region_name_; - std::string decorated_region_name_; - time_duration_t total_walltime_; - time_duration_t recursion_total_walltime_; - time_duration_t self_walltime_; - time_duration_t child_walltime_; - time_duration_t overhead_walltime_; - unsigned long long int call_count_; - unsigned int recursion_level_; - +public: + // Constructor + RegionRecord() = delete; + explicit RegionRecord(size_t const, std::string_view const, int); + + // Data members + size_t region_hash_; + std::string region_name_; + std::string decorated_region_name_; + time_duration_t total_walltime_; + time_duration_t recursion_total_walltime_; + time_duration_t self_walltime_; + time_duration_t child_walltime_; + time_duration_t overhead_walltime_; + unsigned long long int call_count_; + unsigned int recursion_level_; }; // Define the hashvec type. @@ -56,7 +53,6 @@ using hashvec_t = std::vector; // Type definitions using record_index_t = std::vector::size_type; -} // End meto namespace +} // namespace meto #endif - diff --git a/src/c++/hashvec_handler.cpp b/src/c++/hashvec_handler.cpp index b5ae05c9..46ecf45c 100644 --- a/src/c++/hashvec_handler.cpp +++ b/src/c++/hashvec_handler.cpp @@ -13,28 +13,27 @@ * @param [in] mpi_context The MPI context to use. * * @note Allocates the writer strategy based on the PROF_IO_MODE environment - * variable. + * variable. * */ -meto::HashVecHandler::HashVecHandler(MPIContext const& mpi_context) -{ +meto::HashVecHandler::HashVecHandler(MPIContext const &mpi_context) { - // Default the IO mode to one file per MPI rank. - std::string io_mode = "multi"; + // Default the IO mode to one file per MPI rank. + std::string io_mode = "multi"; - // Read environment variable. - char const* env_io_mode = std::getenv("VERNIER_OUTPUT_MODE"); - if (env_io_mode) { io_mode = env_io_mode; } + // Read environment variable. + char const *env_io_mode = std::getenv("VERNIER_OUTPUT_MODE"); + if (env_io_mode) { + io_mode = env_io_mode; + } - // Allocate writer to be of required type. - if (io_mode == "multi") - { - writer_strategy_ = std::make_unique(mpi_context); - } - else { - error_handler("Invalid IO mode choice", EXIT_FAILURE); - } + // Allocate writer to be of required type. + if (io_mode == "multi") { + writer_strategy_ = std::make_unique(mpi_context); + } else { + error_handler("Invalid IO mode choice", EXIT_FAILURE); + } } /** @@ -43,8 +42,7 @@ meto::HashVecHandler::HashVecHandler(MPIContext const& mpi_context) * */ -void meto::HashVecHandler::append(hashvec_t const& append_hashvec) -{ +void meto::HashVecHandler::append(hashvec_t const &append_hashvec) { hashvec_.insert(hashvec_.end(), append_hashvec.begin(), append_hashvec.end()); } @@ -53,15 +51,9 @@ void meto::HashVecHandler::append(hashvec_t const& append_hashvec) * */ -void meto::HashVecHandler::sort() -{ - std::sort - ( - begin(hashvec_), end(hashvec_), - [] (auto a, auto b) { - return a.self_walltime_ > b.self_walltime_; - } - ); +void meto::HashVecHandler::sort() { + std::sort(begin(hashvec_), end(hashvec_), + [](auto a, auto b) { return a.self_walltime_ > b.self_walltime_; }); } /** @@ -69,9 +61,7 @@ void meto::HashVecHandler::sort() * */ -void meto::HashVecHandler::write() -{ - std::ofstream os; - writer_strategy_->write(os, hashvec_); +void meto::HashVecHandler::write() { + std::ofstream os; + writer_strategy_->write(os, hashvec_); } - diff --git a/src/c++/hashvec_handler.h b/src/c++/hashvec_handler.h index 154b5e87..1c5d3a1d 100644 --- a/src/c++/hashvec_handler.h +++ b/src/c++/hashvec_handler.h @@ -19,15 +19,14 @@ #include "hashvec.h" #include "mpi_context.h" -#include "writer/writer.h" #include "writer/multi.h" +#include "writer/writer.h" -namespace meto -{ +namespace meto { /** * @brief HashVecHandler class - * + * * @details The HashVecHandler contains a hashvec vector as a data member. * It wraps this vector with additional functionality to sort entries * and set a writer strategy based on the PROF_IO_MODE environment @@ -37,27 +36,23 @@ namespace meto class HashVecHandler { - private: +private: + // Vector of hash entries. + hashvec_t hashvec_; - // Vector of hash entries. - hashvec_t hashvec_; + // Writer strategy + std::unique_ptr writer_strategy_; - // Writer strategy - std::unique_ptr writer_strategy_; - - public: +public: + // Constructor + HashVecHandler(MPIContext const &); - // Constructor - HashVecHandler(MPIContext const&); - - // Member functions - void sort(); - void write(); - void append(hashvec_t const&); - + // Member functions + void sort(); + void write(); + void append(hashvec_t const &); }; -} // End meto namespace +} // namespace meto #endif - diff --git a/src/c++/mpi_context.cpp b/src/c++/mpi_context.cpp index 650cdff8..a36a4216 100644 --- a/src/c++/mpi_context.cpp +++ b/src/c++/mpi_context.cpp @@ -5,7 +5,6 @@ * ----------------------------------------------------------------------------- */ - #include #include @@ -17,22 +16,18 @@ * @details This constructor does not initialise MPI. */ -meto::MPIContext::MPIContext() -{ - reset(); -} +meto::MPIContext::MPIContext() { reset(); } /** * @brief Resets data members to sensible null values. - * + * */ -void meto::MPIContext::reset() -{ - comm_handle_ = MPI_COMM_NULL; - comm_rank_ = -1; - comm_size_ = -1; - initialized_ = false; +void meto::MPIContext::reset() { + comm_handle_ = MPI_COMM_NULL; + comm_rank_ = -1; + comm_size_ = -1; + initialized_ = false; } /** @@ -41,13 +36,12 @@ void meto::MPIContext::reset() * @note Duplicates the input MPI communicator. */ -void meto::MPIContext::init(MPI_Comm client_comm_handle) -{ +void meto::MPIContext::init(MPI_Comm client_comm_handle) { // Check that the storage is correctly null first. assert(comm_handle_ == MPI_COMM_NULL); - assert(comm_rank_ == -1); - assert(comm_size_ == -1); + assert(comm_rank_ == -1); + assert(comm_size_ == -1); int mpi_is_initialised; MPI_Initialized(&mpi_is_initialised); @@ -56,14 +50,15 @@ void meto::MPIContext::init(MPI_Comm client_comm_handle) // If MPI is initialised, then the passed communicator should not be null. if (client_comm_handle == MPI_COMM_NULL) { - meto::error_handler("MPIContext::init. MPI initialized, but null communicator passed.", EXIT_FAILURE); + meto::error_handler( + "MPIContext::init. MPI initialized, but null communicator passed.", + EXIT_FAILURE); } MPI_Comm_dup(client_comm_handle, &comm_handle_); MPI_Comm_rank(comm_handle_, &comm_rank_); MPI_Comm_size(comm_handle_, &comm_size_); - } - else { + } else { meto::error_handler("MPIContext::init. MPI not initialized.", EXIT_FAILURE); } @@ -81,8 +76,7 @@ void meto::MPIContext::init(MPI_Comm client_comm_handle) * @returns Boolean initialisation status. */ -bool meto::MPIContext::is_initialized() -{ +bool meto::MPIContext::is_initialized() { // Returning local_initialized ought to be sufficient. Belt and braces. bool local_initialized = initialized_; return local_initialized; @@ -91,15 +85,13 @@ bool meto::MPIContext::is_initialized() /** * @brief Finaliser for a Vernier MPI context. * @note Since the constructor duplicated an MPI communicator, creating a new - * communicator handle in the process, this destructor needs to free that - * communicator handle. + * communicator handle in the process, this destructor needs to free + * that communicator handle. */ -void meto::MPIContext::finalize() -{ - if (comm_handle_ != MPI_COMM_WORLD && - comm_handle_ != MPI_COMM_NULL){ - MPI_Comm_free(&comm_handle_); +void meto::MPIContext::finalize() { + if (comm_handle_ != MPI_COMM_WORLD && comm_handle_ != MPI_COMM_NULL) { + MPI_Comm_free(&comm_handle_); } reset(); @@ -110,18 +102,11 @@ void meto::MPIContext::finalize() * @returns The MPI rank. */ -int meto::MPIContext::get_rank() -{ - return comm_rank_; -} +int meto::MPIContext::get_rank() { return comm_rank_; } /** * @brief Gets the size of the MPI communicator from an MPIContext object. * @returns The MPI communicator size. */ -int meto::MPIContext::get_size() -{ - return comm_size_; -} - +int meto::MPIContext::get_size() { return comm_size_; } diff --git a/src/c++/mpi_context.h b/src/c++/mpi_context.h index b604458b..77c6d94d 100644 --- a/src/c++/mpi_context.h +++ b/src/c++/mpi_context.h @@ -7,7 +7,7 @@ /** * @file mpi_context.h * @brief Defines an MPIContext class. - * + * * In order to reduce the proliferation of MPI throughout the codebase, and to * ensure that required information - such as MPI rank - is available at * appropriate levels in the code, we define an MPIContext class which we know @@ -21,42 +21,38 @@ #include #include "hashvec.h" -#include "vernier_mpi.h" #include "vernier_gettime.h" +#include "vernier_mpi.h" -namespace meto -{ +namespace meto { /** * @brief Provides a wrapper for MPI functionality. */ - class MPIContext { - - private: +class MPIContext { - MPI_Comm comm_handle_; - int comm_size_; - int comm_rank_; - bool initialized_; - - public: +private: + MPI_Comm comm_handle_; + int comm_size_; + int comm_rank_; + bool initialized_; - // Constructor - MPIContext(); +public: + // Constructor + MPIContext(); - // Init and finalize - bool is_initialized(); - void init(MPI_Comm); - void finalize(); - void reset(); + // Init and finalize + bool is_initialized(); + void init(MPI_Comm); + void finalize(); + void reset(); - // Getters - int get_size(); - int get_rank(); - - }; + // Getters + int get_size(); + int get_rank(); +}; -} // End meto namespace +} // namespace meto #endif diff --git a/src/c++/vernier.cpp b/src/c++/vernier.cpp index 183345d3..4faab281 100644 --- a/src/c++/vernier.cpp +++ b/src/c++/vernier.cpp @@ -4,15 +4,15 @@ under which the code may be used. \*----------------------------------------------------------------------------*/ -#include "hashvec_handler.h" #include "vernier.h" #include "error_handler.h" +#include "hashvec_handler.h" #include #include #include #ifdef _OPENMP - #include +#include #endif // Initialize static data members. @@ -31,25 +31,21 @@ meto::time_point_t meto::Vernier::logged_calliper_start_time_{}; */ meto::Vernier::TracebackEntry::TracebackEntry( - size_t record_hash, - meto::record_index_t record_index, - meto::time_point_t region_start_time, - meto::time_point_t calliper_start_time) - : record_hash_ (record_hash) - , record_index_ (record_index) - , region_start_time_ (region_start_time) - , calliper_start_time_(calliper_start_time) - {} + size_t record_hash, meto::record_index_t record_index, + meto::time_point_t region_start_time, + meto::time_point_t calliper_start_time) + : record_hash_(record_hash), record_index_(record_index), + region_start_time_(region_start_time), + calliper_start_time_(calliper_start_time) {} /** * @brief Initialise Vernier object. * @param [in] client_comm_handle MPI communicator handle that Vernier will * duplicate and use the duplicate. * Defaults to MPI_COMM_WORLD. - */ + */ -void meto::Vernier::init(MPI_Comm const client_comm_handle) -{ +void meto::Vernier::init(MPI_Comm const client_comm_handle) { // Set the maximum number of threads. max_threads_ = 1; @@ -58,8 +54,7 @@ void meto::Vernier::init(MPI_Comm const client_comm_handle) #endif // Create vector of hash tables: one hashtable for each thread. - for (int tid=0; tid new_list; thread_traceback_.push_back(new_list); - } // Initialise MPI context @@ -78,22 +72,20 @@ void meto::Vernier::init(MPI_Comm const client_comm_handle) initialized_ = true; // Assertions - assert ( static_cast (thread_hashtables_.size()) == max_threads_); - assert ( static_cast (thread_traceback_.size() ) == max_threads_); - assert ( mpi_context_.is_initialized() ); - assert ( initialized_ ); - + assert(static_cast(thread_hashtables_.size()) == max_threads_); + assert(static_cast(thread_traceback_.size()) == max_threads_); + assert(mpi_context_.is_initialized()); + assert(initialized_); } /** * @brief Finalize Vernier object. * @note Clears hashtable and traceback information; frees duplicate * MPI communicator. - */ + */ -void meto::Vernier::finalize() -{ - if(mpi_context_.is_initialized()){ +void meto::Vernier::finalize() { + if (mpi_context_.is_initialized()) { mpi_context_.finalize(); } @@ -105,10 +97,10 @@ void meto::Vernier::finalize() initialized_ = false; // Assertions - assert ( static_cast (thread_hashtables_.size()) == 0); - assert ( static_cast (thread_traceback_.size() ) == 0); - assert ( !mpi_context_.is_initialized() ); - assert ( !initialized_ ); + assert(static_cast(thread_hashtables_.size()) == 0); + assert(static_cast(thread_traceback_.size()) == 0); + assert(!mpi_context_.is_initialized()); + assert(!initialized_); } /** @@ -118,8 +110,7 @@ void meto::Vernier::finalize() * @returns Unique hash for the code region being started. */ -size_t meto::Vernier::start(std::string_view const region_name) -{ +size_t meto::Vernier::start(std::string_view const region_name) { start_part1(); auto hash = start_part2(region_name); return hash; @@ -130,12 +121,12 @@ size_t meto::Vernier::start(std::string_view const region_name) * threadprivate note of the time. */ -void meto::Vernier::start_part1() -{ +void meto::Vernier::start_part1() { // Check that Vernier has been initialised if (!initialized_) { - meto::error_handler("Vernier::start_part1. Vernier not initialised.", EXIT_FAILURE); + meto::error_handler("Vernier::start_part1. Vernier not initialised.", + EXIT_FAILURE); } // Store the calliper start time, which is used in part2. @@ -148,8 +139,7 @@ void meto::Vernier::start_part1() * @returns Unique hash for the code region being started. */ -size_t meto::Vernier::start_part2(std::string_view const region_name) -{ +size_t meto::Vernier::start_part2(std::string_view const region_name) { // Determine the thread number auto tid = static_cast(0); #ifdef _OPENMP @@ -157,23 +147,23 @@ size_t meto::Vernier::start_part2(std::string_view const region_name) #endif auto tid_int = static_cast(tid); - assert (tid <= thread_hashtables_.size()); - assert (tid <= thread_traceback_.size()); + assert(tid <= thread_hashtables_.size()); + assert(tid <= thread_traceback_.size()); size_t hash; record_index_t record_index; - thread_hashtables_[tid].query_insert(region_name, tid_int, hash, record_index); + thread_hashtables_[tid].query_insert(region_name, tid_int, hash, + record_index); thread_hashtables_[tid].increment_recursion_level(record_index); // Store the calliper and region start times. ++call_depth_; - if (call_depth_ < PROF_MAX_TRACEBACK_SIZE){ + if (call_depth_ < PROF_MAX_TRACEBACK_SIZE) { auto call_depth_index = static_cast(call_depth_); auto region_start_time = vernier_gettime(); - thread_traceback_[tid].at(call_depth_index) - = TracebackEntry(hash, record_index, region_start_time, logged_calliper_start_time_); - } - else { + thread_traceback_[tid].at(call_depth_index) = TracebackEntry( + hash, record_index, region_start_time, logged_calliper_start_time_); + } else { error_handler("EMERGENCY STOP: Traceback array exhausted.", EXIT_FAILURE); } return hash; @@ -183,14 +173,13 @@ size_t meto::Vernier::start_part2(std::string_view const region_name) * @brief Stop timing a profiled code region. * @param [in] hash Hash of the profiled code region being stopped. * @note The calliper time (spent in the profiler) is measured by - * differencing the beginning of the start calliper from the end of the stop - * calliper, and subtracting the measured region time. Hence larger + * differencing the beginning of the start calliper from the end of the + * stop calliper, and subtracting the measured region time. Hence larger * absolute times are being measured, which are less likely to suffer * fractional error from precision limitations of the clock. */ -void meto::Vernier::stop(size_t const hash) -{ +void meto::Vernier::stop(size_t const hash) { // Log the region stop time. auto region_stop_time = vernier_gettime(); @@ -204,17 +193,22 @@ void meto::Vernier::stop(size_t const hash) // Check that we have called a start calliper before the stop calliper. // If not, then the call depth would be -1. if (call_depth_ < 0) { - error_handler("EMERGENCY STOP: stop called before start calliper.", EXIT_FAILURE); + error_handler("EMERGENCY STOP: stop called before start calliper.", + EXIT_FAILURE); } // Get reference to the traceback entry. auto call_depth_index = static_cast(call_depth_); - auto& traceback_entry = thread_traceback_[tid].at(call_depth_index); + auto &traceback_entry = thread_traceback_[tid].at(call_depth_index); // Check: which hash is last on the traceback list? size_t last_hash_on_list = traceback_entry.record_hash_; - if (hash != last_hash_on_list){ - std::string error_msg = "EMERGENCY STOP: hashes don't match. Expected calliper: " + thread_hashtables_[tid].get_decorated_region_name(last_hash_on_list) + " Received calliper: " + thread_hashtables_[tid].get_decorated_region_name(hash) + "\n"; + if (hash != last_hash_on_list) { + std::string error_msg = + "EMERGENCY STOP: hashes don't match. Expected calliper: " + + thread_hashtables_[tid].get_decorated_region_name(last_hash_on_list) + + " Received calliper: " + + thread_hashtables_[tid].get_decorated_region_name(hash) + "\n"; error_handler(error_msg, EXIT_FAILURE); } @@ -222,8 +216,10 @@ void meto::Vernier::stop(size_t const hash) auto region_duration = region_stop_time - traceback_entry.region_start_time_; // Do the hashtable update for the child region. - thread_hashtables_[tid].decrement_recursion_level(traceback_entry.record_index_); - thread_hashtables_[tid].update(traceback_entry.record_index_, region_duration); + thread_hashtables_[tid].decrement_recursion_level( + traceback_entry.record_index_); + thread_hashtables_[tid].update(traceback_entry.record_index_, + region_duration); // Precompute times as far as possible. We just need the calliper stop time // later. @@ -234,16 +230,16 @@ void meto::Vernier::stop(size_t const hash) // The sequence of code that follows is aimed at leaving only minimal and // simple operations after the call to vernier_gettime(). - time_duration_t* parent_overhead_time_ptr = nullptr; - time_duration_t* profiler_overhead_time_ptr = nullptr; + time_duration_t *parent_overhead_time_ptr = nullptr; + time_duration_t *profiler_overhead_time_ptr = nullptr; // Acquire parent pointers - if (call_depth_ > 0){ - auto parent_depth = static_cast(call_depth_-1); - record_index_t parent_index = thread_traceback_[tid].at(parent_depth).record_index_; + if (call_depth_ > 0) { + auto parent_depth = static_cast(call_depth_ - 1); + record_index_t parent_index = + thread_traceback_[tid].at(parent_depth).record_index_; thread_hashtables_[tid].add_child_time_to_parent( - parent_index, region_duration, - parent_overhead_time_ptr); + parent_index, region_duration, parent_overhead_time_ptr); } // Increment profiler calls, and get a pointer to the total overhead time. @@ -260,7 +256,9 @@ void meto::Vernier::stop(size_t const hash) // direct children, and also the overall profiling overhead time. // Being outside the stop calliper, these operations need to be as cheap // as possible. - if(parent_overhead_time_ptr) { *parent_overhead_time_ptr += calliper_time; } + if (parent_overhead_time_ptr) { + *parent_overhead_time_ptr += calliper_time; + } *profiler_overhead_time_ptr += calliper_time; } @@ -272,17 +270,16 @@ void meto::Vernier::stop(size_t const hash) * */ -void meto::Vernier::write() -{ +void meto::Vernier::write() { - if (!initialized_){ - meto::error_handler("Vernier::write. Vernier not initialised.", EXIT_FAILURE); + if (!initialized_) { + meto::error_handler("Vernier::write. Vernier not initialised.", + EXIT_FAILURE); } // Create hashvec handler object and feed in data from thread_hashtables_ HashVecHandler output_data(mpi_context_); - for (auto& table : thread_hashtables_) - { + for (auto &table : thread_hashtables_) { table.append_to(output_data); } @@ -292,30 +289,31 @@ void meto::Vernier::write() } /** - * @brief Get the total (inclusive) time taken by a region and everything below it. + * @brief Get the total (inclusive) time taken by a region and everything below + * it. * - * @param[in] hash The hash corresponding to the region of interest. + * @param[in] hash The hash corresponding to the region of interest. * @param[in] thread_id The thread ID for which to return the walltime. * */ -double meto::Vernier::get_total_walltime(size_t const hash, int const thread_id) -{ +double meto::Vernier::get_total_walltime(size_t const hash, + int const thread_id) { auto tid = static_cast(thread_id); return thread_hashtables_[tid].get_total_walltime(hash); } /** - * @brief Get the profiling overhead time experienced by a region, + * @brief Get the profiling overhead time experienced by a region, * as incurred by calling child regions. * - * @param[in] hash The hash corresponding to the region of interest. + * @param[in] hash The hash corresponding to the region of interest. * @param[in] thread_id The thread ID for which to return the walltime. * */ -double meto::Vernier::get_overhead_walltime(size_t const hash, int const thread_id) -{ +double meto::Vernier::get_overhead_walltime(size_t const hash, + int const thread_id) { auto tid = static_cast(thread_id); return thread_hashtables_[tid].get_overhead_walltime(hash); } @@ -324,22 +322,22 @@ double meto::Vernier::get_overhead_walltime(size_t const hash, int const thread_ * @brief Get the self (exclusive) time spent executing a region, minus the * cost of child regions. * - * @param[in] hash The hash corresponding to the region of interest. + * @param[in] hash The hash corresponding to the region of interest. * @param[in] input_tid The thread ID for which to return the walltime. * */ -double meto::Vernier::get_self_walltime(size_t const hash, int const input_tid) -{ +double meto::Vernier::get_self_walltime(size_t const hash, + int const input_tid) { auto tid = static_cast(input_tid); return thread_hashtables_[tid].get_self_walltime(hash); } /** - * @brief Get the time spent executing children of a region, including + * @brief Get the time spent executing children of a region, including * the time taken by their descendents. * - * @param[in] hash The hash corresponding to the region of interest. + * @param[in] hash The hash corresponding to the region of interest. * @param[in] input_tid The thread ID for which to return the walltime. * * @note This time does not include profiling overhead costs incurred directly @@ -347,8 +345,8 @@ double meto::Vernier::get_self_walltime(size_t const hash, int const input_tid) * */ -double meto::Vernier::get_child_walltime(size_t const hash, int const input_tid) const -{ +double meto::Vernier::get_child_walltime(size_t const hash, + int const input_tid) const { auto tid = static_cast(input_tid); return thread_hashtables_[tid].get_child_walltime(hash); } @@ -356,7 +354,7 @@ double meto::Vernier::get_child_walltime(size_t const hash, int const input_tid) /** * @brief Get the name of a region corresponding to a given hash. * - * @param[in] hash The hash corresponding to the region of interest. + * @param[in] hash The hash corresponding to the region of interest. * @param[in] input_tid The thread ID for which to return the walltime. * * @note The thread ID is included to future-proof against the possibility of @@ -365,9 +363,9 @@ double meto::Vernier::get_child_walltime(size_t const hash, int const input_tid) * */ -std::string meto::Vernier::get_decorated_region_name(size_t const hash, - int const input_tid) const -{ +std::string +meto::Vernier::get_decorated_region_name(size_t const hash, + int const input_tid) const { auto tid = static_cast(input_tid); return thread_hashtables_[tid].get_decorated_region_name(hash); } @@ -384,8 +382,8 @@ std::string meto::Vernier::get_decorated_region_name(size_t const hash, * */ -unsigned long long int meto::Vernier::get_call_count(size_t const hash, int const input_tid) const -{ +unsigned long long int +meto::Vernier::get_call_count(size_t const hash, int const input_tid) const { auto tid = static_cast(input_tid); return thread_hashtables_[tid].get_call_count(hash); } @@ -400,8 +398,8 @@ unsigned long long int meto::Vernier::get_call_count(size_t const hash, int cons * */ -unsigned long long int meto::Vernier::get_prof_call_count(int const input_tid) const -{ +unsigned long long int +meto::Vernier::get_prof_call_count(int const input_tid) const { auto tid = static_cast(input_tid); return thread_hashtables_[tid].get_prof_call_count(); } diff --git a/src/c++/vernier.h b/src/c++/vernier.h index 7f43f254..3601908a 100644 --- a/src/c++/vernier.h +++ b/src/c++/vernier.h @@ -16,29 +16,28 @@ #ifndef VERNIER_H #define VERNIER_H +#include #include -#include #include -#include +#include #ifdef _OPENMP - #include +#include #endif -#include "vernier_mpi.h" -#include "mpi_context.h" #include "hashtable.h" +#include "mpi_context.h" +#include "vernier_mpi.h" #define PROF_MAX_TRACEBACK_SIZE 1000 -namespace meto -{ +namespace meto { // Forward declarations. The definitions of these functions will require access // to private methods. extern "C" { - void c_vernier_start_part1(); - void c_vernier_start_part2(long int& hash_out, char const* name); +void c_vernier_start_part1(); +void c_vernier_start_part2(long int &hash_out, char const *name); } /** @@ -48,86 +47,84 @@ extern "C" { * of profiled regions. */ -class Vernier -{ - private: - - /** - * @brief Struct to store values set during the start calliper, and needed in - * the stop calliper. - */ - - struct TracebackEntry - { - public: - - // Constructors - TracebackEntry() = default; - TracebackEntry(size_t, record_index_t, time_point_t, time_point_t); - - // Data members - size_t record_hash_; - record_index_t record_index_; - time_point_t region_start_time_; - time_point_t calliper_start_time_; - }; - - // Default initialisation flag. No explicit constructor, and pointless - // to set this in the init() method. - bool initialized_ = false; - - // Data members - int max_threads_; - - // MPI Context - MPIContext mpi_context_; - - // Static, threadprivate data members - static time_point_t logged_calliper_start_time_; - static int call_depth_; - #pragma omp threadprivate(call_depth_, logged_calliper_start_time_) - - // Hashtables and tracebacks - std::vector thread_hashtables_; - std::vector> thread_traceback_; - - // Type definitions for vector array indexing. - typedef std::vector::size_type hashtable_iterator_t_; - typedef std::vector> - ::size_type traceback_index_t; - - // Private methods - void start_part1(); - size_t start_part2(std::string_view const); +class Vernier { +private: + /** + * @brief Struct to store values set during the start calliper, and needed in + * the stop calliper. + */ + struct TracebackEntry { public: + // Constructors + TracebackEntry() = default; + TracebackEntry(size_t, record_index_t, time_point_t, time_point_t); - // Default constructor needed for `inline` global Vernier object. - Vernier() = default; - - // Member functions - void init(MPI_Comm const client_comm_handle = MPI_COMM_WORLD); - void finalize(); - size_t start(std::string_view const); - void stop (size_t const); - void write(); - - // Getters - double get_total_walltime (size_t const, int const); - double get_overhead_walltime (size_t const, int const); - double get_self_walltime(size_t const hash, int const input_tid); - double get_child_walltime(size_t const hash, int const input_tid) const; - std::string get_decorated_region_name(size_t const hash, int const input_tid) const; - unsigned long long int get_call_count(size_t const hash, int const input_tid) const; - unsigned long long int get_prof_call_count(int const input_tid) const; - - // Grant these functions access to private methods. - void friend c_vernier_start_part1(); - void friend c_vernier_start_part2(long int& hash_out, char const* name); + // Data members + size_t record_hash_; + record_index_t record_index_; + time_point_t region_start_time_; + time_point_t calliper_start_time_; + }; + + // Default initialisation flag. No explicit constructor, and pointless + // to set this in the init() method. + bool initialized_ = false; + + // Data members + int max_threads_; + + // MPI Context + MPIContext mpi_context_; + + // Static, threadprivate data members + static time_point_t logged_calliper_start_time_; + static int call_depth_; +#pragma omp threadprivate(call_depth_, logged_calliper_start_time_) + + // Hashtables and tracebacks + std::vector thread_hashtables_; + std::vector> + thread_traceback_; + + // Type definitions for vector array indexing. + typedef std::vector::size_type hashtable_iterator_t_; + typedef std::vector>:: + size_type traceback_index_t; + + // Private methods + void start_part1(); + size_t start_part2(std::string_view const); + +public: + // Default constructor needed for `inline` global Vernier object. + Vernier() = default; + + // Member functions + void init(MPI_Comm const client_comm_handle = MPI_COMM_WORLD); + void finalize(); + size_t start(std::string_view const); + void stop(size_t const); + void write(); + + // Getters + double get_total_walltime(size_t const, int const); + double get_overhead_walltime(size_t const, int const); + double get_self_walltime(size_t const hash, int const input_tid); + double get_child_walltime(size_t const hash, int const input_tid) const; + std::string get_decorated_region_name(size_t const hash, + int const input_tid) const; + unsigned long long int get_call_count(size_t const hash, + int const input_tid) const; + unsigned long long int get_prof_call_count(int const input_tid) const; + + // Grant these functions access to private methods. + void friend c_vernier_start_part1(); + void friend c_vernier_start_part2(long int &hash_out, char const *name); }; // Declare global profiler inline Vernier vernier; -} // End meto namespace +} // namespace meto #endif diff --git a/src/c++/vernier_get_wtime.cpp b/src/c++/vernier_get_wtime.cpp index 4d890f54..9f0faf3e 100644 --- a/src/c++/vernier_get_wtime.cpp +++ b/src/c++/vernier_get_wtime.cpp @@ -7,12 +7,12 @@ #include "vernier_get_wtime.h" #include "error_handler.h" -#include -#include -#include -#include #include -#define BILLION 1000000000L +#include +#include +#include +#include +#define BILLION 1000000000L /** * @brief Returns the current time. @@ -20,14 +20,13 @@ * @returns A timespec struct which has the timings in seconds and nanoseconds. */ -double meto::vernier_get_wtime() -{ - struct timespec point; - double time; - if (clock_gettime( CLOCK_REALTIME, &point) == -1) - { - error_handler("clock gettime", EXIT_FAILURE); - } - time = static_cast(point.tv_sec) + static_cast(point.tv_nsec)/BILLION; - return time; +double meto::vernier_get_wtime() { + struct timespec point; + double time; + if (clock_gettime(CLOCK_REALTIME, &point) == -1) { + error_handler("clock gettime", EXIT_FAILURE); + } + time = static_cast(point.tv_sec) + + static_cast(point.tv_nsec) / BILLION; + return time; } diff --git a/src/c++/vernier_get_wtime.h b/src/c++/vernier_get_wtime.h index 7ae52a3b..17364347 100644 --- a/src/c++/vernier_get_wtime.h +++ b/src/c++/vernier_get_wtime.h @@ -9,16 +9,15 @@ * @file vernier_get_wtime().h * @brief vernier_get_wtime function which returns the current time * - * + * */ #ifndef VERNIER_GET_WTIME_H #define VERNIER_GET_WTIME_H -namespace meto -{ - // Function prototypes - double vernier_get_wtime(); -} +namespace meto { +// Function prototypes +double vernier_get_wtime(); +} // namespace meto #endif \ No newline at end of file diff --git a/src/c++/vernier_gettime.cpp b/src/c++/vernier_gettime.cpp index fb717223..c52c8d1d 100644 --- a/src/c++/vernier_gettime.cpp +++ b/src/c++/vernier_gettime.cpp @@ -13,7 +13,6 @@ * @returns The present time point. */ -meto::time_point_t meto::vernier_gettime() -{ +meto::time_point_t meto::vernier_gettime() { return std::chrono::steady_clock::now(); } diff --git a/src/c++/vernier_gettime.h b/src/c++/vernier_gettime.h index 176c4101..764b4c6e 100644 --- a/src/c++/vernier_gettime.h +++ b/src/c++/vernier_gettime.h @@ -17,15 +17,15 @@ #include -namespace meto -{ +namespace meto { // Type definitions for chrono steady clock time points and durations using time_duration_t = std::chrono::duration; -using time_point_t = std::chrono::time_point; +using time_point_t = + std::chrono::time_point; // Function prototypes time_point_t vernier_gettime(); -} // End meto namespace +} // namespace meto #endif diff --git a/src/c++/vernier_mpi.cpp b/src/c++/vernier_mpi.cpp index fecf965b..ea0a5269 100644 --- a/src/c++/vernier_mpi.cpp +++ b/src/c++/vernier_mpi.cpp @@ -15,8 +15,7 @@ * @returns MPI success code. */ -int MPI_Init([[maybe_unused]] int* const, [[maybe_unused]] char*** const) -{ +int MPI_Init([[maybe_unused]] int *const, [[maybe_unused]] char ***const) { return MPI_SUCCESS; } @@ -25,10 +24,7 @@ int MPI_Init([[maybe_unused]] int* const, [[maybe_unused]] char*** const) * @returns MPI success code. */ -int MPI_Finalize(void) -{ - return MPI_SUCCESS; -} +int MPI_Finalize(void) { return MPI_SUCCESS; } /** * @brief Stub for MPI_Abort @@ -37,22 +33,18 @@ int MPI_Finalize(void) * @returns MPI success code. */ -int MPI_Abort([[maybe_unused]] MPI_Comm const comm, int const errcode) -{ - std::exit (errcode); +int MPI_Abort([[maybe_unused]] MPI_Comm const comm, int const errcode) { + std::exit(errcode); } /** * @brief Stub for MPI_Comm_f2c - * + * * @param [in] MPI communicator handle. (Fortran) * @returns MPI communicator handle. */ -int MPI_Comm_f2c(MPI_Fint const comm) -{ - return comm; -} +int MPI_Comm_f2c(MPI_Fint const comm) { return comm; } /** * @brief Stub for MPI_Initialized @@ -60,8 +52,7 @@ int MPI_Comm_f2c(MPI_Fint const comm) * @returns MPI success code. */ -int MPI_Initialized(int* flag) -{ +int MPI_Initialized(int *flag) { *flag = 1; return MPI_SUCCESS; } @@ -72,9 +63,8 @@ int MPI_Initialized(int* flag) * @returns MPI success code. */ -int MPI_Comm_free([[maybe_unused]] MPI_Comm* comm) -{ - *comm=MPI_COMM_NULL; +int MPI_Comm_free([[maybe_unused]] MPI_Comm *comm) { + *comm = MPI_COMM_NULL; return MPI_SUCCESS; } @@ -87,9 +77,8 @@ int MPI_Comm_free([[maybe_unused]] MPI_Comm* comm) * input and output handles are not the same. */ -int MPI_Comm_dup (MPI_Comm const comm, MPI_Comm* newcomm) -{ - *newcomm = comm + 1; +int MPI_Comm_dup(MPI_Comm const comm, MPI_Comm *newcomm) { + *newcomm = comm + 1; return MPI_SUCCESS; } @@ -100,8 +89,7 @@ int MPI_Comm_dup (MPI_Comm const comm, MPI_Comm* newcomm) * @returns MPI success code. */ -int MPI_Comm_size([[maybe_unused]] MPI_Comm const comm, int* size) -{ +int MPI_Comm_size([[maybe_unused]] MPI_Comm const comm, int *size) { *size = 1; return MPI_SUCCESS; } @@ -113,8 +101,7 @@ int MPI_Comm_size([[maybe_unused]] MPI_Comm const comm, int* size) * @returns MPI success code. */ -int MPI_Comm_rank([[maybe_unused]] MPI_Comm const comm, int* rank) -{ +int MPI_Comm_rank([[maybe_unused]] MPI_Comm const comm, int *rank) { *rank = 0; return MPI_SUCCESS; } diff --git a/src/c++/vernier_mpi.h b/src/c++/vernier_mpi.h index 7786d575..1c96d33f 100644 --- a/src/c++/vernier_mpi.h +++ b/src/c++/vernier_mpi.h @@ -17,27 +17,28 @@ #define VERNIER_MPI_H #ifdef USE_MPI - #include +#include #else - #define MPI_COMM_NULL 0 - #define MPI_COMM_WORLD 1 - #define MPI_SUCCESS 0 - using MPI_Comm = int; - using MPI_Fint = int; +#define MPI_COMM_NULL 0 +#define MPI_COMM_WORLD 1 +#define MPI_SUCCESS 0 +using MPI_Comm = int; +using MPI_Fint = int; - int MPI_Init([[maybe_unused]] int* const, [[maybe_unused]] char*** const); - int MPI_Finalize(void); - int MPI_Initialized(int* value); +int MPI_Init([[maybe_unused]] int *const, [[maybe_unused]] char ***const); +int MPI_Finalize(void); +int MPI_Initialized(int *value); - int MPI_Abort([[maybe_unused]] MPI_Comm const comm, int const errcode); +int MPI_Abort([[maybe_unused]] MPI_Comm const comm, int const errcode); - int MPI_Comm_f2c(MPI_Fint const); +int MPI_Comm_f2c(MPI_Fint const); - int MPI_Comm_free([[maybe_unused]] MPI_Comm* comm); - int MPI_Comm_dup ([[maybe_unused]] MPI_Comm const comm, [[maybe_unused]] MPI_Comm* newcomm); +int MPI_Comm_free([[maybe_unused]] MPI_Comm *comm); +int MPI_Comm_dup([[maybe_unused]] MPI_Comm const comm, + [[maybe_unused]] MPI_Comm *newcomm); - int MPI_Comm_size([[maybe_unused]] MPI_Comm const comm, int* size); - int MPI_Comm_rank([[maybe_unused]] MPI_Comm const comm, int* rank); +int MPI_Comm_size([[maybe_unused]] MPI_Comm const comm, int *size); +int MPI_Comm_rank([[maybe_unused]] MPI_Comm const comm, int *rank); #endif #endif diff --git a/src/c++/writer/multi.cpp b/src/c++/writer/multi.cpp index 66cae1dc..a59e766e 100644 --- a/src/c++/writer/multi.cpp +++ b/src/c++/writer/multi.cpp @@ -7,28 +7,26 @@ #include "multi.h" - /** * @brief Construct a new Multi writer. * @param[in] mpi_context The MPI context the writer will use. */ -meto::Multi::Multi(MPIContext const& mpi_context): - meto::Multi::Writer(mpi_context) {} +meto::Multi::Multi(MPIContext const &mpi_context) + : meto::Multi::Writer(mpi_context) {} /** * @brief Opens a unique file per mpi rank - * + * * @param[in] os Output stream to write to */ -void meto::Multi::open_files(std::ofstream& os) -{ +void meto::Multi::open_files(std::ofstream &os) { // Append the MPI rank to the output filename. std::string mpi_filename_tail = "-" + std::to_string(mpi_context_.get_rank()); output_filename_ += mpi_filename_tail; - + os.open(output_filename_); } @@ -40,8 +38,7 @@ void meto::Multi::open_files(std::ofstream& os) * @param[in] hashvec The vector containing all necessary data */ -void meto::Multi::write(std::ofstream& os, hashvec_t hashvec) -{ +void meto::Multi::write(std::ofstream &os, hashvec_t hashvec) { open_files(os); formatter_.execute_format(os, hashvec); os.flush(); diff --git a/src/c++/writer/multi.h b/src/c++/writer/multi.h index 135eb68f..e7eec06f 100644 --- a/src/c++/writer/multi.h +++ b/src/c++/writer/multi.h @@ -8,7 +8,7 @@ /** * @file multi.h * @brief Multi class, derived from Writer. - * + * */ #ifndef VERNIER_MULTI_H @@ -17,8 +17,7 @@ #include "../mpi_context.h" #include "writer.h" -namespace meto -{ +namespace meto { /** * @brief Multiple-file output strategy @@ -28,21 +27,18 @@ namespace meto class Multi : public Writer { - private: - - // Method - void open_files(std::ofstream& os); - - public: - - // Constructor - Multi(MPIContext const&); +private: + // Method + void open_files(std::ofstream &os); - // Implementation of pure virtual function. - void write(std::ofstream& os, hashvec_t) override; +public: + // Constructor + Multi(MPIContext const &); + // Implementation of pure virtual function. + void write(std::ofstream &os, hashvec_t) override; }; -} // End meto namespace +} // namespace meto #endif diff --git a/src/c++/writer/writer.cpp b/src/c++/writer/writer.cpp index 1a6b06de..4c0f50e7 100644 --- a/src/c++/writer/writer.cpp +++ b/src/c++/writer/writer.cpp @@ -8,19 +8,19 @@ #include "writer.h" /** - * @brief Set data members common to all Writer objects. + * @brief Set data members common to all Writer objects. * @param [in] The MPI context the writer will use. * */ -meto::Writer::Writer(MPIContext const& mpi_context) -{ +meto::Writer::Writer(MPIContext const &mpi_context) { // Pick up environment variable filename if it exists. If it's not set, a - // suitable default is set in the data member declaration. - const char* env_output_filename = std::getenv("VERNIER_OUTPUT_FILENAME"); - if (env_output_filename) {output_filename_ = env_output_filename;} + // suitable default is set in the data member declaration. + const char *env_output_filename = std::getenv("VERNIER_OUTPUT_FILENAME"); + if (env_output_filename) { + output_filename_ = env_output_filename; + } // MPI handling mpi_context_ = mpi_context; - } diff --git a/src/c++/writer/writer.h b/src/c++/writer/writer.h index 39b8f904..046ccbf0 100644 --- a/src/c++/writer/writer.h +++ b/src/c++/writer/writer.h @@ -8,48 +8,44 @@ /** * @file writer.h * @brief Writer base strategy class. - * + * */ #ifndef VERNIER_WRITER_H #define VERNIER_WRITER_H -#include "../mpi_context.h" #include "../formatter.h" +#include "../mpi_context.h" -namespace meto -{ +namespace meto { /** * @brief Abstract Writer strategy class. * @details Specific implementations of this class override the 'write' function * to produce different behaviour. - * + * */ class Writer { - protected: - - // Formatter strategy - Formatter formatter_; - - // Default filename - std::string output_filename_ = "vernier-output"; - - // MPI context - MPIContext mpi_context_; +protected: + // Formatter strategy + Formatter formatter_; - public: + // Default filename + std::string output_filename_ = "vernier-output"; - explicit Writer(MPIContext const&); - virtual ~Writer() = default; + // MPI context + MPIContext mpi_context_; - // Pure virtual write method - virtual void write(std::ofstream& os, hashvec_t) = 0; +public: + explicit Writer(MPIContext const &); + virtual ~Writer() = default; + // Pure virtual write method + virtual void write(std::ofstream &os, hashvec_t) = 0; }; -} // End meto namespace +} // namespace meto #endif diff --git a/src/c/vernier_c.cpp b/src/c/vernier_c.cpp index e7b39d75..989fb660 100644 --- a/src/c/vernier_c.cpp +++ b/src/c/vernier_c.cpp @@ -16,21 +16,21 @@ */ #include "vernier.h" -#include "vernier_mpi.h" #include "vernier_get_wtime.h" +#include "vernier_mpi.h" -#include #include +#include extern "C" { - void c_vernier_init(MPI_Fint const& client_comm_handle); - void c_vernier_finalize(); - void c_vernier_start_part1(); - void c_vernier_start_part2(long int&, char const*); - void c_vernier_stop (long int const&); - void c_vernier_write(); - double c_vernier_get_total_walltime(long int const&, int const&); - double c_vernier_get_wtime(); +void c_vernier_init(MPI_Fint const &client_comm_handle); +void c_vernier_finalize(); +void c_vernier_start_part1(); +void c_vernier_start_part2(long int &, char const *); +void c_vernier_stop(long int const &); +void c_vernier_write(); +double c_vernier_get_total_walltime(long int const &, int const &); +double c_vernier_get_wtime(); } /** @@ -39,7 +39,7 @@ extern "C" { * @param [in] The Fortran communicator handle. */ -void c_vernier_init(MPI_Fint const& client_comm_handle) +void c_vernier_init(MPI_Fint const &client_comm_handle) { MPI_Comm local_handle = MPI_Comm_f2c(client_comm_handle); @@ -50,19 +50,13 @@ void c_vernier_init(MPI_Fint const& client_comm_handle) * @brief Finalize Vernier. */ -void c_vernier_finalize() -{ - meto::vernier.finalize(); -} +void c_vernier_finalize() { meto::vernier.finalize(); } /** * @brief Start timing, part 1 of 2. */ -void meto::c_vernier_start_part1() -{ - meto::vernier.start_part1(); -} +void meto::c_vernier_start_part1() { meto::vernier.start_part1(); } /** * @brief Start timing, part 2 of 2. a named region and return a unique handle. @@ -70,9 +64,8 @@ void meto::c_vernier_start_part1() * @param [out] hash_out The returned unique hash for this region. */ -void meto::c_vernier_start_part2(long int& hash_out, char const* name) -{ - size_t hash = meto::vernier.start_part2( name ); +void meto::c_vernier_start_part2(long int &hash_out, char const *name) { + size_t hash = meto::vernier.start_part2(name); // Ensure that the source and destination have the same size. static_assert(sizeof(hash) == sizeof(hash_out), "Hash/Out size mismatch."); @@ -83,35 +76,31 @@ void meto::c_vernier_start_part2(long int& hash_out, char const* name) * @brief Stop timing the region with the specified handle. */ -void c_vernier_stop(long int const& hash_in) -{ +void c_vernier_stop(long int const &hash_in) { size_t hash; // Ensure that the source and destination have the same size. static_assert(sizeof(hash) == sizeof(hash_in), "Hash/In size mismatch."); std::memcpy(&hash, &hash_in, sizeof(hash)); - meto::vernier.stop( hash ); + meto::vernier.stop(hash); } /** * @brief Write the profile itself. */ -void c_vernier_write() -{ - meto::vernier.write(); -} +void c_vernier_write() { meto::vernier.write(); } /** * @brief Get the total wallclock time for the specified region on the * specified thread. - * @param[in] hash_in The hash of the region of interest. + * @param[in] hash_in The hash of the region of interest. * @param[in] thread_id Return the time for this thread ID. */ -double c_vernier_get_total_walltime(long int const& hash_in, int const& thread_id) -{ +double c_vernier_get_total_walltime(long int const &hash_in, + int const &thread_id) { size_t hash; // Ensure that the source and destination have the same size. @@ -125,9 +114,4 @@ double c_vernier_get_total_walltime(long int const& hash_in, int const& thread_i * @brief Timing with clock_gettime(). */ -double c_vernier_get_wtime() -{ - return meto::vernier_get_wtime(); -} - - +double c_vernier_get_wtime() { return meto::vernier_get_wtime(); } diff --git a/tests/unit_tests/c++/mpi_main.cpp b/tests/unit_tests/c++/mpi_main.cpp index 7591e86c..d188c3ea 100644 --- a/tests/unit_tests/c++/mpi_main.cpp +++ b/tests/unit_tests/c++/mpi_main.cpp @@ -5,8 +5,8 @@ * ----------------------------------------------------------------------------- */ -#include #include "vernier_mpi.h" +#include int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); @@ -19,4 +19,3 @@ int main(int argc, char **argv) { return result; } - diff --git a/tests/unit_tests/c++/test_callcount.cpp b/tests/unit_tests/c++/test_callcount.cpp index 8114e89e..97e774f6 100644 --- a/tests/unit_tests/c++/test_callcount.cpp +++ b/tests/unit_tests/c++/test_callcount.cpp @@ -6,14 +6,13 @@ #include #ifdef _OPENMP - #include +#include #endif #include #include "vernier.h" -TEST(HashEntryTest,CallCountTest) -{ +TEST(HashEntryTest, CallCountTest) { meto::vernier.init(); @@ -27,23 +26,24 @@ TEST(HashEntryTest,CallCountTest) int num_threads = 1; // Start parallel region -#pragma omp parallel default(none) shared(prof_sub_shared, meto::vernier, num_threads) +#pragma omp parallel default(none) \ + shared(prof_sub_shared, meto::vernier, num_threads) { // Get total number of threads, only need to calculate on a single thread // since value won't change. #pragma omp single { - #ifdef _OPENMP +#ifdef _OPENMP num_threads = omp_get_num_threads(); - #endif +#endif prof_sub_shared.resize(static_cast(num_threads)); } // Current thread ID int thread_id = 0; - #ifdef _OPENMP - thread_id = omp_get_thread_num(); - #endif +#ifdef _OPENMP + thread_id = omp_get_thread_num(); +#endif // Also initialise prof_sub_private. The compiler doesn't know how many // iterations of the subsequent 'for' loop there will be, and may flag @@ -53,17 +53,14 @@ TEST(HashEntryTest,CallCountTest) // Call a subregion a differing number of times depending on the thread ID. // The highest thread ID will have the fewest calls: just 1. - for (int i = 0; i < num_threads-thread_id; ++i) - { + for (int i = 0; i < num_threads - thread_id; ++i) { prof_sub_private = meto::vernier.start("SubRegion"); meto::vernier.stop(prof_sub_private); } // Give prof_sub_shared a value for later use in EXPECT's #pragma omp critical - { - prof_sub_shared[static_cast(thread_id)] = prof_sub_private; - } + { prof_sub_shared[static_cast(thread_id)] = prof_sub_private; } } // Stop main region @@ -72,13 +69,13 @@ TEST(HashEntryTest,CallCountTest) // Check call_count_ is the number expected on all threads. On most threads, // the profiler calliper call count should match this number, except on thread // zero which includes the main region callipers. - for (int thread = 0; thread < num_threads; ++thread) - { + for (int thread = 0; thread < num_threads; ++thread) { size_t hash = prof_sub_shared[static_cast(thread)]; - EXPECT_EQ(meto::vernier.get_call_count(hash,thread), num_threads-thread); + EXPECT_EQ(meto::vernier.get_call_count(hash, thread), num_threads - thread); - int incr = (thread==0) ? 1 : 0; - EXPECT_EQ(meto::vernier.get_prof_call_count(thread), num_threads-thread+incr); + int incr = (thread == 0) ? 1 : 0; + EXPECT_EQ(meto::vernier.get_prof_call_count(thread), + num_threads - thread + incr); } meto::vernier.finalize(); diff --git a/tests/unit_tests/c++/test_hashtable.cpp b/tests/unit_tests/c++/test_hashtable.cpp index 7b4a80e9..d937e019 100644 --- a/tests/unit_tests/c++/test_hashtable.cpp +++ b/tests/unit_tests/c++/test_hashtable.cpp @@ -4,10 +4,10 @@ under which the code may be used. \*----------------------------------------------------------------------------*/ -#include #include +#include #ifdef _OPENMP - #include +#include #endif #include "vernier.h" @@ -18,7 +18,7 @@ using ::testing::Gt; int const tid = 0; std::string tid_str(std::to_string(tid)); -std::string tid_bytes(reinterpret_cast(&tid), sizeof(tid)); +std::string tid_bytes(reinterpret_cast(&tid), sizeof(tid)); // // Testing that the hashing function works as expected (we don't want @@ -28,13 +28,14 @@ std::string tid_bytes(reinterpret_cast(&tid), sizeof(tid)); // sure it returns the MDI of 0.0 // -TEST(HashTableTest,HashFunctionTest) { +TEST(HashTableTest, HashFunctionTest) { meto::vernier.init(); - // Create new hashes via HashTable::query_insert, which is used in Vernier::start - const auto& prof_rigatoni = meto::vernier.start("Rigatoni"); - const auto& prof_penne = meto::vernier.start("Penne"); + // Create new hashes via HashTable::query_insert, which is used in + // Vernier::start + const auto &prof_rigatoni = meto::vernier.start("Rigatoni"); + const auto &prof_penne = meto::vernier.start("Penne"); meto::vernier.stop(prof_penne); meto::vernier.stop(prof_rigatoni); @@ -44,9 +45,12 @@ TEST(HashTableTest,HashFunctionTest) { // Checking that: // - query_insert'ing Penne or Rigatoni just returns the hash // - the regions have different hashes - // - the regions have the hashes returned by hash_function_ which uses std::hash - EXPECT_EQ(meto::vernier.start("Rigatoni"), std::hash{}("Rigatoni" + tid_bytes)); - EXPECT_EQ(meto::vernier.start("Penne"), std::hash{}("Penne" + tid_bytes)); + // - the regions have the hashes returned by hash_function_ which uses + // std::hash + EXPECT_EQ(meto::vernier.start("Rigatoni"), + std::hash{}("Rigatoni" + tid_bytes)); + EXPECT_EQ(meto::vernier.start("Penne"), + std::hash{}("Penne" + tid_bytes)); } meto::vernier.finalize(); @@ -58,7 +62,7 @@ TEST(HashTableTest,HashFunctionTest) { * */ -TEST(HashTableTest,UpdateTimesTest) { +TEST(HashTableTest, UpdateTimesTest) { meto::vernier.init(); @@ -66,18 +70,20 @@ TEST(HashTableTest,UpdateTimesTest) { size_t prof_pie = std::hash{}("Pie" + tid_bytes); // Trying to find a time before .start() will throw an exception - EXPECT_THROW(meto::vernier.get_total_walltime(prof_pie, 0), std::out_of_range); + EXPECT_THROW(meto::vernier.get_total_walltime(prof_pie, 0), + std::out_of_range); // Start timing - auto const& expected_hash = meto::vernier.start("Pie"); - EXPECT_EQ(expected_hash,prof_pie); // Make sure prof_pie has the hash we expect + auto const &expected_hash = meto::vernier.start("Pie"); + EXPECT_EQ(expected_hash, + prof_pie); // Make sure prof_pie has the hash we expect sleep(1); // Time t1 declared inbetween .start() and first .stop() double const t1 = meto::vernier.get_total_walltime(prof_pie, 0); - //Stop timing + // Stop timing meto::vernier.stop(prof_pie); // Time t2 declared after first vernier.stop() @@ -92,7 +98,7 @@ TEST(HashTableTest,UpdateTimesTest) { double const t3 = meto::vernier.get_total_walltime(prof_pie, 0); // Expected behaviour: t1 return the MDI and t3 > t2 > 0 - constexpr double MDI = 0.0; // Missing Data Indicator (MDI) + constexpr double MDI = 0.0; // Missing Data Indicator (MDI) { SCOPED_TRACE("MDI missing from time points expected to return it"); @@ -102,7 +108,7 @@ TEST(HashTableTest,UpdateTimesTest) { { SCOPED_TRACE("Update potentially not incrementing times correctly"); EXPECT_GT(t2, 0.0); - EXPECT_GT(t3, t2 ); + EXPECT_GT(t3, t2); } meto::vernier.finalize(); diff --git a/tests/unit_tests/c++/test_hashtiming.cpp b/tests/unit_tests/c++/test_hashtiming.cpp index 33d6e297..ef7ed55a 100644 --- a/tests/unit_tests/c++/test_hashtiming.cpp +++ b/tests/unit_tests/c++/test_hashtiming.cpp @@ -4,9 +4,9 @@ under which the code may be used. \*----------------------------------------------------------------------------*/ -#include #include #include +#include #include "vernier.h" @@ -23,13 +23,13 @@ TEST(HashEntryTest, TimingsTest) { meto::vernier.init(); // Start main profiler region and chrono timing - const auto& prof_main = meto::vernier.start("QuicheLorraine"); + const auto &prof_main = meto::vernier.start("QuicheLorraine"); const auto chrono_main_start = std::chrono::steady_clock::now(); sleep(1); // Start a sub-region and chrono timing - const auto& prof_sub = meto::vernier.start("SalmonQuiche"); + const auto &prof_sub = meto::vernier.start("SalmonQuiche"); const auto chrono_sub_start = std::chrono::steady_clock::now(); sleep(1); @@ -46,28 +46,30 @@ TEST(HashEntryTest, TimingsTest) { SCOPED_TRACE("Self walltime calculation failed"); // Grab the total, child and self wallclock times - const double& total = meto::vernier.get_total_walltime (prof_main,0); - const double& child = meto::vernier.get_child_walltime (prof_main,0); - const double& self = meto::vernier.get_self_walltime (prof_main,0); - const double& overhead = meto::vernier.get_overhead_walltime (prof_main,0); - std::string region = meto::vernier.get_decorated_region_name(prof_main,0); + const double &total = meto::vernier.get_total_walltime(prof_main, 0); + const double &child = meto::vernier.get_child_walltime(prof_main, 0); + const double &self = meto::vernier.get_self_walltime(prof_main, 0); + const double &overhead = meto::vernier.get_overhead_walltime(prof_main, 0); + std::string region = meto::vernier.get_decorated_region_name(prof_main, 0); // Test that self_walltime = total_walltime - child_walltime - overheads // NB: This test does not include recursive subroutine calls. - EXPECT_EQ(self,total-child-overhead) - << " region: " << region << std::endl - << " self: " << self << std::endl - << " child: " << child << std::endl - << " overhead: " << overhead << std::endl; - ; + EXPECT_EQ(self, total - child - overhead) + << " region: " << region << std::endl + << " self: " << self << std::endl + << " child: " << child << std::endl + << " overhead: " << overhead << std::endl; + ; } // Work out chrono durations in seconds - std::chrono::duration main_region_duration = chrono_main_end - chrono_main_start; + std::chrono::duration main_region_duration = + chrono_main_end - chrono_main_start; double main_in_s = main_region_duration.count(); - std::chrono::duration sub_region_duration = chrono_sub_end - chrono_sub_start; - double sub_in_s = sub_region_duration.count(); + std::chrono::duration sub_region_duration = + chrono_sub_end - chrono_sub_start; + double sub_in_s = sub_region_duration.count(); { SCOPED_TRACE("Chrono and profiler times not within tolerance"); @@ -76,8 +78,10 @@ TEST(HashEntryTest, TimingsTest) { const double time_tolerance = 0.0005; // Expect profiler & chrono times to be within tolerance - EXPECT_NEAR( meto::vernier.get_total_walltime(prof_main,0), main_in_s, time_tolerance ); - EXPECT_NEAR( meto::vernier.get_total_walltime(prof_sub,0) , sub_in_s , time_tolerance ); + EXPECT_NEAR(meto::vernier.get_total_walltime(prof_main, 0), main_in_s, + time_tolerance); + EXPECT_NEAR(meto::vernier.get_total_walltime(prof_sub, 0), sub_in_s, + time_tolerance); } meto::vernier.finalize(); diff --git a/tests/unit_tests/c++/test_mpi_not_init.cpp b/tests/unit_tests/c++/test_mpi_not_init.cpp index 0f6b6fd7..09f9ba03 100644 --- a/tests/unit_tests/c++/test_mpi_not_init.cpp +++ b/tests/unit_tests/c++/test_mpi_not_init.cpp @@ -4,8 +4,8 @@ under which the code may be used. \*----------------------------------------------------------------------------*/ -#include #include +#include #include "vernier.h" @@ -14,18 +14,16 @@ using ::testing::ExitedWithCode; // Attempt to initialise Vernier without MPI being initialized. TEST(TestMPINotInit, MpiNotInitialised) { + // clang-format off #ifdef USE_MPI [[maybe_unused]] int ierr; - EXPECT_EXIT({ - meto::vernier.init(); - }, - ExitedWithCode(EXIT_FAILURE), - "MPIContext::init. MPI not initialized."), - meto::vernier.finalize(); + EXPECT_EXIT( + { meto::vernier.init(); }, ExitedWithCode(EXIT_FAILURE), + "MPIContext::init. MPI not initialized."), + meto::vernier.finalize(); #else meto::vernier.init(); meto::vernier.finalize(); #endif - + // clang-format on } - diff --git a/tests/unit_tests/c++/test_profiler.cpp b/tests/unit_tests/c++/test_profiler.cpp index b189c0cc..0f87658d 100644 --- a/tests/unit_tests/c++/test_profiler.cpp +++ b/tests/unit_tests/c++/test_profiler.cpp @@ -6,21 +6,20 @@ #include #ifdef _OPENMP - #include +#include #endif #include #include "vernier.h" #include "vernier_get_wtime.h" -TEST(SystemTests, TimingTest) -{ +TEST(SystemTests, TimingTest) { meto::vernier.init(); // Start timing: noddy way, and using Vernier. auto prof_main = meto::vernier.start("MAIN"); - double t1 = meto::vernier_get_wtime(); + double t1 = meto::vernier_get_wtime(); // Time a region { @@ -48,7 +47,7 @@ TEST(SystemTests, TimingTest) sleep(2); // End of profiling; record t2 immediately before. - double t2 = meto::vernier_get_wtime(); + double t2 = meto::vernier_get_wtime(); meto::vernier.stop(prof_main); // Check that the total time measured by the profiler is within some tolerance @@ -57,11 +56,12 @@ TEST(SystemTests, TimingTest) double const time_tolerance = 0.0005; double actual_time = t2 - t1; - double prof_time = meto::vernier.get_total_walltime(prof_main, 0); - std::cout << "\n" << "Actual timing: " << actual_time << "\n"; - std::cout << "\n" << "Profiler timing: " << prof_time << "\n\n"; + double prof_time = meto::vernier.get_total_walltime(prof_main, 0); + std::cout << "\n" + << "Actual timing: " << actual_time << "\n"; + std::cout << "\n" + << "Profiler timing: " << prof_time << "\n\n"; EXPECT_NEAR(prof_time, actual_time, time_tolerance); meto::vernier.finalize(); - } diff --git a/tests/unit_tests/c++/test_proftests.cpp b/tests/unit_tests/c++/test_proftests.cpp index 0b38853c..f3854e2a 100644 --- a/tests/unit_tests/c++/test_proftests.cpp +++ b/tests/unit_tests/c++/test_proftests.cpp @@ -4,16 +4,15 @@ under which the code may be used. \*----------------------------------------------------------------------------*/ -#include #include -#include #include -#include +#include +#include -#include "vernier.h" -#include "vernier_mpi.h" #include "error_handler.h" #include "hashvec_handler.h" +#include "vernier.h" +#include "vernier_mpi.h" using ::testing::ExitedWithCode; @@ -22,51 +21,50 @@ using ::testing::ExitedWithCode; // // Make sure the code exits when a hash mismatch happens. -TEST(ProfilerDeathTest,WrongHashTest) { +TEST(ProfilerDeathTest, WrongHashTest) { meto::vernier.init(); - EXPECT_EXIT({ + EXPECT_EXIT( + { + // Start main + const auto &prof_main = meto::vernier.start("Chocolate"); - // Start main - const auto& prof_main = meto::vernier.start("Chocolate"); + // A subregion + const auto &prof_sub = meto::vernier.start("Vanilla"); + meto::vernier.stop(prof_sub); - // A subregion - const auto& prof_sub = meto::vernier.start("Vanilla"); - meto::vernier.stop(prof_sub); + // Wrong hash in profiler.stop() + meto::vernier.stop(prof_sub); - // Wrong hash in profiler.stop() - meto::vernier.stop(prof_sub); - - // Eventually stop prof_main to avoid Wunused telling me off... - meto::vernier.stop(prof_main); - - }, ExitedWithCode(EXIT_FAILURE), "EMERGENCY STOP: hashes don't match."); + // Eventually stop prof_main to avoid Wunused telling me off... + meto::vernier.stop(prof_main); + }, + ExitedWithCode(EXIT_FAILURE), "EMERGENCY STOP: hashes don't match."); meto::vernier.finalize(); } // Tests for a segfault when stopping before anything else. -TEST(ProfilerDeathTest,StopBeforeStartTest) { - - EXPECT_EXIT({ +TEST(ProfilerDeathTest, StopBeforeStartTest) { - const auto prof_main = std::hash{}("Main"); + EXPECT_EXIT( + { + const auto prof_main = std::hash{}("Main"); - // Stop the profiler before anything is done - meto::vernier.stop(prof_main); - - }, ExitedWithCode(EXIT_FAILURE), "EMERGENCY STOP: stop called before start calliper."); + // Stop the profiler before anything is done + meto::vernier.stop(prof_main); + }, + ExitedWithCode(EXIT_FAILURE), + "EMERGENCY STOP: stop called before start calliper."); } // Vernier is not initialised before first start() call. TEST(ProfilerDeathTest, StartBeforeInit) { - - EXPECT_EXIT({ - meto::vernier.start("MAIN"); - }, - ExitedWithCode(EXIT_FAILURE), - "Vernier::start_part1. Vernier not initialised."); + // clang-format off + EXPECT_EXIT({ meto::vernier.start("MAIN"); }, ExitedWithCode(EXIT_FAILURE), + "Vernier::start_part1. Vernier not initialised."); + // clang-format on } // MPI is initialised, but the passed communicator handle is @@ -74,11 +72,9 @@ TEST(ProfilerDeathTest, StartBeforeInit) { TEST(ProfilerDeathTest, NullCommunicatorPassed) { [[maybe_unused]] int ierr; - EXPECT_EXIT({ - meto::vernier.init(MPI_COMM_NULL); - }, - ExitedWithCode(EXIT_FAILURE), - "MPIContext::init. MPI initialized, but null communicator passed."); + EXPECT_EXIT( + { meto::vernier.init(MPI_COMM_NULL); }, ExitedWithCode(EXIT_FAILURE), + "MPIContext::init. MPI initialized, but null communicator passed."); meto::vernier.finalize(); } @@ -87,12 +83,10 @@ TEST(ProfilerDeathTest, NullCommunicatorPassed) { TEST(ProfilerDeathTest, VernierUninitialisedInWrite) { // No init() called yet, so MPI context not initialised. - - EXPECT_EXIT({ - meto::vernier.write(); - }, - ExitedWithCode(EXIT_FAILURE), - "Vernier::write. Vernier not initialised."); + // clang-format off + EXPECT_EXIT({ meto::vernier.write(); }, ExitedWithCode(EXIT_FAILURE), + "Vernier::write. Vernier not initialised."); + // clang-format on } // The traceback array is not a growable vector. Check that the code exits @@ -101,28 +95,30 @@ TEST(ProfilerDeathTest, TooManyTracebackEntries) { meto::vernier.init(); - EXPECT_EXIT({ - - const int beyond_maximum = PROF_MAX_TRACEBACK_SIZE+1; - for (int i=0; i #ifdef _OPENMP - #include +#include #endif #include "vernier.h" @@ -26,10 +26,9 @@ double const time_tolerance = 0.001; // ------------------------------------------------------------------------------ // Structure To hold timings from the various recursive functions. -struct Timings -{ +struct Timings { double zeroth_function_total_time_ = 0.0; - double first_function_total_time_ = 0.0; + double first_function_total_time_ = 0.0; double second_function_total_time_ = 0.0; }; @@ -38,14 +37,13 @@ struct Timings // ------------------------------------------------------------------------------ // Needed to escape circular dependence on function declarations. -void second_function(Timings&); +void second_function(Timings &); // ------------------------------------------------------------------------------ // Zeroth function - calls itself // ------------------------------------------------------------------------------ -void zeroth_function(Timings& timings) -{ +void zeroth_function(Timings &timings) { static int recursion_depth = 1; #pragma omp threadprivate(recursion_depth) @@ -55,28 +53,26 @@ void zeroth_function(Timings& timings) sleep(sleep_seconds); ++recursion_depth; - if (recursion_depth <= max_depth) - { + if (recursion_depth <= max_depth) { zeroth_function(timings); } meto::vernier.stop(prof_handle); // Update the total walltime so far spent in this function. - int tid = 0; //const was here before -> int const tid = 0; - #ifdef _OPENMP - tid = omp_get_thread_num(); - #endif - timings.zeroth_function_total_time_ = meto::vernier.get_total_walltime(prof_handle, tid); - + int tid = 0; // const was here before -> int const tid = 0; +#ifdef _OPENMP + tid = omp_get_thread_num(); +#endif + timings.zeroth_function_total_time_ = + meto::vernier.get_total_walltime(prof_handle, tid); } // ------------------------------------------------------------------------------ // First function - calls the second function. // ------------------------------------------------------------------------------ -void first_function(Timings& timings) -{ +void first_function(Timings &timings) { static int recursion_depth = 1; #pragma omp threadprivate(recursion_depth) @@ -86,8 +82,7 @@ void first_function(Timings& timings) sleep(sleep_seconds); ++recursion_depth; - if (recursion_depth <= max_depth) - { + if (recursion_depth <= max_depth) { second_function(timings); } @@ -95,20 +90,19 @@ void first_function(Timings& timings) // Update the total walltime so far spent in this function. Do here while we // have access to the prof_handle. - int tid = 0; //const was here before -> int const tid = 0; - #ifdef _OPENMP - tid = omp_get_thread_num(); - #endif - timings.first_function_total_time_ = meto::vernier.get_total_walltime(prof_handle, tid); - + int tid = 0; // const was here before -> int const tid = 0; +#ifdef _OPENMP + tid = omp_get_thread_num(); +#endif + timings.first_function_total_time_ = + meto::vernier.get_total_walltime(prof_handle, tid); } // ------------------------------------------------------------------------------ // Second function - calls the first function. // ------------------------------------------------------------------------------ -void second_function(Timings& timings) -{ +void second_function(Timings &timings) { static int recursion_depth = 1; #pragma omp threadprivate(recursion_depth) @@ -117,8 +111,7 @@ void second_function(Timings& timings) sleep(sleep_seconds); ++recursion_depth; - if (recursion_depth <= max_depth) - { + if (recursion_depth <= max_depth) { first_function(timings); } @@ -126,11 +119,12 @@ void second_function(Timings& timings) // Update the total walltime so far spent in this function. Do here while we // have access to the prof_handle. - int tid = 0; //const was here before -> int const tid = 0; - #ifdef _OPENMP - tid = omp_get_thread_num(); - #endif - timings.second_function_total_time_ = meto::vernier.get_total_walltime(prof_handle, tid); + int tid = 0; // const was here before -> int const tid = 0; +#ifdef _OPENMP + tid = omp_get_thread_num(); +#endif + timings.second_function_total_time_ = + meto::vernier.get_total_walltime(prof_handle, tid); } // ------------------------------------------------------------------------------- @@ -141,8 +135,7 @@ void second_function(Timings& timings) // Direct recursion // -TEST(RecursionTest,DirectRecursion) -{ +TEST(RecursionTest, DirectRecursion) { meto::vernier.init(); auto prof_handle = meto::vernier.start("test_recursion"); @@ -159,10 +152,11 @@ TEST(RecursionTest,DirectRecursion) zeroth_function(timings); double t2 = meto::vernier_get_wtime(); - double overall_time = t2-t1; + double overall_time = t2 - t1; - EXPECT_LE (timings.zeroth_function_total_time_, overall_time); - EXPECT_NEAR(timings.zeroth_function_total_time_, overall_time, time_tolerance); + EXPECT_LE(timings.zeroth_function_total_time_, overall_time); + EXPECT_NEAR(timings.zeroth_function_total_time_, overall_time, + time_tolerance); meto::vernier.stop(prof_handle_threaded); } @@ -175,8 +169,7 @@ TEST(RecursionTest,DirectRecursion) // Indirect recursion // -TEST(RecursionTest,IndirectRecursion) -{ +TEST(RecursionTest, IndirectRecursion) { meto::vernier.init(); auto prof_handle = meto::vernier.start("test_recursion"); @@ -193,11 +186,14 @@ TEST(RecursionTest,IndirectRecursion) double t2 = meto::vernier_get_wtime(); - double overall_time = t2-t1; - - EXPECT_LE (timings.first_function_total_time_, overall_time); - EXPECT_NEAR(timings.first_function_total_time_, overall_time, time_tolerance); - EXPECT_NEAR(timings.second_function_total_time_, timings.first_function_total_time_ - sleep_seconds, time_tolerance); + double overall_time = t2 - t1; + + EXPECT_LE(timings.first_function_total_time_, overall_time); + EXPECT_NEAR(timings.first_function_total_time_, overall_time, + time_tolerance); + EXPECT_NEAR(timings.second_function_total_time_, + timings.first_function_total_time_ - sleep_seconds, + time_tolerance); meto::vernier.stop(prof_handle_threaded); } @@ -205,4 +201,3 @@ TEST(RecursionTest,IndirectRecursion) meto::vernier.stop(prof_handle); meto::vernier.finalize(); } - diff --git a/tests/unit_tests/c++/test_regionname.cpp b/tests/unit_tests/c++/test_regionname.cpp index 7b9c9bd6..fa27fb98 100644 --- a/tests/unit_tests/c++/test_regionname.cpp +++ b/tests/unit_tests/c++/test_regionname.cpp @@ -4,9 +4,9 @@ under which the code may be used. \*----------------------------------------------------------------------------*/ -#include #include #include +#include #include #include "vernier.h" @@ -19,24 +19,25 @@ int const tid = 0; std::string tid_str(std::to_string(tid)); -std::string tid_bytes(reinterpret_cast(&tid), sizeof(tid)); +std::string tid_bytes(reinterpret_cast(&tid), sizeof(tid)); -TEST(RegionNameTest,NamesMatchTest) { +TEST(RegionNameTest, NamesMatchTest) { meto::vernier.init(); - //Start main region with name "Cappucino" - const auto& prof_cappucino = meto::vernier.start("Cappucino"); + // Start main region with name "Cappucino" + const auto &prof_cappucino = meto::vernier.start("Cappucino"); { SCOPED_TRACE("Problem with sub-region name"); // Start timing a sub-region with name "Latte" std::string myString = "Latte"; - const auto& prof_latte = meto::vernier.start(myString); + const auto &prof_latte = meto::vernier.start(myString); // Get subregion name out from profiler and check it is what we expect - std::string subregionName = meto::vernier.get_decorated_region_name(prof_latte, tid); + std::string subregionName = + meto::vernier.get_decorated_region_name(prof_latte, tid); EXPECT_EQ("Latte@" + tid_str, subregionName); meto::vernier.stop(prof_latte); @@ -46,7 +47,8 @@ TEST(RegionNameTest,NamesMatchTest) { SCOPED_TRACE("Problem with main region name"); // Get main region name out from profiler and test - std::string regionName = meto::vernier.get_decorated_region_name(prof_cappucino, tid); + std::string regionName = + meto::vernier.get_decorated_region_name(prof_cappucino, tid); EXPECT_EQ("Cappucino@" + tid_str, regionName); } @@ -54,8 +56,10 @@ TEST(RegionNameTest,NamesMatchTest) { SCOPED_TRACE("Problem with the profiler region name"); // Get profiler region name out from the profiler and test - auto const prof_self_handle = std::hash{}("__vernier__" + tid_bytes); - std::string profilerRegionName = meto::vernier.get_decorated_region_name(prof_self_handle, tid); + auto const prof_self_handle = + std::hash{}("__vernier__" + tid_bytes); + std::string profilerRegionName = + meto::vernier.get_decorated_region_name(prof_self_handle, tid); EXPECT_EQ("__vernier__@" + tid_str, profilerRegionName); } @@ -65,16 +69,18 @@ TEST(RegionNameTest,NamesMatchTest) { } /** - * @TODO Think about whether or not we want region name checks within code, i.e - * rules for what is and isn't allowed. See Issue #54. + * @TODO Think about whether or not we want region name checks within code, + * i.e rules for what is and isn't allowed. See Issue #54. * */ -/* Placeholder for testing different region names, which there are no checks for within the code yet... +/* Placeholder for testing different region names, which there are no checks for +within the code yet... TEST(RegionNameTest,InvalidsTest) { // Long name - const auto& A = vernier.hashtable_query_insert("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"); + const auto& A = +vernier.hashtable_query_insert("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"); // Nothing / blank space diff --git a/tests/unit_tests/f/CMakeLists.txt b/tests/unit_tests/f/CMakeLists.txt index bfb54417..2f80dc87 100644 --- a/tests/unit_tests/f/CMakeLists.txt +++ b/tests/unit_tests/f/CMakeLists.txt @@ -5,11 +5,11 @@ # ------------------------------------------------------------------------------ if(BUILD_FORTRAN_TESTS) # If build Fortran tests is on add tests - add_pfunit_ctest( test_vernier_f + add_pfunit_ctest( TestVernierFortran TEST_SOURCES test_vernier_mod.pf LINK_LIBRARIES ${CMAKE_PROJECT_NAME}_f MAX_PES 2 ) message(STATUS "${CMAKE_BINARY_DIR}/src/f/modules") - target_include_directories(test_vernier_f PUBLIC ${CMAKE_BINARY_DIR}/src/f/modules) + target_include_directories(TestVernierFortran PUBLIC ${CMAKE_BINARY_DIR}/src/f/modules) endif()