diff --git a/.gitignore b/.gitignore index b80ef85489..efc73a828e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ build transport lib/*-build lib/checkpoint +lib/papi lib/googletest lib/kokkos lib/vt-tv diff --git a/ci/azure/azure-clang-10-ubuntu-mpich.yml b/ci/azure/azure-clang-10-ubuntu-mpich.yml index 90f36ecdee..8dd331bed6 100644 --- a/ci/azure/azure-clang-10-ubuntu-mpich.yml +++ b/ci/azure/azure-clang-10-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-clang-11-ubuntu-mpich.yml b/ci/azure/azure-clang-11-ubuntu-mpich.yml index 7f7e949017..a28c051e46 100644 --- a/ci/azure/azure-clang-11-ubuntu-mpich.yml +++ b/ci/azure/azure-clang-11-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-clang-12-ubuntu-mpich.yml b/ci/azure/azure-clang-12-ubuntu-mpich.yml index c49dc12ae6..41b827edd8 100644 --- a/ci/azure/azure-clang-12-ubuntu-mpich.yml +++ b/ci/azure/azure-clang-12-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-clang-13-ubuntu-mpich.yml b/ci/azure/azure-clang-13-ubuntu-mpich.yml index 998a1c8d17..7c400d65a5 100644 --- a/ci/azure/azure-clang-13-ubuntu-mpich.yml +++ b/ci/azure/azure-clang-13-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-clang-14-ubuntu-mpich-papi.yml b/ci/azure/azure-clang-14-ubuntu-mpich-papi.yml new file mode 100644 index 0000000000..87262a5faa --- /dev/null +++ b/ci/azure/azure-clang-14-ubuntu-mpich-papi.yml @@ -0,0 +1,218 @@ +############################################################################### +############## Warning this is a generated file---do not modify ############### +############################################################################### + +name: PR tests (clang-14, ubuntu, mpich, papi) + +trigger: + branches: + include: + - develop + - main + +pr: + drafts: false + autoCancel: true + branches: + include: + - '*' + + +resources: +- repo: self + +variables: + tag: '$(Build.BuildId)' + REPO: lifflander1/vt + ARCH: amd64 + UBUNTU: 22.04 + COMPILER_TYPE: clang + COMPILER: clang-14 + HOST_COMPILER: clang-14 + BUILD_TYPE: release + ULIMIT_CORE: 0 + VT_CODE_COVERAGE: 0 + VT_LB: 1 + VT_TRACE: 1 + VT_TRACE_RT: 0 + VT_TRACE_ONLY: 1 + VT_MIMALLOC: 0 + VT_DOCS: 0 + VT_ASAN: 0 + VT_UBSAN: 0 + VT_WERROR: 1 + VT_POOL: 1 + VT_EXTENDED_TESTS: 1 + VT_TESTS_NUM_NODES: 2 + VT_EXTERNAL_FMT: 0 + VT_UNITY_BUILD: 1 + VT_PRODUCTION_BUILD: 0 + VT_FCONTEXT: 0 + VT_ZOLTAN: 0 + VT_CI_BUILD: 1 + VT_DIAGNOSTICS: 1 + VT_NO_COLOR: 1 + VT_BUILD_SHARED_LIBS: 0 + VT_INCLUSION: TPL + VT_DEBUG_VERBOSE: 1 + VT_KOKKOS_ENABLED: 0 + VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 + CMAKE_CXX_STANDARD: 17 + VT_CI_TEST_LB_SCHEMA: 0 + RUN_FULL_CI: true + CACHE: "$(Agent.TempDirectory)/cache/" + cache_name: ubuntu-clang-14-cache + volume_name: ubuntu-cpp + build_root: "$(CACHE)$(ARCH)-ubuntu-$(UBUNTU)-$(HOST_COMPILER)-$(COMPILER)-cache/" + TS: 0 + TS_YEAR: 0 + TS_MONTH: 0 + TS_DAY: 0 + + + +stages: +- stage: Build + displayName: Build image + jobs: + - job: Build + displayName: Build + pool: + vmImage: 'ubuntu-22.04' + timeoutInMinutes: 180 + steps: + - checkout: self + fetchDepth: 0 + - task: Bash@3 + displayName: Build timestamp for caching + continueOnError: true + condition: eq(variables['RUN_FULL_CI'], 'true') + inputs: + targetType: 'inline' + script: | + echo 'string(TIMESTAMP current_date "%H;%M;%S" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS]$val" + echo 'string(TIMESTAMP current_date "%Y" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_YEAR]$val" + echo 'string(TIMESTAMP current_date "%m" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_MONTH]$val" + echo 'string(TIMESTAMP current_date "%d" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_DAY]$val" + - task: Bash@3 + displayName: Output timestamp for caching + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetType: 'inline' + script: 'echo "my pipeline variable is $(TS) $(TS_YEAR) $(TS_MONTH) $(TS_DAY)"' + - task: Cache@2 + displayName: Update cache + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + securityNamespace: cache + key: $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) | $(TS_DAY) | $(TS) + path: '$(build_root)$(volume_name)/ccache' + restoreKeys: | + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) | $(TS_DAY) + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) + $(Agent.OS) | "$(cache_name)" + - task: Bash@3 + displayName: Check for changes in containers + condition: in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues') + inputs: + targetType: 'inline' + script: | + val=$(./scripts/check_containers.sh) + echo "##vso[task.setvariable variable=compose_command]$val" + - task: DockerCompose@1 + displayName: Pull container + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: '$(compose_command) ubuntu-cpp-clean' + - task: DockerCompose@1 + displayName: Build container + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: 'run ubuntu-cpp-clean' + env: + CODECOV_TOKEN: $(codecov_token) + - task: Bash@3 + displayName: Put compilation's and tests' logs in PR comment + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), and(succeededOrFailed(), eq(variables['Build.Reason'], 'PullRequest'))) + inputs: + targetType: 'inline' + script: | + ./scripts/report_logs_in_comment.sh \ + "$(build_root)$(volume_name)/vt/compilation_errors_warnings.out" \ + "$(build_root)$(volume_name)/vt/cmake-output.log" \ + "$(Build.BuildNumber)" \ + "$(System.PullRequest.PullRequestNumber)" \ + "$(Build.Repository.Name)" \ + "$GITHUB_PAT" \ + "$(Build.BuildId)" \ + "$(System.JobId)" \ + "$(Agent.JobStatus)" + env: + GITHUB_PAT: $(github_pat) + - task: DockerCompose@1 + displayName: Push container to registry + continueOnError: true + condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop')) + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerRegistryEndpoint: 'dockerRegistryConnection1' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: 'push ubuntu-cpp-clean' + - task: Bash@3 + displayName: Create artifacts + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetType: 'inline' + script: | + zip -j $(Agent.TempDirectory)/LastTest.log.gz $(build_root)$(volume_name)/vt/Testing/Temporary/LastTest.log + zip -j $(Agent.TempDirectory)/cmake-output.log.gz $(build_root)$(volume_name)/vt/cmake-output.log + - task: PublishPipelineArtifact@1 + displayName: Upload CMake test output artifact + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetPath: '$(Agent.TempDirectory)/LastTest.log.gz' + artifact: 'CMakeLastTestLog' + publishLocation: 'pipeline' + - task: PublishPipelineArtifact@1 + displayName: Upload CMake full output artifact + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetPath: '$(Agent.TempDirectory)/cmake-output.log.gz' + artifact: 'CMakeOutputLog' + publishLocation: 'pipeline' + - task: Bash@3 + displayName: Finish pipeline + condition: in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues') + inputs: + targetType: 'inline' + script: | + echo Done diff --git a/ci/azure/azure-clang-14-ubuntu-mpich-perf.yml b/ci/azure/azure-clang-14-ubuntu-mpich-perf.yml new file mode 100644 index 0000000000..b03e9a1620 --- /dev/null +++ b/ci/azure/azure-clang-14-ubuntu-mpich-perf.yml @@ -0,0 +1,218 @@ +############################################################################### +############## Warning this is a generated file---do not modify ############### +############################################################################### + +name: PR tests (clang-14, ubuntu, mpich, perf) + +trigger: + branches: + include: + - develop + - main + +pr: + drafts: false + autoCancel: true + branches: + include: + - '*' + + +resources: +- repo: self + +variables: + tag: '$(Build.BuildId)' + REPO: lifflander1/vt + ARCH: amd64 + UBUNTU: 22.04 + COMPILER_TYPE: clang + COMPILER: clang-14 + HOST_COMPILER: clang-14 + BUILD_TYPE: release + ULIMIT_CORE: 0 + VT_CODE_COVERAGE: 0 + VT_LB: 1 + VT_TRACE: 0 + VT_TRACE_RT: 0 + VT_TRACE_ONLY: 1 + VT_MIMALLOC: 0 + VT_DOCS: 0 + VT_ASAN: 0 + VT_UBSAN: 0 + VT_WERROR: 1 + VT_POOL: 1 + VT_EXTENDED_TESTS: 1 + VT_TESTS_NUM_NODES: 2 + VT_EXTERNAL_FMT: 0 + VT_UNITY_BUILD: 1 + VT_PRODUCTION_BUILD: 0 + VT_FCONTEXT: 0 + VT_ZOLTAN: 0 + VT_CI_BUILD: 1 + VT_DIAGNOSTICS: 1 + VT_NO_COLOR: 1 + VT_BUILD_SHARED_LIBS: 0 + VT_INCLUSION: TPL + VT_DEBUG_VERBOSE: 0 + VT_KOKKOS_ENABLED: 0 + VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 + CMAKE_CXX_STANDARD: 17 + VT_CI_TEST_LB_SCHEMA: 0 + RUN_FULL_CI: true + CACHE: "$(Agent.TempDirectory)/cache/" + cache_name: ubuntu-clang-14-cache + volume_name: ubuntu-cpp + build_root: "$(CACHE)$(ARCH)-ubuntu-$(UBUNTU)-$(HOST_COMPILER)-$(COMPILER)-cache/" + TS: 0 + TS_YEAR: 0 + TS_MONTH: 0 + TS_DAY: 0 + + + +stages: +- stage: Build + displayName: Build image + jobs: + - job: Build + displayName: Build + pool: + vmImage: 'ubuntu-22.04' + timeoutInMinutes: 180 + steps: + - checkout: self + fetchDepth: 0 + - task: Bash@3 + displayName: Build timestamp for caching + continueOnError: true + condition: eq(variables['RUN_FULL_CI'], 'true') + inputs: + targetType: 'inline' + script: | + echo 'string(TIMESTAMP current_date "%H;%M;%S" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS]$val" + echo 'string(TIMESTAMP current_date "%Y" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_YEAR]$val" + echo 'string(TIMESTAMP current_date "%m" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_MONTH]$val" + echo 'string(TIMESTAMP current_date "%d" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_DAY]$val" + - task: Bash@3 + displayName: Output timestamp for caching + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetType: 'inline' + script: 'echo "my pipeline variable is $(TS) $(TS_YEAR) $(TS_MONTH) $(TS_DAY)"' + - task: Cache@2 + displayName: Update cache + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + securityNamespace: cache + key: $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) | $(TS_DAY) | $(TS) + path: '$(build_root)$(volume_name)/ccache' + restoreKeys: | + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) | $(TS_DAY) + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) + $(Agent.OS) | "$(cache_name)" + - task: Bash@3 + displayName: Check for changes in containers + condition: in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues') + inputs: + targetType: 'inline' + script: | + val=$(./scripts/check_containers.sh) + echo "##vso[task.setvariable variable=compose_command]$val" + - task: DockerCompose@1 + displayName: Pull container + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: '$(compose_command) ubuntu-cpp-clean' + - task: DockerCompose@1 + displayName: Build container + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: 'run ubuntu-cpp-clean' + env: + CODECOV_TOKEN: $(codecov_token) + - task: Bash@3 + displayName: Put compilation's and tests' logs in PR comment + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), and(succeededOrFailed(), eq(variables['Build.Reason'], 'PullRequest'))) + inputs: + targetType: 'inline' + script: | + ./scripts/report_logs_in_comment.sh \ + "$(build_root)$(volume_name)/vt/compilation_errors_warnings.out" \ + "$(build_root)$(volume_name)/vt/cmake-output.log" \ + "$(Build.BuildNumber)" \ + "$(System.PullRequest.PullRequestNumber)" \ + "$(Build.Repository.Name)" \ + "$GITHUB_PAT" \ + "$(Build.BuildId)" \ + "$(System.JobId)" \ + "$(Agent.JobStatus)" + env: + GITHUB_PAT: $(github_pat) + - task: DockerCompose@1 + displayName: Push container to registry + continueOnError: true + condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop')) + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerRegistryEndpoint: 'dockerRegistryConnection1' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: 'push ubuntu-cpp-clean' + - task: Bash@3 + displayName: Create artifacts + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetType: 'inline' + script: | + zip -j $(Agent.TempDirectory)/LastTest.log.gz $(build_root)$(volume_name)/vt/Testing/Temporary/LastTest.log + zip -j $(Agent.TempDirectory)/cmake-output.log.gz $(build_root)$(volume_name)/vt/cmake-output.log + - task: PublishPipelineArtifact@1 + displayName: Upload CMake test output artifact + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetPath: '$(Agent.TempDirectory)/LastTest.log.gz' + artifact: 'CMakeLastTestLog' + publishLocation: 'pipeline' + - task: PublishPipelineArtifact@1 + displayName: Upload CMake full output artifact + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetPath: '$(Agent.TempDirectory)/cmake-output.log.gz' + artifact: 'CMakeOutputLog' + publishLocation: 'pipeline' + - task: Bash@3 + displayName: Finish pipeline + condition: in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues') + inputs: + targetType: 'inline' + script: | + echo Done diff --git a/ci/azure/azure-clang-14-ubuntu-mpich.yml b/ci/azure/azure-clang-14-ubuntu-mpich.yml index 99bcf4dfb0..80ef52adcc 100644 --- a/ci/azure/azure-clang-14-ubuntu-mpich.yml +++ b/ci/azure/azure-clang-14-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 1 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-clang-16-ubuntu-mpich.yml b/ci/azure/azure-clang-16-ubuntu-mpich.yml index 9fb0c8a723..c26be333c8 100644 --- a/ci/azure/azure-clang-16-ubuntu-mpich.yml +++ b/ci/azure/azure-clang-16-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 1 RUN_FULL_CI: true diff --git a/ci/azure/azure-clang-17-ubuntu-mpich-perf.yml b/ci/azure/azure-clang-17-ubuntu-mpich-perf.yml new file mode 100644 index 0000000000..a01722fca1 --- /dev/null +++ b/ci/azure/azure-clang-17-ubuntu-mpich-perf.yml @@ -0,0 +1,218 @@ +############################################################################### +############## Warning this is a generated file---do not modify ############### +############################################################################### + +name: PR tests (clang-17, ubuntu, mpich, perf) + +trigger: + branches: + include: + - develop + - main + +pr: + drafts: false + autoCancel: true + branches: + include: + - '*' + + +resources: +- repo: self + +variables: + tag: '$(Build.BuildId)' + REPO: lifflander1/vt + ARCH: amd64 + UBUNTU: 22.04 + COMPILER_TYPE: clang + COMPILER: clang-17 + HOST_COMPILER: clang-17 + BUILD_TYPE: release + ULIMIT_CORE: 0 + VT_CODE_COVERAGE: 0 + VT_LB: 1 + VT_TRACE: 0 + VT_TRACE_RT: 0 + VT_TRACE_ONLY: 1 + VT_MIMALLOC: 0 + VT_DOCS: 0 + VT_ASAN: 0 + VT_UBSAN: 0 + VT_WERROR: 1 + VT_POOL: 1 + VT_EXTENDED_TESTS: 1 + VT_TESTS_NUM_NODES: 2 + VT_EXTERNAL_FMT: 0 + VT_UNITY_BUILD: 1 + VT_PRODUCTION_BUILD: 0 + VT_FCONTEXT: 0 + VT_ZOLTAN: 0 + VT_CI_BUILD: 1 + VT_DIAGNOSTICS: 1 + VT_NO_COLOR: 1 + VT_BUILD_SHARED_LIBS: 0 + VT_INCLUSION: TPL + VT_DEBUG_VERBOSE: 0 + VT_KOKKOS_ENABLED: 0 + VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 1 + VT_PAPI_ENABLED: 0 + CMAKE_CXX_STANDARD: 17 + VT_CI_TEST_LB_SCHEMA: 0 + RUN_FULL_CI: true + CACHE: "$(Agent.TempDirectory)/cache/" + cache_name: ubuntu-clang-17-cache + volume_name: ubuntu-cpp + build_root: "$(CACHE)$(ARCH)-ubuntu-$(UBUNTU)-$(HOST_COMPILER)-$(COMPILER)-cache/" + TS: 0 + TS_YEAR: 0 + TS_MONTH: 0 + TS_DAY: 0 + + + +stages: +- stage: Build + displayName: Build image + jobs: + - job: Build + displayName: Build + pool: + vmImage: 'ubuntu-22.04' + timeoutInMinutes: 180 + steps: + - checkout: self + fetchDepth: 0 + - task: Bash@3 + displayName: Build timestamp for caching + continueOnError: true + condition: eq(variables['RUN_FULL_CI'], 'true') + inputs: + targetType: 'inline' + script: | + echo 'string(TIMESTAMP current_date "%H;%M;%S" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS]$val" + echo 'string(TIMESTAMP current_date "%Y" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_YEAR]$val" + echo 'string(TIMESTAMP current_date "%m" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_MONTH]$val" + echo 'string(TIMESTAMP current_date "%d" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_DAY]$val" + - task: Bash@3 + displayName: Output timestamp for caching + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetType: 'inline' + script: 'echo "my pipeline variable is $(TS) $(TS_YEAR) $(TS_MONTH) $(TS_DAY)"' + - task: Cache@2 + displayName: Update cache + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + securityNamespace: cache + key: $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) | $(TS_DAY) | $(TS) + path: '$(build_root)$(volume_name)/ccache' + restoreKeys: | + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) | $(TS_DAY) + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) + $(Agent.OS) | "$(cache_name)" + - task: Bash@3 + displayName: Check for changes in containers + condition: in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues') + inputs: + targetType: 'inline' + script: | + val=$(./scripts/check_containers.sh) + echo "##vso[task.setvariable variable=compose_command]$val" + - task: DockerCompose@1 + displayName: Pull container + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: '$(compose_command) ubuntu-cpp-clean' + - task: DockerCompose@1 + displayName: Build container + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: 'run ubuntu-cpp-clean' + env: + CODECOV_TOKEN: $(codecov_token) + - task: Bash@3 + displayName: Put compilation's and tests' logs in PR comment + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), and(succeededOrFailed(), eq(variables['Build.Reason'], 'PullRequest'))) + inputs: + targetType: 'inline' + script: | + ./scripts/report_logs_in_comment.sh \ + "$(build_root)$(volume_name)/vt/compilation_errors_warnings.out" \ + "$(build_root)$(volume_name)/vt/cmake-output.log" \ + "$(Build.BuildNumber)" \ + "$(System.PullRequest.PullRequestNumber)" \ + "$(Build.Repository.Name)" \ + "$GITHUB_PAT" \ + "$(Build.BuildId)" \ + "$(System.JobId)" \ + "$(Agent.JobStatus)" + env: + GITHUB_PAT: $(github_pat) + - task: DockerCompose@1 + displayName: Push container to registry + continueOnError: true + condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop')) + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerRegistryEndpoint: 'dockerRegistryConnection1' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: 'push ubuntu-cpp-clean' + - task: Bash@3 + displayName: Create artifacts + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetType: 'inline' + script: | + zip -j $(Agent.TempDirectory)/LastTest.log.gz $(build_root)$(volume_name)/vt/Testing/Temporary/LastTest.log + zip -j $(Agent.TempDirectory)/cmake-output.log.gz $(build_root)$(volume_name)/vt/cmake-output.log + - task: PublishPipelineArtifact@1 + displayName: Upload CMake test output artifact + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetPath: '$(Agent.TempDirectory)/LastTest.log.gz' + artifact: 'CMakeLastTestLog' + publishLocation: 'pipeline' + - task: PublishPipelineArtifact@1 + displayName: Upload CMake full output artifact + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetPath: '$(Agent.TempDirectory)/cmake-output.log.gz' + artifact: 'CMakeOutputLog' + publishLocation: 'pipeline' + - task: Bash@3 + displayName: Finish pipeline + condition: in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues') + inputs: + targetType: 'inline' + script: | + echo Done diff --git a/ci/azure/azure-clang-18-ubuntu-papi.yml b/ci/azure/azure-clang-18-ubuntu-papi.yml new file mode 100644 index 0000000000..6b149996f8 --- /dev/null +++ b/ci/azure/azure-clang-18-ubuntu-papi.yml @@ -0,0 +1,218 @@ +############################################################################### +############## Warning this is a generated file---do not modify ############### +############################################################################### + +name: PR tests (clang-18, ubuntu, papi) + +trigger: + branches: + include: + - develop + - main + +pr: + drafts: false + autoCancel: true + branches: + include: + - '*' + + +resources: +- repo: self + +variables: + tag: '$(Build.BuildId)' + REPO: lifflander1/vt + ARCH: amd64 + UBUNTU: 24.04 + COMPILER_TYPE: clang + COMPILER: clang-18 + HOST_COMPILER: clang-18 + BUILD_TYPE: release + ULIMIT_CORE: 0 + VT_CODE_COVERAGE: 0 + VT_LB: 1 + VT_TRACE: 0 + VT_TRACE_RT: 0 + VT_TRACE_ONLY: 1 + VT_MIMALLOC: 0 + VT_DOCS: 0 + VT_ASAN: 0 + VT_UBSAN: 0 + VT_WERROR: 1 + VT_POOL: 1 + VT_EXTENDED_TESTS: 1 + VT_TESTS_NUM_NODES: 2 + VT_EXTERNAL_FMT: 0 + VT_UNITY_BUILD: 1 + VT_PRODUCTION_BUILD: 0 + VT_FCONTEXT: 0 + VT_ZOLTAN: 0 + VT_CI_BUILD: 1 + VT_DIAGNOSTICS: 1 + VT_NO_COLOR: 1 + VT_BUILD_SHARED_LIBS: 0 + VT_INCLUSION: TPL + VT_DEBUG_VERBOSE: 0 + VT_KOKKOS_ENABLED: 0 + VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 1 + CMAKE_CXX_STANDARD: 17 + VT_CI_TEST_LB_SCHEMA: 0 + RUN_FULL_CI: true + CACHE: "$(Agent.TempDirectory)/cache/" + cache_name: ubuntu-clang-18-cache + volume_name: ubuntu-cpp + build_root: "$(CACHE)$(ARCH)-ubuntu-$(UBUNTU)-$(HOST_COMPILER)-$(COMPILER)-cache/" + TS: 0 + TS_YEAR: 0 + TS_MONTH: 0 + TS_DAY: 0 + + + +stages: +- stage: Build + displayName: Build image + jobs: + - job: Build + displayName: Build + pool: + vmImage: 'ubuntu-22.04' + timeoutInMinutes: 180 + steps: + - checkout: self + fetchDepth: 0 + - task: Bash@3 + displayName: Build timestamp for caching + continueOnError: true + condition: eq(variables['RUN_FULL_CI'], 'true') + inputs: + targetType: 'inline' + script: | + echo 'string(TIMESTAMP current_date "%H;%M;%S" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS]$val" + echo 'string(TIMESTAMP current_date "%Y" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_YEAR]$val" + echo 'string(TIMESTAMP current_date "%m" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_MONTH]$val" + echo 'string(TIMESTAMP current_date "%d" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_DAY]$val" + - task: Bash@3 + displayName: Output timestamp for caching + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetType: 'inline' + script: 'echo "my pipeline variable is $(TS) $(TS_YEAR) $(TS_MONTH) $(TS_DAY)"' + - task: Cache@2 + displayName: Update cache + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + securityNamespace: cache + key: $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) | $(TS_DAY) | $(TS) + path: '$(build_root)$(volume_name)/ccache' + restoreKeys: | + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) | $(TS_DAY) + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) + $(Agent.OS) | "$(cache_name)" + - task: Bash@3 + displayName: Check for changes in containers + condition: in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues') + inputs: + targetType: 'inline' + script: | + val=$(./scripts/check_containers.sh) + echo "##vso[task.setvariable variable=compose_command]$val" + - task: DockerCompose@1 + displayName: Pull container + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: '$(compose_command) ubuntu-cpp-clean' + - task: DockerCompose@1 + displayName: Build container + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: 'run ubuntu-cpp-clean' + env: + CODECOV_TOKEN: $(codecov_token) + - task: Bash@3 + displayName: Put compilation's and tests' logs in PR comment + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), and(succeededOrFailed(), eq(variables['Build.Reason'], 'PullRequest'))) + inputs: + targetType: 'inline' + script: | + ./scripts/report_logs_in_comment.sh \ + "$(build_root)$(volume_name)/vt/compilation_errors_warnings.out" \ + "$(build_root)$(volume_name)/vt/cmake-output.log" \ + "$(Build.BuildNumber)" \ + "$(System.PullRequest.PullRequestNumber)" \ + "$(Build.Repository.Name)" \ + "$GITHUB_PAT" \ + "$(Build.BuildId)" \ + "$(System.JobId)" \ + "$(Agent.JobStatus)" + env: + GITHUB_PAT: $(github_pat) + - task: DockerCompose@1 + displayName: Push container to registry + continueOnError: true + condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop')) + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerRegistryEndpoint: 'dockerRegistryConnection1' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: 'push ubuntu-cpp-clean' + - task: Bash@3 + displayName: Create artifacts + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetType: 'inline' + script: | + zip -j $(Agent.TempDirectory)/LastTest.log.gz $(build_root)$(volume_name)/vt/Testing/Temporary/LastTest.log + zip -j $(Agent.TempDirectory)/cmake-output.log.gz $(build_root)$(volume_name)/vt/cmake-output.log + - task: PublishPipelineArtifact@1 + displayName: Upload CMake test output artifact + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetPath: '$(Agent.TempDirectory)/LastTest.log.gz' + artifact: 'CMakeLastTestLog' + publishLocation: 'pipeline' + - task: PublishPipelineArtifact@1 + displayName: Upload CMake full output artifact + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetPath: '$(Agent.TempDirectory)/cmake-output.log.gz' + artifact: 'CMakeOutputLog' + publishLocation: 'pipeline' + - task: Bash@3 + displayName: Finish pipeline + condition: in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues') + inputs: + targetType: 'inline' + script: | + echo Done diff --git a/ci/azure/azure-clang-9-ubuntu-mpich.yml b/ci/azure/azure-clang-9-ubuntu-mpich.yml index 2bda7143f7..2303c2164b 100644 --- a/ci/azure/azure-clang-9-ubuntu-mpich.yml +++ b/ci/azure/azure-clang-9-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-clang-alpine-mpich.yml b/ci/azure/azure-clang-alpine-mpich.yml index 5e1d4fd27d..0e48324194 100644 --- a/ci/azure/azure-clang-alpine-mpich.yml +++ b/ci/azure/azure-clang-alpine-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-gcc-10-ubuntu-openmpi-spack.yml b/ci/azure/azure-gcc-10-ubuntu-openmpi-spack.yml index 41da998d91..66891b7a2d 100644 --- a/ci/azure/azure-gcc-10-ubuntu-openmpi-spack.yml +++ b/ci/azure/azure-gcc-10-ubuntu-openmpi-spack.yml @@ -50,6 +50,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: false diff --git a/ci/azure/azure-gcc-10-ubuntu-openmpi.yml b/ci/azure/azure-gcc-10-ubuntu-openmpi.yml index 255681d57c..2af7d2ed79 100644 --- a/ci/azure/azure-gcc-10-ubuntu-openmpi.yml +++ b/ci/azure/azure-gcc-10-ubuntu-openmpi.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-gcc-11-ubuntu-mpich.yml b/ci/azure/azure-gcc-11-ubuntu-mpich.yml index d84579d971..94d99635f8 100644 --- a/ci/azure/azure-gcc-11-ubuntu-mpich.yml +++ b/ci/azure/azure-gcc-11-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-gcc-12-ubuntu-mpich.yml b/ci/azure/azure-gcc-12-ubuntu-mpich.yml index 3909b9a04b..1fec733851 100644 --- a/ci/azure/azure-gcc-12-ubuntu-mpich.yml +++ b/ci/azure/azure-gcc-12-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 1 VT_KOKKOS_ENABLED: 1 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-gcc-12-ubuntu-vttv.yml b/ci/azure/azure-gcc-12-ubuntu-vttv.yml index fc797c8a73..af00521c52 100644 --- a/ci/azure/azure-gcc-12-ubuntu-vttv.yml +++ b/ci/azure/azure-gcc-12-ubuntu-vttv.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 1 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-gcc-13-ubuntu-mpich.yml b/ci/azure/azure-gcc-13-ubuntu-mpich.yml index dbd42a39be..92102336e1 100644 --- a/ci/azure/azure-gcc-13-ubuntu-mpich.yml +++ b/ci/azure/azure-gcc-13-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-gcc-14-ubuntu-perf.yml b/ci/azure/azure-gcc-14-ubuntu-perf.yml new file mode 100644 index 0000000000..196033d7e2 --- /dev/null +++ b/ci/azure/azure-gcc-14-ubuntu-perf.yml @@ -0,0 +1,218 @@ +############################################################################### +############## Warning this is a generated file---do not modify ############### +############################################################################### + +name: PR tests (gcc-14, ubuntu, perf) + +trigger: + branches: + include: + - develop + - main + +pr: + drafts: false + autoCancel: true + branches: + include: + - '*' + + +resources: +- repo: self + +variables: + tag: '$(Build.BuildId)' + REPO: lifflander1/vt + ARCH: amd64 + UBUNTU: 24.04 + COMPILER_TYPE: gnu + COMPILER: gcc-14 + HOST_COMPILER: gcc-14 + BUILD_TYPE: release + ULIMIT_CORE: 0 + VT_CODE_COVERAGE: 0 + VT_LB: 1 + VT_TRACE: 0 + VT_TRACE_RT: 0 + VT_TRACE_ONLY: 1 + VT_MIMALLOC: 0 + VT_DOCS: 0 + VT_ASAN: 0 + VT_UBSAN: 0 + VT_WERROR: 1 + VT_POOL: 1 + VT_EXTENDED_TESTS: 1 + VT_TESTS_NUM_NODES: 2 + VT_EXTERNAL_FMT: 0 + VT_UNITY_BUILD: 1 + VT_PRODUCTION_BUILD: 0 + VT_FCONTEXT: 0 + VT_ZOLTAN: 0 + VT_CI_BUILD: 1 + VT_DIAGNOSTICS: 1 + VT_NO_COLOR: 1 + VT_BUILD_SHARED_LIBS: 0 + VT_INCLUSION: TPL + VT_DEBUG_VERBOSE: 0 + VT_KOKKOS_ENABLED: 0 + VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 1 + VT_PAPI_ENABLED: 0 + CMAKE_CXX_STANDARD: 17 + VT_CI_TEST_LB_SCHEMA: 0 + RUN_FULL_CI: true + CACHE: "$(Agent.TempDirectory)/cache/" + cache_name: ubuntu-gcc-14-cache + volume_name: ubuntu-cpp + build_root: "$(CACHE)$(ARCH)-ubuntu-$(UBUNTU)-$(HOST_COMPILER)-$(COMPILER)-cache/" + TS: 0 + TS_YEAR: 0 + TS_MONTH: 0 + TS_DAY: 0 + + + +stages: +- stage: Build + displayName: Build image + jobs: + - job: Build + displayName: Build + pool: + vmImage: 'ubuntu-22.04' + timeoutInMinutes: 180 + steps: + - checkout: self + fetchDepth: 0 + - task: Bash@3 + displayName: Build timestamp for caching + continueOnError: true + condition: eq(variables['RUN_FULL_CI'], 'true') + inputs: + targetType: 'inline' + script: | + echo 'string(TIMESTAMP current_date "%H;%M;%S" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS]$val" + echo 'string(TIMESTAMP current_date "%Y" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_YEAR]$val" + echo 'string(TIMESTAMP current_date "%m" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_MONTH]$val" + echo 'string(TIMESTAMP current_date "%d" UTC)' > script + echo 'execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${current_date}")' >> script + val=$(cmake -P script) + echo "##vso[task.setvariable variable=TS_DAY]$val" + - task: Bash@3 + displayName: Output timestamp for caching + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetType: 'inline' + script: 'echo "my pipeline variable is $(TS) $(TS_YEAR) $(TS_MONTH) $(TS_DAY)"' + - task: Cache@2 + displayName: Update cache + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + securityNamespace: cache + key: $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) | $(TS_DAY) | $(TS) + path: '$(build_root)$(volume_name)/ccache' + restoreKeys: | + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) | $(TS_DAY) + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) | $(TS_MONTH) + $(Agent.OS) | "$(cache_name)" | $(TS_YEAR) + $(Agent.OS) | "$(cache_name)" + - task: Bash@3 + displayName: Check for changes in containers + condition: in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues') + inputs: + targetType: 'inline' + script: | + val=$(./scripts/check_containers.sh) + echo "##vso[task.setvariable variable=compose_command]$val" + - task: DockerCompose@1 + displayName: Pull container + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: '$(compose_command) ubuntu-cpp-clean' + - task: DockerCompose@1 + displayName: Build container + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: 'run ubuntu-cpp-clean' + env: + CODECOV_TOKEN: $(codecov_token) + - task: Bash@3 + displayName: Put compilation's and tests' logs in PR comment + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), and(succeededOrFailed(), eq(variables['Build.Reason'], 'PullRequest'))) + inputs: + targetType: 'inline' + script: | + ./scripts/report_logs_in_comment.sh \ + "$(build_root)$(volume_name)/vt/compilation_errors_warnings.out" \ + "$(build_root)$(volume_name)/vt/cmake-output.log" \ + "$(Build.BuildNumber)" \ + "$(System.PullRequest.PullRequestNumber)" \ + "$(Build.Repository.Name)" \ + "$GITHUB_PAT" \ + "$(Build.BuildId)" \ + "$(System.JobId)" \ + "$(Agent.JobStatus)" + env: + GITHUB_PAT: $(github_pat) + - task: DockerCompose@1 + displayName: Push container to registry + continueOnError: true + condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop')) + inputs: + projectName: darma-tasking-vt + containerregistrytype: 'Container Registry' + dockerRegistryEndpoint: 'dockerRegistryConnection1' + dockerComposeFile: '**/docker-compose.yml' + action: 'Run a Docker Compose command' + dockerComposeCommand: 'push ubuntu-cpp-clean' + - task: Bash@3 + displayName: Create artifacts + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetType: 'inline' + script: | + zip -j $(Agent.TempDirectory)/LastTest.log.gz $(build_root)$(volume_name)/vt/Testing/Temporary/LastTest.log + zip -j $(Agent.TempDirectory)/cmake-output.log.gz $(build_root)$(volume_name)/vt/cmake-output.log + - task: PublishPipelineArtifact@1 + displayName: Upload CMake test output artifact + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetPath: '$(Agent.TempDirectory)/LastTest.log.gz' + artifact: 'CMakeLastTestLog' + publishLocation: 'pipeline' + - task: PublishPipelineArtifact@1 + displayName: Upload CMake full output artifact + continueOnError: true + condition: and(eq(variables['RUN_FULL_CI'], 'true'), in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')) + inputs: + targetPath: '$(Agent.TempDirectory)/cmake-output.log.gz' + artifact: 'CMakeOutputLog' + publishLocation: 'pipeline' + - task: Bash@3 + displayName: Finish pipeline + condition: in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues') + inputs: + targetType: 'inline' + script: | + echo Done diff --git a/ci/azure/azure-gcc-9-ubuntu-mpich.yml b/ci/azure/azure-gcc-9-ubuntu-mpich.yml index 9552abaa2b..11e46fcf4f 100644 --- a/ci/azure/azure-gcc-9-ubuntu-mpich.yml +++ b/ci/azure/azure-gcc-9-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-intel-oneapi-icpc-ubuntu-mpich.yml b/ci/azure/azure-intel-oneapi-icpc-ubuntu-mpich.yml index 20c6394c36..ef777626e6 100644 --- a/ci/azure/azure-intel-oneapi-icpc-ubuntu-mpich.yml +++ b/ci/azure/azure-intel-oneapi-icpc-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-intel-oneapi-icpx-ubuntu-mpich.yml b/ci/azure/azure-intel-oneapi-icpx-ubuntu-mpich.yml index f5301e1df8..43c1da8bf4 100644 --- a/ci/azure/azure-intel-oneapi-icpx-ubuntu-mpich.yml +++ b/ci/azure/azure-intel-oneapi-icpx-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 1 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-nvidia-11-2-ubuntu-mpich.yml b/ci/azure/azure-nvidia-11-2-ubuntu-mpich.yml index da23bddc82..75a84a232c 100644 --- a/ci/azure/azure-nvidia-11-2-ubuntu-mpich.yml +++ b/ci/azure/azure-nvidia-11-2-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 0 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/azure/azure-nvidia-12-ubuntu-mpich.yml b/ci/azure/azure-nvidia-12-ubuntu-mpich.yml index 3c2ce1ba58..70643ceb7a 100644 --- a/ci/azure/azure-nvidia-12-ubuntu-mpich.yml +++ b/ci/azure/azure-nvidia-12-ubuntu-mpich.yml @@ -57,6 +57,8 @@ variables: VT_DEBUG_VERBOSE: 1 VT_KOKKOS_ENABLED: 0 VT_TV_ENABLED: 0 + VT_PERF_ENABLED: 0 + VT_PAPI_ENABLED: 0 CMAKE_CXX_STANDARD: 17 VT_CI_TEST_LB_SCHEMA: 0 RUN_FULL_CI: true diff --git a/ci/build_cpp.sh b/ci/build_cpp.sh index f1ddf2abdd..338d73ee27 100755 --- a/ci/build_cpp.sh +++ b/ci/build_cpp.sh @@ -114,6 +114,29 @@ then fi fi +if test "$VT_PAPI_ENABLED" -eq 1 && "$VT_PERF_ENABLED" -eq 1 +then + echo "Both PAPI and perf measurements are enabled; this is not supported. Please turn off one of these options. Exiting." + exit +fi + +if test "${VT_PAPI_ENABLED:-0}" -eq 1 +then + if test -d "${source_dir}/lib/papi" + then + { echo "papi already in lib... not downloading, building, and installing"; } 2>/dev/null + else + cd "${source_dir}/lib" + papi_rev="papi-7-2-0b1-t" + git clone -b "${papi_rev}" --depth 1 https://github.com/icl-utk-edu/papi.git + cd papi/src + export PAPI_BUILD=${build_dir}/papi + mkdir -p "$PAPI_BUILD" + CC="${CC:-cc}" F77="${F77:-gfortran}" ./configure --prefix="$PAPI_BUILD/install" + make "${dashj}" && make install + fi +fi + if test "${VT_ZOLTAN_ENABLED:-0}" -eq 1 then export Zoltan_DIR=${ZOLTAN_DIR:-""} @@ -141,9 +164,12 @@ cmake -G "${CMAKE_GENERATOR:-Ninja}" \ -Dvt_ubsan_enabled="${VT_UBSAN_ENABLED:-0}" \ -Dvt_werror_enabled="${VT_WERROR_ENABLED:-0}" \ -Dvt_pool_enabled="${VT_POOL_ENABLED:-1}" \ + -Dvt_build_tests="${VT_BUILD_TESTS:-1}" \ -Dvt_build_extended_tests="${VT_EXTENDED_TESTS_ENABLED:-1}" \ -Dvt_zoltan_enabled="${VT_ZOLTAN_ENABLED:-0}" \ -Dvt_tv_enabled="${VT_TV_ENABLED:-0}" \ + -Dvt_papi_enabled="${VT_PAPI_ENABLED:-0}" \ + -Dvt_perf_enabled="${VT_PERF_ENABLED:-0}" \ -Dvt_production_build_enabled="${VT_PRODUCTION_BUILD_ENABLED:-0}" \ -Dvt_unity_build_enabled="${VT_UNITY_BUILD_ENABLED:-0}" \ -Dvt_diagnostics_enabled="${VT_DIAGNOSTICS_ENABLED:-1}" \ @@ -163,6 +189,7 @@ cmake -G "${CMAKE_GENERATOR:-Ninja}" \ -DCMAKE_C_COMPILER="${CC:-cc}" \ -DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS:-}" \ -Dmagistrate_ROOT="$MAGISTRATE_BUILD/install" \ + -Dpapi_ROOT="${build_dir}/papi/install" \ -DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH:-}" \ -DCMAKE_INSTALL_PREFIX="$VT_BUILD/install" \ -Dvt_ci_build="${VT_CI_BUILD:-0}" \ diff --git a/ci/docker/ubuntu-clang-cpp.dockerfile b/ci/docker/ubuntu-clang-cpp.dockerfile index cd77b905fe..f1b9054793 100644 --- a/ci/docker/ubuntu-clang-cpp.dockerfile +++ b/ci/docker/ubuntu-clang-cpp.dockerfile @@ -18,6 +18,7 @@ RUN apt-get update -y -q && \ ${ubsan_enabled:+llvm-$(echo ${compiler} | cut -d- -f2)} \ brotli \ ca-certificates \ + linux-tools-$(uname -r) \ ccache \ curl \ git \ diff --git a/ci/docker/ubuntu-gnu-cpp.dockerfile b/ci/docker/ubuntu-gnu-cpp.dockerfile index 5469cd6098..28c62c58f6 100644 --- a/ci/docker/ubuntu-gnu-cpp.dockerfile +++ b/ci/docker/ubuntu-gnu-cpp.dockerfile @@ -20,6 +20,7 @@ RUN apt-get update -y -q && \ ${zoltan_enabled:+gfortran-$(echo ${compiler} | cut -d- -f2)} \ brotli \ ca-certificates \ + linux-tools-$(uname -r) \ ccache \ curl \ git \ diff --git a/cmake/FindPAPI.cmake b/cmake/FindPAPI.cmake new file mode 100644 index 0000000000..66d652b4b9 --- /dev/null +++ b/cmake/FindPAPI.cmake @@ -0,0 +1,21 @@ +# Set minimum CMake version +cmake_minimum_required(VERSION 3.23 FATAL_ERROR) + + +# Find the PAPI include directory and library +message(STATUS "Finding PAPI, PAPI_BUILD_ROOT: ${papi_ROOT}") +find_path(PAPI_INCLUDE_DIR NAMES papi.h HINTS ${papi_ROOT}/include) +find_library(PAPI_LIBRARY NAMES papi HINTS ${papi_ROOT}/lib) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(PAPI DEFAULT_MSG PAPI_LIBRARY PAPI_INCLUDE_DIR) + +if(PAPI_FOUND AND NOT TARGET PAPI::PAPI) + add_library(PAPI::PAPI UNKNOWN IMPORTED) + set_target_properties(PAPI::PAPI PROPERTIES + IMPORTED_LOCATION "{PAPI_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${PAPI_INCLUDE_DIR}" + ) +endif() + +mark_as_advanced(PAPI_INCLUDE_DIR PAPI_LIBRARY) diff --git a/cmake/configure_options.cmake b/cmake/configure_options.cmake index e3509db735..bfde60cbe2 100644 --- a/cmake/configure_options.cmake +++ b/cmake/configure_options.cmake @@ -100,6 +100,8 @@ define_option(vt_rdma_tests_enabled "RDMA tests" "Build VT with RDMA tests enabl ON vt_feature_cmake_rdma_tests ) +define_option(vt_papi_enabled "PAPI task measurement" "Build VT with PAPI to measure low level metrics of interest" OFF vt_feature_cmake_papi) +define_option(vt_perf_enabled "perf task measurement" "Build VT with perf to measure low level metrics of interest" OFF vt_feature_cmake_perf) ##################################################### #################### DIAGNOSTICS #################### diff --git a/cmake/link_vt.cmake b/cmake/link_vt.cmake index cc3c9ad340..107e78756e 100644 --- a/cmake/link_vt.cmake +++ b/cmake/link_vt.cmake @@ -35,6 +35,7 @@ function(link_target_with_vt) LINK_JSON LINK_BROTLI LINK_VT_TV + LINK_PAPI ) set( multiValueArg @@ -230,6 +231,22 @@ function(link_target_with_vt) ) endif() + if (NOT DEFINED ARG_LINK_PAPI AND ${ARG_DEFAULT_LINK_SET} OR ARG_LINK_PAPI) + if (vt_papi_enabled) + if (${ARG_DEBUG_LINK}) + message(STATUS "link_target_with_vt: papi=${ARG_LINK_PAPI}") + endif() + # message(STATUS "target_link_libraries: ${ARG_TARGET} PUBLIC ${ARG_BUILD_TYPE} ${PAPI_LIBRARY}") + # message(STATUS "target_include_directories: ${ARG_TARGET} PUBLIC ${ARG_BUILD_TYPE} ${PAPI_INCLUDE_DIR}") + target_link_libraries( + ${ARG_TARGET} PUBLIC ${ARG_BUILD_TYPE} ${PAPI_LIBRARY} + ) + target_include_directories( + ${ARG_TARGET} PUBLIC ${ARG_BUILD_TYPE} ${PAPI_INCLUDE_DIR} + ) + endif() + endif() + if (${vt_mimalloc_enabled}) if (${ARG_DEBUG_LINK}) message(STATUS "link_target_with_vt: mimalloc=${vt_mimalloc_enabled}") diff --git a/cmake/load_packages.cmake b/cmake/load_packages.cmake index 754b62ea43..84bddc8a43 100644 --- a/cmake/load_packages.cmake +++ b/cmake/load_packages.cmake @@ -18,5 +18,11 @@ include(cmake/load_libunwind.cmake) # Optionally link with Zoltan include(cmake/load_zoltan_package.cmake) +# If enabled, link with PAPI +include(cmake/load_papi.cmake) + +# If enabled, test if perf is available and works +include(cmake/load_perf.cmake) + # Tests include(cmake/test_vt.cmake) diff --git a/cmake/load_papi.cmake b/cmake/load_papi.cmake new file mode 100644 index 0000000000..dee7f778d2 --- /dev/null +++ b/cmake/load_papi.cmake @@ -0,0 +1,12 @@ +set(vt_papi_found "0") + +if (vt_papi_enabled) + if (vt_perf_enabled) + set(vt_papi_found "0") + set(vt_papi_enabled "0") + message(FATAL_ERROR "Both PAPI and perf measurements are enabled; this will cause errors, please turn off one of these options. Exiting.") + endif () + find_package(PAPI REQUIRED) + message(STATUS: "FOUND PAPI: PAPI LIBRARY: ${PAPI_LIBRARY}\n PAPI INCLUDE DIR: ${PAPI_INCLUDE_DIR}") + set(vt_papi_found "1") +endif () diff --git a/cmake/load_perf.cmake b/cmake/load_perf.cmake new file mode 100644 index 0000000000..663154a924 --- /dev/null +++ b/cmake/load_perf.cmake @@ -0,0 +1,48 @@ +set(vt_perf_found "0") + +if (vt_perf_enabled) + if (vt_papi_enabled) + message(FATAL_ERROR "Both PAPI and perf measurements are enabled; this will cause errors, please turn off one of these options. Exiting.") + endif () + # check if linux + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + # check if there's the perf header we need + include(CheckIncludeFiles) + CHECK_INCLUDE_FILES("linux/perf_event.h" HAVE_PERF_EVENT_H) + if (HAVE_PERF_EVENT_H) + # check if the kernel is recent enough + string(REPLACE "." ";" VERSION_LIST ${CMAKE_SYSTEM_VERSION}) + list(GET VERSION_LIST 0 KERNEL_MAJOR_VERSION) + if (KERNEL_MAJOR_VERSION GREATER_EQUAL 4) + # check if a simple perf stat runs without issues + execute_process( + COMMAND perf stat pwd + RESULT_VARIABLE PERF_STAT_RESULT + OUTPUT_QUIET + ERROR_QUIET + ) + if (PERF_STAT_RESULT EQUAL 0) + message(STATUS "Perf measurements enabled.") + set(vt_perf_enabled "1") + set(vt_perf_found "1") + else () + message(WARNING "Perf disabled: \"perf stat\" results in non-zero error code.") + set(vt_perf_enabled "0") + set(vt_perf_found "0") + endif () + else () + message(WARNING "Perf disabled: kernel major version is less than 4.") + set(vt_perf_enabled "0") + set(vt_perf_found "0") + endif () + else () + message(WARNING "Perf disabled: could not find \"perf_event.h\".") + set(vt_perf_enabled "0") + set(vt_perf_found "0") + endif () + else () + message(WARNING "Perf disabled: system name is not Linux.") + set(vt_perf_enabled "0") + set(vt_perf_found "0") + endif () +endif () diff --git a/cmake_config.h.in b/cmake_config.h.in index 86585007df..2ab6b55c57 100644 --- a/cmake_config.h.in +++ b/cmake_config.h.in @@ -68,6 +68,8 @@ #define vt_feature_cmake_external_fmt @vt_feature_cmake_external_fmt@ #define vt_feature_cmake_libunwind @vt_feature_cmake_libunwind@ #define vt_feature_cmake_tv @vt_feature_cmake_tv@ +#define vt_feature_cmake_papi @vt_feature_cmake_papi@ +#define vt_feature_cmake_perf @vt_feature_cmake_perf@ #define vt_detected_max_num_nodes @cmake_detected_max_num_nodes@ diff --git a/docker-compose.yml b/docker-compose.yml index f2e4f50c8a..ecaff52fd1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -103,6 +103,8 @@ x-vtopts: &vtopts VT_EXTENDED_TESTS_ENABLED: ${VT_EXTENDED_TESTS:-1} VT_CODE_COVERAGE: ${VT_CODE_COVERAGE:-0} VT_KOKKOS_ENABLED: ${VT_KOKKOS_ENABLED:-0} + VT_PERF_ENABLED: ${VT_PERF_ENABLED:-0} + VT_PAPI_ENABLED: ${VT_PAPI_ENABLED:-0} https_proxy: ${PROXY-} http_proxy: ${PROXY-} LSAN_OPTIONS: ${LSAN_OPTIONS-} diff --git a/examples/collection/CMakeLists.txt b/examples/collection/CMakeLists.txt index 7daf1df4d4..db318be6f2 100644 --- a/examples/collection/CMakeLists.txt +++ b/examples/collection/CMakeLists.txt @@ -12,6 +12,12 @@ set( transpose 4d_collection ) +if (vt_papi_enabled AND vt_papi_found) + list(APPEND COLLECTION_EXAMPLES do_flops_papi) +endif() +if (vt_perf_enabled AND vt_perf_found) + list(APPEND COLLECTION_EXAMPLES do_flops_perf) +endif() foreach(EXAMPLE_NAME ${COLLECTION_EXAMPLES}) # message("Example: building collection example >>>>> ${EXAMPLE_NAME}") diff --git a/examples/collection/do_flops_papi.cc b/examples/collection/do_flops_papi.cc new file mode 100644 index 0000000000..c281fa4401 --- /dev/null +++ b/examples/collection/do_flops_papi.cc @@ -0,0 +1,285 @@ +/* +//@HEADER +// ***************************************************************************** +// +// do_flops_papi.cc +// DARMA/vt => Virtual Transport +// +// Copyright 2019-2024 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +/// [Do Flops example] + +#include +#include + +#include +#include +#include + +static constexpr std::size_t const default_nrow_object = 8; +static constexpr std::size_t const default_num_objs = 1; +static constexpr double const default_tol = 1.0e-02; +static constexpr std::size_t const default_flops_per_iter = 100000; + + +double pi(uint64_t n) { + double sum = 0.0; + int sign = 1; + for (uint64_t i = 0; i < n; ++i) { + sum += sign/(2.0*i+1.0); + sign *= -1; + } + return 4.0*sum; +} + +struct NodeObj { + bool is_finished_ = false; + void workFinishedHandler() { is_finished_ = true; } + bool isWorkFinished() { return is_finished_; } +}; +using NodeObjProxy = vt::objgroup::proxy::Proxy; + +struct GenericWork : vt::Collection { + +private: + size_t iter_ = 0; + size_t msgReceived_ = 0, totalReceive_ = 0; + size_t numObjs_ = 1; + size_t flopsPerIter_ = default_flops_per_iter; + size_t maxIter_ = 8; + NodeObjProxy objProxy_; + +public: + explicit GenericWork() : + iter_(0), msgReceived_(0), totalReceive_(0), + numObjs_(1), flopsPerIter_(default_flops_per_iter), maxIter_(8) + { } + + using BlankMsg = vt::CollectionMessage; + + struct WorkMsg : vt::CollectionMessage { + size_t numObjects = 0; + size_t flopsPerIter = 0; + size_t iterMax = 0; + NodeObjProxy objProxy; + + WorkMsg() = default; + + WorkMsg(const size_t nobjs, const size_t flops, const size_t itMax, NodeObjProxy proxy) : + numObjects(nobjs), flopsPerIter(flops), iterMax(itMax), objProxy(proxy) + { } + }; + + void checkCompleteCB() { + auto const iter_max_reached = iter_ > maxIter_; + + if (iter_max_reached) { + fmt::print("\n Maximum Number of Iterations Reached. \n\n"); + objProxy_.broadcast<&NodeObj::workFinishedHandler>(); + } else { + fmt::print(" ## ITER {} completed. \n", iter_); + } + } + + void doIteration() { + iter_ += 1; + fmt::print("-- Starting Iteration --\n"); + + vt::theContext()->getTask()->startMetrics(); + + // ---------------------------------------------------------- + // test non packed double precision floating point operations + // should result in ~4*n of these operations + + double p; + p = pi(10000000); + fmt::print("pi: {}\n", p); + // ---------------------------------------------------------- + + auto proxy = this->getCollectionProxy(); + proxy.reduce<&GenericWork::checkCompleteCB, vt::collective::MaxOp>( + proxy[0] + ); + + vt::theContext()->getTask()->stopMetrics(); + std::unordered_map res = vt::theContext()->getTask()->getMetrics(); + for (auto [name, value] : res) { + fmt::print(" {}: {}\n", name, value); + } + + fmt::print("-- Stopping Iteration --\n"); + } + + struct VecMsg : vt::CollectionMessage { + using MessageParentType = vt::CollectionMessage; + vt_msg_serialize_if_needed_by_parent_or_type1(vt::IdxBase); + + VecMsg() = default; + + explicit VecMsg(vt::IdxBase const& in_index) : + vt::CollectionMessage(), + from_index(in_index) + { } + + template + void serialize(Serializer& s) { + MessageParentType::serialize(s); + s | from_index; + } + + vt::IdxBase from_index = 0; + }; + + void exchange(VecMsg *msg) { + msgReceived_ += 1; + + if (msgReceived_ == totalReceive_) { + msgReceived_ = 0; + doIteration(); + } + } + + void doIter([[maybe_unused]] BlankMsg *msg) { + if (numObjs_ == 1) { + doIteration(); + return; + } + + vt::IdxBase const myIdx = getIndex().x(); + auto proxy = this->getCollectionProxy(); + + if (myIdx > 0) { + proxy[myIdx - 1].send( + VecMsg(myIdx) + ); + } + + if (size_t(myIdx) < numObjs_ - 1) { + proxy[myIdx + 1].send( + VecMsg(myIdx) + ); + } + } + + void init() { + totalReceive_ = 2; + + if (getIndex().x() == 0) { + totalReceive_ -= 1; + } + + if (getIndex().x() == numObjs_ - 1) { + totalReceive_ -= 1; + } + } + + void init(WorkMsg* msg) { + numObjs_ = msg->numObjects; + flopsPerIter_ = msg->flopsPerIter; + maxIter_ = msg->iterMax; + objProxy_ = msg->objProxy; + + init(); + } +}; + +bool isWorkDone(vt::objgroup::proxy::Proxy const& proxy) { + auto const this_node = vt::theContext()->getNode(); + return proxy[this_node].invoke<&NodeObj::isWorkFinished>(); +} + +int main(int argc, char** argv) { + size_t num_objs = default_num_objs; + size_t flopsPerIter = default_flops_per_iter; + size_t maxIter = 8; + + std::string name(argv[0]); + + vt::initialize(argc, argv); + + vt::NodeType this_node = vt::theContext()->getNode(); + vt::NodeType num_nodes = vt::theContext()->getNumNodes(); + + if (argc == 1) { + if (this_node == 0) { + fmt::print(stderr, "{}: using default arguments since none provided\n", name); + } + num_objs = default_num_objs * num_nodes; + } else if (argc == 2) { + num_objs = static_cast(strtol(argv[1], nullptr, 10)); + } else if (argc == 3) { + num_objs = static_cast(strtol(argv[1], nullptr, 10)); + flopsPerIter = static_cast(strtol(argv[2], nullptr, 10)); + } else if (argc == 4) { + num_objs = static_cast(strtol(argv[1], nullptr, 10)); + flopsPerIter = static_cast(strtol(argv[2], nullptr, 10)); + maxIter = static_cast(strtol(argv[3], nullptr, 10)); + } else { + fmt::print(stderr, "usage: {} \n", name); + return 1; + } + + auto grp_proxy = vt::theObjGroup()->makeCollective("examples_generic_work"); + using BaseIndexType = typename vt::Index1D::DenseIndexType; + auto range = vt::Index1D(static_cast(num_objs)); + + auto col_proxy = vt::makeCollection("examples_generic_work") + .bounds(range) + .bulkInsert() + .wait(); + + vt::runInEpochCollective([col_proxy, grp_proxy, num_objs, flopsPerIter, maxIter]{ + col_proxy.broadcastCollective( + num_objs, flopsPerIter, maxIter, grp_proxy + ); + }); + + while(!isWorkDone(grp_proxy)) { + vt::runInEpochCollective([col_proxy]{ + col_proxy.broadcastCollective< + GenericWork::BlankMsg, &GenericWork::doIter + >(); + }); + + vt::thePhase()->nextPhaseCollective(); + } + + vt::finalize(); + + return 0; +} +/// [Do Flops example] diff --git a/examples/collection/do_flops_perf.cc b/examples/collection/do_flops_perf.cc new file mode 100644 index 0000000000..a664763588 --- /dev/null +++ b/examples/collection/do_flops_perf.cc @@ -0,0 +1,149 @@ +/* +//@HEADER +// ***************************************************************************** +// +// do_flops_perf.cc +// DARMA/vt => Virtual Transport +// +// Copyright 2019-2024 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +/// [Do Flops example] + +#include +#include + +#include + +static constexpr std::size_t const default_num_objs = 100; +static constexpr std::size_t const default_flops_per_iter = 100000; + +double pi(uint64_t n) { + double sum = 0.0; + int sign = 1; + for (uint64_t i = 0; i < n; ++i) { + sum += sign/(2.0*i+1.0); + sign *= -1; + } + return 4.0*sum; +} + +struct GenericWork : vt::Collection { + void doIteration() { + iter_ += 1; + fmt::print("-- Starting Iteration --\n"); + + vt::theContext()->getTask()->startMetrics(); + + // ---------------------------------------------------------- + // test non packed double precision floating point operations + // should result in ~4*n of these operations + double p = pi(10000000); + fmt::print("pi: {}\n", p); + // ---------------------------------------------------------- + + vt::theContext()->getTask()->stopMetrics(); + std::unordered_map res = vt::theContext()->getTask()->getMetrics(); + for (auto [name, value] : res) { + fmt::print(" {}: {}\n", name, value); + } + + fmt::print("-- Stopping Iteration --\n"); + } + + void init(int in_flops_per_iter) { + flopsPerIter_ = in_flops_per_iter; + } + +private: + size_t flopsPerIter_ = 0; +}; + +int main(int argc, char** argv) { + size_t num_objs = default_num_objs; + size_t flopsPerIter = default_flops_per_iter; + size_t maxIter = 8; + + std::string name(argv[0]); + + vt::initialize(argc, argv); + + vt::NodeType this_node = vt::theContext()->getNode(); + vt::NodeType num_nodes = vt::theContext()->getNumNodes(); + + if (argc == 1) { + if (this_node == 0) { + fmt::print(stderr, "{}: using default arguments since none provided\n", name); + } + num_objs = default_num_objs * num_nodes; + } else if (argc == 2) { + num_objs = static_cast(strtol(argv[1], nullptr, 10)); + } else if (argc == 3) { + num_objs = static_cast(strtol(argv[1], nullptr, 10)); + flopsPerIter = static_cast(strtol(argv[2], nullptr, 10)); + } else if (argc == 4) { + num_objs = static_cast(strtol(argv[1], nullptr, 10)); + flopsPerIter = static_cast(strtol(argv[2], nullptr, 10)); + maxIter = static_cast(strtol(argv[3], nullptr, 10)); + } else { + fmt::print(stderr, "usage: {} \n", name); + return 1; + } + + using BaseIndexType = typename vt::Index1D::DenseIndexType; + auto range = vt::Index1D(static_cast(num_objs)); + + auto col_proxy = vt::makeCollection("examples_generic_work") + .bounds(range) + .bulkInsert() + .wait(); + + vt::runInEpochCollective([&]{ + col_proxy.broadcastCollective<&GenericWork::init>(flopsPerIter); + }); + + for (std::size_t i = 0; i < maxIter; i++) { + vt::runInEpochCollective([&]{ + col_proxy.broadcastCollective<&GenericWork::doIteration>(flopsPerIter); + }); + vt::thePhase()->nextPhaseCollective(); + } + + vt::finalize(); + + return 0; +} +/// [Do Flops example] diff --git a/scripts/workflow-azure-template.yml b/scripts/workflow-azure-template.yml index a54ba86de5..4db9f7d50a 100644 --- a/scripts/workflow-azure-template.yml +++ b/scripts/workflow-azure-template.yml @@ -45,6 +45,8 @@ variables: VT_DEBUG_VERBOSE: [% vt_debug_verbose %] VT_KOKKOS_ENABLED: [% vt_kokkos_enabled %] VT_TV_ENABLED: [% vt_tv_enabled %] + VT_PERF_ENABLED: [% vt_perf_enabled %] + VT_PAPI_ENABLED: [% vt_papi_enabled %] CMAKE_CXX_STANDARD: [% cmake_cxx_standard %] VT_CI_TEST_LB_SCHEMA: [% vt_ci_test_lb_schema %] RUN_FULL_CI: [% run_full_ci %] @@ -129,7 +131,7 @@ stages: containerregistrytype: 'Container Registry' dockerComposeFile: '**/docker-compose.yml' action: 'Run a Docker Compose command' - dockerComposeCommand: '$(compose_command) [% docker_target %]' + dockerComposeCommand: '$(compose_command) [% docker_target %][% IF privileged %] --privileged[% END %]' - task: DockerCompose@1 displayName: Build container inputs: @@ -137,7 +139,7 @@ stages: containerregistrytype: 'Container Registry' dockerComposeFile: '**/docker-compose.yml' action: 'Run a Docker Compose command' - dockerComposeCommand: 'run [% docker_target %]' + dockerComposeCommand: 'run [% IF privileged %]--privileged [% END %][% docker_target %]' env: CODECOV_TOKEN: $(codecov_token) - task: Bash@3 diff --git a/scripts/workflows-azure.ini b/scripts/workflows-azure.ini index 382448cc39..3f1369378e 100644 --- a/scripts/workflows-azure.ini +++ b/scripts/workflows-azure.ini @@ -47,6 +47,9 @@ vt_debug_verbose = 0 vt_kokkos_enabled = 0 run_full_ci = true vt_tv_enabled = 0 +privileged = 0 +vt_perf_enabled = 0 +vt_papi_enabled = 0 [PR-tests-intel-oneAPI] test_configuration = "intel icpx, ubuntu, mpich, verbose" @@ -241,3 +244,27 @@ distro = 22.04 output_name = ci/azure/azure-gcc-12-ubuntu-vttv.yml vt_tv_enabled = 1 vt_trace_only = 0 + +[PR-tests-gcc-14-perf] +test_configuration = "gcc-14, ubuntu, perf" +compiler_type = gnu +compiler = gcc-14 +distro = 24.04 +output_name = ci/azure/azure-gcc-14-ubuntu-perf.yml +vt_perf_enabled = 1 + +[PR-tests-clang-17-perf] +test_configuration = "clang-17, ubuntu, mpich, perf" +compiler_type = clang +compiler = clang-17 +distro = 22.04 +output_name = ci/azure/azure-clang-17-ubuntu-mpich-perf.yml +vt_perf_enabled = 1 + +[PR-tests-clang-18-papi] +test_configuration = "clang-18, ubuntu, papi" +compiler_type = clang +compiler = clang-18 +distro = 24.04 +output_name = ci/azure/azure-clang-18-ubuntu-papi.yml +vt_papi_enabled = 1 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 380c8d4a4b..6572399cae 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,6 +22,13 @@ set(TOP_LEVEL_SUBDIRS context event handler sequence termination scheduler standalone runtime trace timing demangle rdmahandle ) +if(vt_perf_enabled) + list( + APPEND + TOP_LEVEL_SUBDIRS + metrics + ) +endif() set( PROJECT_SUBDIRS_LIST # Add component along with sub-directories diff --git a/src/vt/configs/features/features_defines.h b/src/vt/configs/features/features_defines.h index 8186bdca24..a38618c166 100644 --- a/src/vt/configs/features/features_defines.h +++ b/src/vt/configs/features/features_defines.h @@ -75,6 +75,8 @@ #define vt_feature_fmt_external 0 || vt_feature_cmake_external_fmt #define vt_feature_libunwind 0 || vt_feature_cmake_libunwind #define vt_feature_tv 0 || vt_feature_cmake_tv +#define vt_feature_papi 0 || vt_feature_cmake_papi +#define vt_feature_perf 0 || vt_feature_cmake_perf #define vt_check_enabled(test_option) (vt_feature_ ## test_option != 0) diff --git a/src/vt/configs/features/features_featureswitch.h b/src/vt/configs/features/features_featureswitch.h index 6a65a249ae..0acb0afbfc 100644 --- a/src/vt/configs/features/features_featureswitch.h +++ b/src/vt/configs/features/features_featureswitch.h @@ -64,5 +64,7 @@ "debug prints disabled)" #define vt_feature_str_trace_enabled "Tracing Projections" #define vt_feature_str_zoltan "Zoltan for load balancing" +#define vt_feature_str_papi "PAPI for event measurement" +#define vt_feature_str_perf "perf for event measurement" #endif /*INCLUDED_VT_CONFIGS_FEATURES_FEATURES_FEATURESWITCH_H*/ diff --git a/src/vt/context/context.cc b/src/vt/context/context.cc index c3ea408aa8..1d50450dd2 100644 --- a/src/vt/context/context.cc +++ b/src/vt/context/context.cc @@ -65,6 +65,14 @@ struct RunnableNew {}; #include +#if vt_check_enabled(papi) +# include +void handle_papi_error (int retval) +{ + vtAbort(fmt::format("PAPI error {}: {}\n", retval, PAPI_strerror(retval))); +} +#endif + // This cannot use the normal debug_print macros because they rely on context // being live to print contextual information #define DEBUG_VT_CONTEXT 0 @@ -90,6 +98,20 @@ Context::Context([[maybe_unused]] bool const is_interop, MPI_Comm comm) { communicator_ = comm; numNodes_ = static_cast(numNodesLocal); thisNode_ = static_cast(thisNodeLocal); + +#if vt_check_enabled(papi) + int retval; + + /* Initialize the PAPI library */ + retval = PAPI_library_init(PAPI_VER_CURRENT); + if (retval != PAPI_VER_CURRENT) + handle_papi_error(retval); + + /* Enable and initialize multiplex support */ + retval = PAPI_multiplex_init(); + if (retval != PAPI_OK) + handle_papi_error(retval); +#endif } Context::~Context() { diff --git a/src/vt/context/runnable_context/lb_data.cc b/src/vt/context/runnable_context/lb_data.cc index af89df779b..ff765e03d1 100644 --- a/src/vt/context/runnable_context/lb_data.cc +++ b/src/vt/context/runnable_context/lb_data.cc @@ -78,4 +78,15 @@ typename LBData::ElementIDStruct const& LBData::getCurrentElementID() const { return cur_elm_id_; } +#if vt_check_enabled(papi) +std::unordered_map LBData::getPAPIMetrics() { + std::unordered_map papi_metrics = papi_data_->events; + papi_metrics["real_time"] = papi_data_->end_real_usec - papi_data_->start_real_usec; + papi_metrics["real_cycles"] = papi_data_->end_real_cycles - papi_data_->start_real_cycles; + papi_metrics["virt_time"] = papi_data_->end_virt_usec - papi_data_->start_virt_usec; + papi_metrics["virt_cycles"] = papi_data_->end_virt_cycles - papi_data_->start_virt_cycles; + return papi_metrics; +} +#endif + }} /* end namespace vt::ctx */ diff --git a/src/vt/context/runnable_context/lb_data.h b/src/vt/context/runnable_context/lb_data.h index c84a0b0cdf..00d843e64c 100644 --- a/src/vt/context/runnable_context/lb_data.h +++ b/src/vt/context/runnable_context/lb_data.h @@ -47,6 +47,10 @@ #include "vt/vrt/collection/balance/lb_common.h" #include "vt/elm/elm_lb_data.fwd.h" +#if vt_check_enabled(papi) +#include "vt/context/runnable_context/papi_data.h" +#endif + namespace vt { namespace ctx { /** @@ -79,7 +83,11 @@ struct LBData { : lb_data_(in_lb_data), cur_elm_id_(in_elm_id), should_instrument_(true) - { } + { +#if vt_check_enabled(papi) + papi_data_ = std::make_unique(); +#endif + } /** * \brief Return whether time is required @@ -115,10 +123,35 @@ struct LBData { */ ElementIDStruct const& getCurrentElementID() const; +#if vt_check_enabled(papi) + /** + * \brief Start PAPI metrics map for the running context + */ + void startPAPIMetrics() { papi_data_->start(); } + + /** + * \brief Stop PAPI metrics map for the running context + * + * \note has to be called after startPAPIMetrics + * + */ + void stopPAPIMetrics() { papi_data_->stop(); } + + /** + * \brief Get the current PAPI metrics map for the running context + * + * \return the PAPI metrics map + */ + std::unordered_map getPAPIMetrics(); +#endif + private: ElementLBData* lb_data_ = nullptr; /**< Element LB data */ ElementIDStruct cur_elm_id_ = {}; /**< Current element ID */ bool should_instrument_ = false; /**< Whether we are instrumenting */ +#if vt_check_enabled(papi) + std::unique_ptr papi_data_; +#endif }; }} /* end namespace vt::ctx */ diff --git a/src/vt/context/runnable_context/lb_data.impl.h b/src/vt/context/runnable_context/lb_data.impl.h index ea5096166c..8ac5126798 100644 --- a/src/vt/context/runnable_context/lb_data.impl.h +++ b/src/vt/context/runnable_context/lb_data.impl.h @@ -50,6 +50,9 @@ #include "vt/vrt/collection/manager.h" #include +#if vt_check_enabled(papi) +#include +#endif namespace vt { namespace ctx { @@ -59,6 +62,9 @@ LBData::LBData(ElmT* in_elm, MsgT* msg) cur_elm_id_(in_elm->getElmID()), should_instrument_(msg->lbLiteInstrument()) { +#if vt_check_enabled(papi) + papi_data_ = std::make_unique(); +#endif // record the communication LB data right away! theCollection()->recordLBData(in_elm, msg); } diff --git a/src/vt/context/runnable_context/papi_data.cc b/src/vt/context/runnable_context/papi_data.cc new file mode 100644 index 0000000000..8d49bdb59e --- /dev/null +++ b/src/vt/context/runnable_context/papi_data.cc @@ -0,0 +1,145 @@ +/* +//@HEADER +// ***************************************************************************** +// +// papi_data.cc +// DARMA/vt => Virtual Transport +// +// Copyright 2019-2024 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + + +#include "vt/context/runnable_context/papi_data.h" + +#if vt_check_enabled(papi) + +namespace vt { namespace ctx { + +PAPIData::PAPIData() + : event_set(PAPI_NULL), retval(0), + start_real_cycles(0), end_real_cycles(0), start_real_usec(0), end_real_usec(0), + start_virt_cycles(0), end_virt_cycles(0), start_virt_usec(0), end_virt_usec(0) +{ + char const* env_p = getenv("VT_EVENTS"); + + if (env_p == nullptr) { + events["PAPI_TOT_INS"] = 0; + } else { + std::string env_str(env_p); + std::stringstream ss(env_str); + std::string item; + while (std::getline(ss, item, ',')) { + events[item] = 0; + } + } + + retval = PAPI_create_eventset(&event_set); + if (retval != PAPI_OK) { + handle_error("PAPIData Constructor: Couldn't create an event set: "); + } + + // Add instructions before multiplexing (needed https://github.com/icl-utk-edu/papi/wiki/PAPI-Multiplexing) + retval = PAPI_add_event(event_set, PAPI_TOT_INS); + if (retval != PAPI_OK) { + handle_error("PAPIData Constructor: Couldn't add instructions to event set: "); + } + + retval = PAPI_set_multiplex(event_set); + if (retval != PAPI_OK) { + handle_error("PAPIData Constructor: Couldn't convert event set to multiplexed: "); + } + + for (auto const& event : events) { + // Skip adding instructions to the event set since it was already + // added before making the event set multiplexed. + if (event.first == "PAPI_TOT_INS") { + continue; + } + int native = 0; + retval = PAPI_event_name_to_code(event.first.c_str(), &native); + if (retval != PAPI_OK) { + handle_error(fmt::format("Couldn't event_name_to_code for {}: ", event.first.c_str())); + } + retval = PAPI_add_event(event_set, native); + if (retval != PAPI_OK) { + handle_error(fmt::format("Couldn't add {} to the PAPI Event Set: ", event.first.c_str())); + } + } +} + +void PAPIData::handle_error(const std::string &info) const { + vtAbort(fmt::format("{}: PAPI error {}: {}\n", info, retval, PAPI_strerror(retval))); +} + +void PAPIData::start() { + retval = PAPI_start(event_set); + if (retval != PAPI_OK) { + handle_error("PAPIData start: Starting counting events in the Event Set: "); + } + + start_real_cycles = PAPI_get_real_cyc(); + start_real_usec = PAPI_get_real_usec(); + start_virt_cycles = PAPI_get_virt_cyc(); + start_virt_usec = PAPI_get_virt_usec(); +} + +void PAPIData::stop() { + std::vector aligned_values(events.size(), 0); + + retval = PAPI_stop(event_set, aligned_values.data()); + if (retval != PAPI_OK) { + handle_error("PAPIData stop: Stopping the counting of events in the Event Set: "); + } + + size_t i = 0; + for (auto& event : events) { + long long papi_value = aligned_values[i++]; + + if (papi_value < 0) { + vtAbort(fmt::format("Unexpected negative value for event {}: {}", event.first, papi_value)); + } + + event.second = static_cast(papi_value); + } + + end_real_cycles = PAPI_get_real_cyc(); + end_real_usec = PAPI_get_real_usec(); + end_virt_cycles = PAPI_get_virt_cyc(); + end_virt_usec = PAPI_get_virt_usec(); +} +}} /* end namespace vt::ctx */ + +#endif diff --git a/src/vt/context/runnable_context/papi_data.h b/src/vt/context/runnable_context/papi_data.h new file mode 100644 index 0000000000..571710114a --- /dev/null +++ b/src/vt/context/runnable_context/papi_data.h @@ -0,0 +1,83 @@ +/* +//@HEADER +// ***************************************************************************** +// +// papi_data.h +// DARMA/vt => Virtual Transport +// +// Copyright 2019-2024 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_VT_CONTEXT_RUNNABLE_CONTEXT_PAPI_DATA_H +#define INCLUDED_VT_CONTEXT_RUNNABLE_CONTEXT_PAPI_DATA_H + + +#include "vt/config.h" + +#if vt_check_enabled(papi) +#include + +#include +#include +#include +#include +#include + +namespace vt { namespace ctx { + +/** + * \struct PAPIData + * + * \brief Structure for storing Performance API (PAPI) related data structures + */ +struct PAPIData { + int event_set = PAPI_NULL; + int retval = PAPI_OK; + uint64_t start_real_cycles = 0, end_real_cycles = 0, start_real_usec = 0, end_real_usec = 0; + uint64_t start_virt_cycles = 0, end_virt_cycles = 0, start_virt_usec = 0, end_virt_usec = 0; + std::unordered_map events = {}; + + PAPIData(); + void start(); + void stop(); + void handle_error(const std::string &info) const; +}; + +}} /* end namespace vt::ctx */ + +#endif + +#endif /*INCLUDED_VT_CONTEXT_RUNNABLE_CONTEXT_PAPI_DATA_H*/ diff --git a/src/vt/metrics/example_events.h b/src/vt/metrics/example_events.h new file mode 100644 index 0000000000..bc7908a3d4 --- /dev/null +++ b/src/vt/metrics/example_events.h @@ -0,0 +1,64 @@ +/* +//@HEADER +// ***************************************************************************** +// +// example_events.h +// DARMA/vt => Virtual Transport +// +// Copyright 2019-2024 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_VT_METRICS_EXAMPLE_EVENTS_H +#define INCLUDED_VT_METRICS_EXAMPLE_EVENTS_H + +#include +#include +#include + +namespace vt { namespace metrics { + +std::unordered_map> const example_event_map = { + {"cycles", std::make_pair(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES)}, + {"instructions", std::make_pair(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS)}, + {"cache_references", std::make_pair(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES)}, + {"cache_misses", std::make_pair(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES)}, + {"branch_instructions", std::make_pair(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS)}, + {"branch_misses", std::make_pair(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES)} +}; + +}} // end namespace vt::metrics + +#endif /*INCLUDED_VT_METRICS_EXAMPLE_EVENTS_H*/ diff --git a/src/vt/metrics/perf_data.cc b/src/vt/metrics/perf_data.cc new file mode 100644 index 0000000000..5b5abd141f --- /dev/null +++ b/src/vt/metrics/perf_data.cc @@ -0,0 +1,186 @@ +/* +//@HEADER +// ***************************************************************************** +// +// perf_data.cc +// DARMA/vt => Virtual Transport +// +// Copyright 2019-2024 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#include "perf_data.h" + +namespace vt { namespace metrics { + +PerfData::PerfData() + : event_map_(example_event_map) +{ + char const* env_p = getenv("VT_EVENTS"); + + // Check if the environment variable is set + if (env_p == nullptr) { + event_names_.push_back("instructions"); + } else { + std::string env_str(env_p); + std::stringstream ss(env_str); + std::string item; + + while (std::getline(ss, item, ',')) + { + event_names_.push_back(item); + } + } + + for (const auto &event_name : event_names_) { + if (event_map_.find(event_name) == event_map_.end()) { + cleanupBeforeAbort(); + vtAbort("Event name isn't in known perf events map: " + event_name); + } + } + + // Initialize perf events once and store file descriptors + for (const auto &event_name : event_names_) { + struct perf_event_attr pe = {}; + pe.type = event_map_.at(event_name).first; + pe.size = sizeof(struct perf_event_attr); + pe.config = event_map_.at(event_name).second; + + pe.disabled = 1; + pe.exclude_kernel = 1; + pe.exclude_hv = 1; + pe.inherit = 1; // Ensure event is inherited by threads + + if (event_name == "instructions") { + pe.pinned = 1; + } + + int fd = perfEventOpen(&pe, 0, -1, -1, PERF_FLAG_FD_CLOEXEC); + if (fd == -1) { + cleanupBeforeAbort(); + vtAbort("Error opening perf event: " + std::string(strerror(errno))); + } + + event_fds_.push_back(fd); + } +} + +PerfData::~PerfData() { + for (int fd : event_fds_) { + if (fd != -1) { + close(fd); + } + } +} + +void PerfData::startTaskMeasurement() { + for (int fd : event_fds_) { + if (fd != -1) { + ioctl(fd, PERF_EVENT_IOC_RESET, 0); + ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); + } + } +} + +void PerfData::stopTaskMeasurement() { + for (int fd : event_fds_) { + if (fd != -1) { + ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); + } + } +} + +std::unordered_map PerfData::getTaskMeasurements() { + std::unordered_map measurements; + + if (event_fds_.size() != event_names_.size()) { + vtAbort("Mismatch between event_fds_ and event_names_ sizes."); + } + + for (size_t i = 0; i < event_fds_.size(); ++i) { + int64_t buffer = 0; + + if (event_fds_[i] != -1) { + if (sizeof(buffer) != sizeof(int64_t)) { + vtAbort("Buffer size mismatch: expected " + std::to_string(sizeof(int64_t)) + + " bytes, but got " + std::to_string(sizeof(buffer))); + } + + ssize_t bytesRead = read(event_fds_[i], &buffer, sizeof(buffer)); + + if (bytesRead == sizeof(buffer)) { + if (buffer < 0) { + vtAbort("Negative value read from perf event data for: " + event_names_[i] + + ". Value: " + std::to_string(buffer)); + } + + uint64_t count = static_cast(buffer); + measurements[event_names_[i]] = count; + } else if (bytesRead == -1) { + vtAbort("Failed to read perf event data for: " + event_names_[i] + + ". Error: " + std::strerror(errno)); + } else { + vtAbort("Incomplete read for: " + event_names_[i] + + ". Expected " + std::to_string(sizeof(buffer)) + + " bytes, but got " + std::to_string(bytesRead)); + } + } else { + vtAbort("Invalid file descriptor for: " + event_names_[i]); + } + } + + return measurements; +} + +std::unordered_map> PerfData::getEventMap() const { return event_map_; } + +void PerfData::startup() { event_map_ = example_event_map; } + +std::string PerfData::name() { return "PerfData"; } + +void PerfData::cleanupBeforeAbort() { + for (int fd : event_fds_) { + if (fd != -1) { + close(fd); + } + } + event_fds_.clear(); +} + +long PerfData::perfEventOpen(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) { + return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); +} + +}} // end namespace vt::metrics diff --git a/src/vt/metrics/perf_data.h b/src/vt/metrics/perf_data.h new file mode 100644 index 0000000000..197a73a6bc --- /dev/null +++ b/src/vt/metrics/perf_data.h @@ -0,0 +1,199 @@ +/* +//@HEADER +// ***************************************************************************** +// +// perf_data.h +// DARMA/vt => Virtual Transport +// +// Copyright 2019-2024 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_VT_METRICS_PERF_DATA_H +#define INCLUDED_VT_METRICS_PERF_DATA_H + +#include "vt/config.h" +#include "vt/runtime/component/component_pack.h" +#include "vt/context/context.h" +#include "example_events.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace vt { namespace metrics { + +/** \file */ + +/** + * \struct PerfData perf_data.h vt/metrics/perf_data.h + * + * \brief Tracks performance metrics per task + * + * The PerfData component is responsible for initializing, tracking, and retrieving + * performance metrics for specific tasks using Linux performance counters. + */ +struct PerfData: runtime::component::Component +{ +public: + /** + * \brief Constructor for PerfData + * + * Initializes performance counters based on the \c VT_EVENTS environment variable, + * which is a comma seperated list of events available in the events header + * (example_events.h by default). For example: \c VT_EVENTS="cache-misses,instructions". + * If \c VT_EVENTS isn't set, will default to measuring instructions. + * Ensures only valid events are configured. + */ + PerfData(); + + /** + * \brief Destructor for PerfData + * + * Cleans up resources, closing file descriptors associated with performance + * counters. + */ + ~PerfData(); + + /** + * \brief Start performance measurement for a task + * + * Resets and enables the performance counters associated with the tracked events. + */ + void startTaskMeasurement(); + + /** + * \brief Stop performance measurement for a task + * + * Disables the performance counters associated with the tracked events. + */ + void stopTaskMeasurement(); + + /** + * \brief Get the measurements collected during the task execution + * + * Reads and retrieves the counter values for all tracked events. + * + * \return A map of event names to their corresponding measurement values. + * + * \throws vtAbort if there is a mismatch in data or an error during reading. + */ + std::unordered_map getTaskMeasurements(); + + /** + * \brief Retrieve the current event map + * + * Returns the mapping of event names to their type and configuration values. + * + * \return A map of event names to pairs of event type and configuration values. + */ + std::unordered_map> getEventMap() const; + + /** + * \brief Component startup method + */ + void startup() override; + + /** + * \brief Get the component name + * + * \return The name of the component as a string. + */ + std::string name() override; + + /** + * \brief Serialize the PerfData object + */ + template + void serialize(SerializerT& s) { + s | event_map_ + | event_names_ + | event_fds_; + } + +private: + /** + * \brief Map of event names to event type and configuration + */ + std::unordered_map> event_map_; + + /** + * \brief List of event names being tracked + */ + std::vector event_names_; + + /** + * \brief List of file descriptors associated with performance counters + */ + std::vector event_fds_; + + /** + * \brief Cleanup resources before aborting + * + * Closes any open file descriptors and clears internal data structures. + */ + void cleanupBeforeAbort(); + + /** + * \brief Open a performance counter event + * + * Wrapper around the syscall to open a performance counter. + * + * \param[in] hw_event The performance event attributes. + * \param[in] pid The process ID to measure (-1 for calling process). + * \param[in] cpu The CPU to measure (-1 for any CPU). + * \param[in] group_fd Group file descriptor for event grouping. + * \param[in] flags Additional flags for the syscall. + * + * \return The file descriptor for the event, or -1 on failure. + */ + static long perfEventOpen(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags); +}; + +}} // end namespace vt::metrics + +namespace vt { + +extern metrics::PerfData* thePerfData(); + +} // end namespace vt + +#endif /*INCLUDED_VT_METRICS_PERF_DATA_H*/ diff --git a/src/vt/runnable/runnable.cc b/src/vt/runnable/runnable.cc index 48c78ed8f2..64b7efbd01 100644 --- a/src/vt/runnable/runnable.cc +++ b/src/vt/runnable/runnable.cc @@ -199,6 +199,42 @@ void RunnableNew::run() { #endif } +#if vt_check_enabled(perf) || vt_check_enabled(papi) +void RunnableNew::startMetrics() { +#if vt_check_enabled(papi) + if (contexts_.has_lb) + { + contexts_.lb.startPAPIMetrics(); + } +#elif vt_check_enabled(perf) + vt::thePerfData()->startTaskMeasurement(); +#endif +} + +void RunnableNew::stopMetrics() { +#if vt_check_enabled(papi) + if (contexts_.has_lb) + { + contexts_.lb.stopPAPIMetrics(); + } +#elif vt_check_enabled(perf) + vt::thePerfData()->stopTaskMeasurement(); +#endif +} + +std::unordered_map RunnableNew::getMetrics() { +#if vt_check_enabled(papi) + if (contexts_.has_lb) + { + return contexts_.lb.getPAPIMetrics(); + } +#elif vt_check_enabled(perf) + return vt::thePerfData()->getTaskMeasurements(); +#endif + return {}; +} +#endif + void RunnableNew::start(TimeType time) { contexts_.setcontext.start(); if (contexts_.has_td) contexts_.td.start(); diff --git a/src/vt/runnable/runnable.h b/src/vt/runnable/runnable.h index ac37d8b2c5..3618f1d529 100644 --- a/src/vt/runnable/runnable.h +++ b/src/vt/runnable/runnable.h @@ -53,6 +53,8 @@ #include "vt/context/runnable_context/continuation.h" #include "vt/pool/static_sized/memory_pool_equal.h" #include "vt/elm/elm_id.h" +#include "vt/metrics/perf_data.h" +#include "vt/runtime/runtime_inst.h" // fwd-declarations for the element types namespace vt { namespace vrt { @@ -318,6 +320,28 @@ struct RunnableNew { */ BaseMsgType* getMsg() const { return msg_.get(); } +#if vt_check_enabled(perf) || vt_check_enabled(papi) + /** + * \brief Start metrics associated to this runnable for the running context + */ + void startMetrics(); + + /** + * \brief Stop metrics associated to this runnable for the running context + * + * \note has to be called after startMetrics + * + */ + void stopMetrics(); + + /** + * \brief Get the dictionnary of task metrics associated with this runnable + * + * \return the dictionnary + */ + std::unordered_map getMetrics(); +#endif + #if vt_check_enabled(fcontext) /** * \brief Check if this runnable is complete or not diff --git a/src/vt/runtime/runtime.cc b/src/vt/runtime/runtime.cc index d8fda56210..69186c0677 100644 --- a/src/vt/runtime/runtime.cc +++ b/src/vt/runtime/runtime.cc @@ -67,6 +67,7 @@ #include "vt/timetrigger/time_trigger_manager.h" #include "vt/phase/phase_manager.h" #include "vt/epoch/epoch_manip.h" +#include "vt/metrics/perf_data.h" #include "vt/configs/arguments/app_config.h" #include "vt/configs/arguments/args.h" @@ -912,6 +913,14 @@ void Runtime::initializeComponents() { >{} ); +# if vt_check_enabled(perf) + p_->registerComponent( + &thePerfData, Deps< + ctx::Context // Everything depends on theContext + >{} + ); +# endif + p_->add(); p_->add(); p_->add(); @@ -941,6 +950,9 @@ void Runtime::initializeComponents() { p_->add(); p_->add(); p_->add(); +# if vt_check_enabled(perf) + p_->add(); +# endif if (addLBDataRestartReader) { p_->add(); diff --git a/src/vt/runtime/runtime.h b/src/vt/runtime/runtime.h index 6e3ba92cda..55682409d6 100644 --- a/src/vt/runtime/runtime.h +++ b/src/vt/runtime/runtime.h @@ -55,6 +55,9 @@ #include "vt/trace/trace.h" #endif #include "vt/pmpi/pmpi_component.h" +#if vt_check_enabled(perf) +#include "vt/metrics/perf_data.h" +#endif #include #include @@ -432,6 +435,9 @@ struct Runtime { #if vt_check_enabled(mpi_access_guards) ComponentPtrType thePMPI = nullptr; #endif + #if vt_check_enabled(perf) + ComponentPtrType thePerfData = nullptr; + #endif static bool volatile sig_user_1_; diff --git a/src/vt/runtime/runtime_banner.cc b/src/vt/runtime/runtime_banner.cc index 66dca757f5..1cc4e64d8f 100644 --- a/src/vt/runtime/runtime_banner.cc +++ b/src/vt/runtime/runtime_banner.cc @@ -139,6 +139,12 @@ void Runtime::printStartupBanner() { #if vt_check_enabled(diagnostics) features.push_back(vt_feature_str_diagnostics); #endif +#if vt_check_enabled(papi) + features.push_back(vt_feature_str_papi); +#endif +#if vt_check_enabled(perf) + features.push_back(vt_feature_str_perf); +#endif std::string dirty = ""; if (vt_git_clean_status == "DIRTY") { diff --git a/src/vt/runtime/runtime_get.cc b/src/vt/runtime/runtime_get.cc index 657ab01345..38c0439620 100644 --- a/src/vt/runtime/runtime_get.cc +++ b/src/vt/runtime/runtime_get.cc @@ -64,6 +64,7 @@ #include "vt/timetrigger/time_trigger_manager.h" #include "vt/phase/phase_manager.h" #include "vt/epoch/epoch_manip.h" +#include "vt/metrics/perf_data.h" #include @@ -123,6 +124,9 @@ trace::Trace* theTrace() { return curRT->theTrace; #if vt_check_enabled(mpi_access_guards) pmpi::PMPIComponent* thePMPI() { return curRT->thePMPI; } #endif +#if vt_check_enabled(perf) +metrics::PerfData* thePerfData() { return curRT->thePerfData; } +#endif } /* end namespace vt */ diff --git a/tests/unit/metrics/test_papi_data.cc b/tests/unit/metrics/test_papi_data.cc new file mode 100644 index 0000000000..c72fd5e86a --- /dev/null +++ b/tests/unit/metrics/test_papi_data.cc @@ -0,0 +1,167 @@ +/* +//@HEADER +// ***************************************************************************** +// +// test_papi_data.cc +// DARMA/vt => Virtual Transport +// +// Copyright 2019-2024 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#include "test_parallel_harness.h" +#include + +#if vt_check_enabled(papi) +#include +#endif + +namespace vt { namespace tests { namespace unit { + +#if vt_check_enabled(papi) + +struct TestPAPIData : TestParallelHarness {}; + +double pi(uint64_t n) { + double sum = 0.0; + int sign = 1; + for (uint64_t i = 0; i < n; ++i) { + sum += sign/(2.0*i+1.0); + sign *= -1; + } + return 4.0*sum; +} + +TEST_F(TestPAPIData, DefaultEventSet) { + unsetenv("VT_EVENTS"); + + vt::ctx::PAPIData papi_data; + + ASSERT_FALSE(papi_data.events.empty()) + << "Default event set should not be empty."; + EXPECT_NE(papi_data.events.find("PAPI_TOT_INS"), papi_data.events.end()) + << "Default event should be 'PAPI_TOT_INS'."; +} + +TEST_F(TestPAPIData, CustomEventSet) { + setenv("VT_EVENTS", "PAPI_TOT_INS,PAPI_TOT_CYC", 1); + + vt::ctx::PAPIData papi_data; + + ASSERT_EQ(papi_data.events.size(), 2) + << "Custom event set should have two events."; + EXPECT_NE(papi_data.events.find("PAPI_TOT_INS"), papi_data.events.end()) + << "First event should be 'PAPI_TOT_INS'."; + EXPECT_NE(papi_data.events.find("PAPI_TOT_CYC"), papi_data.events.end()) + << "Second event should be 'PAPI_TOT_CYC'."; +} + +TEST_F(TestPAPIData, InvalidEventTriggersAbort) { + setenv("VT_EVENTS", "invalid-event", 1); + + EXPECT_THROW( + vt::ctx::PAPIData papi_data, + std::runtime_error + ) << "Invalid event names should trigger vtAbort and throw an exception."; +} + +TEST_F(TestPAPIData, StartAndStopMeasurement) { + setenv("VT_EVENTS", "PAPI_TOT_INS", 1); + + vt::ctx::PAPIData papi_data; + + EXPECT_NO_THROW(papi_data.start()) + << "Calling start() should not throw."; + EXPECT_NO_THROW(papi_data.stop()) + << "Calling stop() should not throw."; + + EXPECT_GT(papi_data.end_real_cycles, papi_data.start_real_cycles) + << "Real cycles should increase after measurement."; + EXPECT_GT(papi_data.end_virt_usec, papi_data.start_virt_usec) + << "Virtual microseconds should increase after measurement."; +} + +TEST_F(TestPAPIData, MeasureMultipleEvents) { + setenv("VT_EVENTS", "PAPI_TOT_INS,PAPI_TOT_CYC", 1); + + vt::ctx::PAPIData papi_data; + + EXPECT_NO_THROW(papi_data.start()) + << "Calling start() should not throw."; + + double p; + p = pi(1000); + fmt::print("pi: {}\n", p); // print to avoid being optimized out + + EXPECT_NO_THROW(papi_data.stop()) + << "Calling stop() should not throw."; + + ASSERT_EQ(papi_data.events.size(), 2) + << "Two events should be measured."; + EXPECT_GT(papi_data.events["PAPI_TOT_INS"], 0) + << "First event (PAPI_TOT_INS) should record positive values."; + EXPECT_GT(papi_data.events["PAPI_TOT_CYC"], 0) + << "Second event (PAPI_TOT_CYC) should record positive values."; +} + +TEST_F(TestPAPIData, MultiplexedEventSet) { + setenv("VT_EVENTS", "PAPI_TOT_INS,PAPI_L3_TCM,PAPI_BR_INS", 1); + + vt::ctx::PAPIData papi_data; + + ASSERT_EQ(papi_data.events.size(), 3) + << "Custom event set should have three events."; + EXPECT_NO_THROW(papi_data.start()) + << "Calling start() should not throw."; + + double p; + p = pi(1000); + fmt::print("pi: {}\n", p); // print to avoid being optimized out + + EXPECT_NO_THROW(papi_data.stop()) + << "Calling stop() should not throw."; + + ASSERT_EQ(papi_data.events.size(), 3) + << "Three events should be measured."; + for (const auto& event : papi_data.events) { + EXPECT_GT(event.second, 0) + << fmt::format("Event {} should record positive values.", event.first); + } +} + + +#endif + +}}} // end namespace vt::tests::unit diff --git a/tests/unit/metrics/test_perf_data.cc b/tests/unit/metrics/test_perf_data.cc new file mode 100644 index 0000000000..655b0ec345 --- /dev/null +++ b/tests/unit/metrics/test_perf_data.cc @@ -0,0 +1,141 @@ +/* +//@HEADER +// ***************************************************************************** +// +// test_perf_data.cc +// DARMA/vt => Virtual Transport +// +// Copyright 2019-2024 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#include "test_parallel_harness.h" +#include +#include + +namespace vt { namespace tests { namespace unit { + +#if vt_check_enabled(perf) + +struct TestPerfData : TestParallelHarness {}; + +double pi(uint64_t n) { + double sum = 0.0; + int sign = 1; + for (uint64_t i = 0; i < n; ++i) { + sum += sign/(2.0*i+1.0); + sign *= -1; + } + return 4.0*sum; +} + +TEST_F(TestPerfData, DefaultEventName) { + unsetenv("VT_EVENTS"); + + vt::metrics::PerfData perf_data; + + auto event_map = perf_data.getEventMap(); + + ASSERT_NE(event_map.find("instructions"), event_map.end()) + << "Default event 'instructions' should be in the event map."; +} + +TEST_F(TestPerfData, ValidCustomEventNames) { + setenv("VT_EVENTS", "instructions,cache_references", 1); + + vt::metrics::PerfData perf_data; + + auto event_map = perf_data.getEventMap(); + + EXPECT_NE(event_map.find("instructions"), event_map.end()) + << "Event 'instructions' should be in the event map."; + EXPECT_NE(event_map.find("cache_references"), event_map.end()) + << "Event 'cache_references' should be in the event map."; +} + +TEST_F(TestPerfData, InvalidEventNameTriggersAbort) { + setenv("VT_EVENTS", "invalid-event", 1); + + EXPECT_THROW( + vt::metrics::PerfData perf_data, + std::runtime_error + ) << "Invalid event names should trigger vtAbort and throw an exception."; +} + +TEST_F(TestPerfData, StartAndStopTaskMeasurement) { + setenv("VT_EVENTS", "instructions", 1); + + vt::metrics::PerfData perf_data; + + EXPECT_NO_THROW(perf_data.startTaskMeasurement()) + << "startTaskMeasurement() should not throw an exception."; + EXPECT_NO_THROW(perf_data.stopTaskMeasurement()) + << "stopTaskMeasurement() should not throw an exception."; +} + +TEST_F(TestPerfData, RepeatedStartStop) { + setenv("VT_EVENTS", "instructions", 1); + + vt::metrics::PerfData perf_data; + + for (int i = 0; i < 100; ++i) { + EXPECT_NO_THROW(perf_data.startTaskMeasurement()); + EXPECT_NO_THROW(perf_data.stopTaskMeasurement()); + } +} + +TEST_F(TestPerfData, StartupFunction) { + setenv("VT_EVENTS", "instructions", 1); + + vt::metrics::PerfData perf_data; + + EXPECT_NO_THROW(perf_data.startup()) + << "startup() should not throw an exception."; +} + +TEST_F(TestPerfData, ConstructorDestructorValidation) { + setenv("VT_EVENTS", "instructions", 1); + + for (int i = 0; i < 100; ++i) { + EXPECT_NO_THROW({ + vt::metrics::PerfData perf_data; + }) << "Repeated construction and destruction should not throw errors."; + } +} + + +#endif + +}}} // end namespace vt::tests::unit