Initial skeleton (#1)
* googletest submodule * cmake folder * misc root files - clang-format - cmake-format - pyproject.toml - requirements.txt - VERSION * workflows * RPM files * external folder * samples folder * tests root folder * source/bin folder * source/include folder * source/lib/common folder * source/lib/plugins folder * source/lib/tests folder - for library unit tests * source/lib/rocprofiler folder - rocprofiler library implementation * Remaining cmake files * lib/common/containers - ring_buffer - atomic_ring_buffer - stable_vector - static_vector * Update .gitignore * Update hsa.hpp - include cstdint * cmake formatting (cmake-format) (#2) Co-authored-by: jrmadsen <jrmadsen@users.noreply.github.com> * Remove linting.yml - uses self-hosted runners --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
کامیت شده توسط
GitHub
والد
7d1c7757a8
کامیت
527aa71f5a
@@ -0,0 +1,114 @@
|
||||
# clang-format v11
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: true
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveBitFields: true
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: TopLevel
|
||||
AlwaysBreakAfterReturnType: TopLevel
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: false
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: true
|
||||
BreakInheritanceList: BeforeComma
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 0
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseLabels: true
|
||||
IndentCaseBlocks: false
|
||||
IndentFunctionDeclarationAfterType: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentExternBlock: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: Never
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: Auto
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
...
|
||||
@@ -0,0 +1,305 @@
|
||||
parse:
|
||||
additional_commands:
|
||||
rocprofiler_checkout_git_submodule:
|
||||
flags:
|
||||
- RECURSIVE
|
||||
kwargs:
|
||||
RELATIVE_PATH: '*'
|
||||
WORKING_DIRECTORY: '*'
|
||||
TEST_FILE: '*'
|
||||
REPO_URL: '*'
|
||||
REPO_BRANCH: '*'
|
||||
ADDITIONAL_COMMANDS: '*'
|
||||
rocprofiler_save_variables:
|
||||
kwargs:
|
||||
VARIABLES: '*'
|
||||
CONDITION: '*'
|
||||
rocprofiler_restore_variables:
|
||||
kwargs:
|
||||
VARIABLES: '*'
|
||||
CONDITION: '*'
|
||||
rocprofiler_target_compile_options:
|
||||
flags:
|
||||
- BUILD_INTERFACE
|
||||
- FORCE
|
||||
kwargs:
|
||||
PUBLIC: '*'
|
||||
PRIVATE: '*'
|
||||
INTERFACE: '*'
|
||||
LANGUAGES: '*'
|
||||
LINK_LANGUAGES: '*'
|
||||
rocprofiler_add_test:
|
||||
flags:
|
||||
- SKIP_BASELINE
|
||||
- SKIP_SAMPLING
|
||||
- SKIP_REWRITE
|
||||
- SKIP_RUNTIME
|
||||
kwargs:
|
||||
NAME: '*'
|
||||
TARGET: '*'
|
||||
MPI: '*'
|
||||
GPU: '*'
|
||||
NUM_PROCS: '*'
|
||||
REWRITE_TIMEOUT: '*'
|
||||
RUNTIME_TIMEOUT: '*'
|
||||
SAMPLING_TIMEOUT: '*'
|
||||
SAMPLING_ARGS: '*'
|
||||
REWRITE_ARGS: '*'
|
||||
RUNTIME_ARGS: '*'
|
||||
RUN_ARGS: '*'
|
||||
ENVIRONMENT: '*'
|
||||
LABELS: '*'
|
||||
PROPERTIES: '*'
|
||||
SAMPLING_PASS_REGEX: '*'
|
||||
SAMPLING_FAIL_REGEX: '*'
|
||||
RUNTIME_PASS_REGEX: '*'
|
||||
RUNTIME_FAIL_REGEX: '*'
|
||||
REWRITE_PASS_REGEX: '*'
|
||||
REWRITE_FAIL_REGEX: '*'
|
||||
BASELINE_PASS_REGEX: '*'
|
||||
BASELINE_FAIL_REGEX: '*'
|
||||
REWRITE_RUN_PASS_REGEX: '*'
|
||||
REWRITE_RUN_FAIL_REGEX: '*'
|
||||
rocprofiler_add_causal_test:
|
||||
flags:
|
||||
- SKIP_BASELINE
|
||||
kwargs:
|
||||
NAME: '*'
|
||||
TARGET: '*'
|
||||
CAUSAL_TIMEOUT: '*'
|
||||
CAUSAL_VALIDATE_TIMEOUT: '*'
|
||||
CAUSAL_MODE: '*'
|
||||
CAUSAL_ARGS: '*'
|
||||
CAUSAL_VALIDATE_ARGS: '*'
|
||||
RUNTIME_ARGS: '*'
|
||||
RUN_ARGS: '*'
|
||||
ENVIRONMENT: '*'
|
||||
LABELS: '*'
|
||||
PROPERTIES: '*'
|
||||
CAUSAL_PASS_REGEX: '*'
|
||||
CAUSAL_FAIL_REGEX: '*'
|
||||
BASELINE_PASS_REGEX: '*'
|
||||
BASELINE_FAIL_REGEX: '*'
|
||||
CAUSAL_VALIDATE_PASS_REGEX: '*'
|
||||
CAUSAL_VALIDATE_FAIL_REGEX: '*'
|
||||
rocprofiler_target_compile_definitions:
|
||||
kwargs:
|
||||
PUBLIC: '*'
|
||||
PRIVATE: '*'
|
||||
INTERFACE: '*'
|
||||
rocprofiler_add_bin_test:
|
||||
flags:
|
||||
- WILL_FAIL
|
||||
kwargs:
|
||||
NAME: '*'
|
||||
ARGS: '*'
|
||||
LABELS: '*'
|
||||
TARGET: '*'
|
||||
DEPENDS: '*'
|
||||
COMMAND: '*'
|
||||
TIMEOUT: '*'
|
||||
PROPERTIES: '*'
|
||||
ENVIRONMENT: '*'
|
||||
WORKING_DIRECTORY: '*'
|
||||
PASS_REGEX: '*'
|
||||
FAIL_REGEX: '*'
|
||||
SKIP_REGEX: '*'
|
||||
rocprofiler_add_python_test:
|
||||
flags:
|
||||
- STANDALONE
|
||||
kwargs:
|
||||
NAME: '*'
|
||||
FILE: '*'
|
||||
TIMEOUT: '*'
|
||||
PROFILE_ARGS: '*'
|
||||
RUN_ARGS: '*'
|
||||
ENVIRONMENT: '*'
|
||||
LABELS: '*'
|
||||
DEPENDS: '*'
|
||||
COMMAND: '*'
|
||||
PROPERTIES: '*'
|
||||
PYTHON_EXECUTABLE: '*'
|
||||
PYTHON_VERSION: '*'
|
||||
PASS_REGEX: '*'
|
||||
FAIL_REGEX: '*'
|
||||
SKIP_REGEX: '*'
|
||||
rocprofiler_add_python_validation_test:
|
||||
kwargs:
|
||||
NAME: '*'
|
||||
ARGS: '*'
|
||||
PERFETTO_FILE: '*'
|
||||
PERFETTO_METRIC: '*'
|
||||
TIMEMORY_FILE: '*'
|
||||
TIMEMORY_METRIC: '*'
|
||||
rocm_version_message:
|
||||
flags:
|
||||
- STATUS
|
||||
- WARNING
|
||||
- SEND_ERROR
|
||||
- FATAL_ERROR
|
||||
- AUTHOR_WARNING
|
||||
rocprofiler_find_python:
|
||||
flags:
|
||||
- REQUIRED
|
||||
- QUIET
|
||||
kwargs:
|
||||
VERSION: '*'
|
||||
ROOT_DIR: '*'
|
||||
COMPONENTS: '*'
|
||||
rocprofiler_python_console_script:
|
||||
kwargs:
|
||||
VERSION: '*'
|
||||
ROOT_DIR: '*'
|
||||
rocprofiler_pybind11_add_module:
|
||||
flags:
|
||||
- MODULE
|
||||
- SHARED
|
||||
- EXCLUDE_FROM_ALL
|
||||
- NO_EXTRAS
|
||||
- SYSTEM
|
||||
- THIN_LTO
|
||||
- LTO
|
||||
kwargs:
|
||||
PYTHON_VERSION: '*'
|
||||
CXX_STANDARD: '*'
|
||||
VISIBILITY: '*'
|
||||
rocprofiler_directory:
|
||||
flags:
|
||||
- MKDIR
|
||||
- FAIL
|
||||
kwargs:
|
||||
PREFIX: '*'
|
||||
OUTPUT_VARIABLE: '*'
|
||||
WORKING_DIRECTORY: '*'
|
||||
PATHS: '*'
|
||||
rocprofiler_check_python_dirs_and_versions:
|
||||
flags:
|
||||
- UNSET
|
||||
- FAIL
|
||||
kwargs:
|
||||
RESULT_VARIABLE: '*'
|
||||
OUTPUT_VARIABLE: '*'
|
||||
rocprofiler_find_static_library:
|
||||
flags:
|
||||
- NO_CACHE
|
||||
- REQUIRED
|
||||
- NO_DEFAULT_PATH
|
||||
- NO_PACKAGE_ROOT_PATH
|
||||
- NO_CMAKE_PATH
|
||||
- NO_CMAKE_ENVIRONMENT_PATH
|
||||
- NO_SYSTEM_ENVIRONMENT_PATH
|
||||
- CMAKE_FIND_ROOT_PATH_BOTH
|
||||
- ONLY_CMAKE_FIND_ROOT_PATH
|
||||
- NO_CMAKE_FIND_ROOT_PATH
|
||||
kwargs:
|
||||
NAMES: '*'
|
||||
NAMES_PER_DIR: '*'
|
||||
HINTS: '*'
|
||||
PATHS: '*'
|
||||
PATH_SUFFIXES: '*'
|
||||
DOC: '*'
|
||||
rocprofiler_find_shared_library:
|
||||
flags:
|
||||
- NO_CACHE
|
||||
- REQUIRED
|
||||
- NO_DEFAULT_PATH
|
||||
- NO_PACKAGE_ROOT_PATH
|
||||
- NO_CMAKE_PATH
|
||||
- NO_CMAKE_ENVIRONMENT_PATH
|
||||
- NO_SYSTEM_ENVIRONMENT_PATH
|
||||
- CMAKE_FIND_ROOT_PATH_BOTH
|
||||
- ONLY_CMAKE_FIND_ROOT_PATH
|
||||
- NO_CMAKE_FIND_ROOT_PATH
|
||||
kwargs:
|
||||
NAMES: '*'
|
||||
NAMES_PER_DIR: '*'
|
||||
HINTS: '*'
|
||||
PATHS: '*'
|
||||
PATH_SUFFIXES: '*'
|
||||
DOC: '*'
|
||||
rocprofiler_causal_example_executable:
|
||||
kwargs:
|
||||
TAG: '*'
|
||||
SOURCES: '*'
|
||||
DEFINITIONS: '*'
|
||||
LINK_LIBRARIES: '*'
|
||||
INCLUDE_DIRECTORIES: '*'
|
||||
rocprofiler_add_validation_test:
|
||||
kwargs:
|
||||
NAME: '*'
|
||||
ARGS: '*'
|
||||
LABELS: '*'
|
||||
TIMEOUT: '*'
|
||||
DEPENDS: '*'
|
||||
PROPERTIES: '*'
|
||||
PASS_REGEX: '*'
|
||||
FAIL_REGEX: '*'
|
||||
SKIP_REGEX: '*'
|
||||
ENVIRONMENT: '*'
|
||||
PERFETTO_FILE: '*'
|
||||
PERFETTO_METRIC: '*'
|
||||
TIMEMORY_FILE: '*'
|
||||
TIMEMORY_METRIC: '*'
|
||||
override_spec: {}
|
||||
vartags: []
|
||||
proptags: []
|
||||
format:
|
||||
disable: false
|
||||
line_width: 90
|
||||
tab_size: 4
|
||||
use_tabchars: false
|
||||
fractional_tab_policy: use-space
|
||||
max_subgroups_hwrap: 2
|
||||
max_pargs_hwrap: 8
|
||||
max_rows_cmdline: 2
|
||||
separate_ctrl_name_with_space: false
|
||||
separate_fn_name_with_space: false
|
||||
dangle_parens: false
|
||||
dangle_align: child
|
||||
min_prefix_chars: 4
|
||||
max_prefix_chars: 10
|
||||
max_lines_hwrap: 2
|
||||
line_ending: unix
|
||||
command_case: lower
|
||||
keyword_case: upper
|
||||
always_wrap: []
|
||||
enable_sort: true
|
||||
autosort: false
|
||||
require_valid_layout: false
|
||||
layout_passes: {}
|
||||
markup:
|
||||
bullet_char: '*'
|
||||
enum_char: .
|
||||
first_comment_is_literal: true
|
||||
literal_comment_pattern: ^#
|
||||
fence_pattern: ^\s*([`~]{3}[`~]*)(.*)$
|
||||
ruler_pattern: ^\s*[^\w\s]{3}.*[^\w\s]{3}$
|
||||
explicit_trailing_pattern: '#<'
|
||||
hashruler_min_length: 10
|
||||
canonicalize_hashrulers: true
|
||||
enable_markup: true
|
||||
lint:
|
||||
disabled_codes: []
|
||||
function_pattern: '[0-9a-z_]+'
|
||||
macro_pattern: '[0-9A-Z_]+'
|
||||
global_var_pattern: '[A-Z][0-9A-Z_]+'
|
||||
internal_var_pattern: _[A-Z][0-9A-Z_]+
|
||||
local_var_pattern: '[a-z][a-z0-9_]+'
|
||||
private_var_pattern: _[0-9a-z_]+
|
||||
public_var_pattern: '[A-Z][0-9A-Z_]+'
|
||||
argument_var_pattern: '[a-z][a-z0-9_]+'
|
||||
keyword_pattern: '[A-Z][0-9A-Z_]+'
|
||||
max_conditionals_custom_parser: 2
|
||||
min_statement_spacing: 1
|
||||
max_statement_spacing: 2
|
||||
max_returns: 6
|
||||
max_branches: 12
|
||||
max_arguments: 5
|
||||
max_localvars: 15
|
||||
max_statements: 50
|
||||
encode:
|
||||
emit_byteorder_mark: false
|
||||
input_encoding: utf-8
|
||||
output_encoding: utf-8
|
||||
misc:
|
||||
per_command: {}
|
||||
@@ -0,0 +1,146 @@
|
||||
|
||||
name: Formatting
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths-ignore:
|
||||
- '.github/workflows/pull_*.yml'
|
||||
- '.github/workflows/linting.yml'
|
||||
- '.github/workflows/markdown_lint.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
cmake:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: |
|
||||
echo "branch=${GITHUB_HEAD_REF:-${GITHUB_HEAD_REF#refs/heads/}}" >> $GITHUB_OUTPUT
|
||||
id: extract_branch
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y python3-pip
|
||||
python3 -m pip install -U cmake-format
|
||||
|
||||
- name: Run cmake-format
|
||||
run: |
|
||||
set +e
|
||||
cmake-format -i $(find . -type f | egrep 'CMakeLists.txt|\.cmake$')
|
||||
if [ $(git diff | wc -l) -ne 0 ]; then
|
||||
echo -e "\nError! CMake code not formatted. Run cmake-format...\n"
|
||||
echo -e "\nFiles:\n"
|
||||
git diff --name-only
|
||||
echo -e "\nFull diff:\n"
|
||||
git diff
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Create pull request
|
||||
if: failure()
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
commit-message: "cmake formatting (cmake-format)"
|
||||
branch: ${{ steps.extract_branch.outputs.branch }}-cmake-format
|
||||
delete-branch: true
|
||||
title: "Format cmake code (via cmake-format) on ${{ steps.extract_branch.outputs.branch }}"
|
||||
base: ${{ steps.extract_branch.outputs.branch }}
|
||||
|
||||
source:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
DISTRIB_CODENAME=$(cat /etc/lsb-release | grep DISTRIB_CODENAME | awk -F '=' '{print $NF}')
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y software-properties-common wget curl clang-format-11
|
||||
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: |
|
||||
echo "branch=${GITHUB_HEAD_REF:-${GITHUB_HEAD_REF#refs/heads/}}" >> $GITHUB_OUTPUT
|
||||
id: extract_branch
|
||||
|
||||
- name: Run clang-format
|
||||
run: |
|
||||
set +e
|
||||
FILES=$(find samples source tests -type f | egrep '\.(h|hpp|hh|c|cc|cpp)(|\.in)$')
|
||||
FORMAT_OUT=$(clang-format-11 -i ${FILES})
|
||||
if [ $(git diff | wc -l) -ne 0 ]; then
|
||||
echo -e "\nError! Code not formatted. Run clang-format (version 11)...\n"
|
||||
echo -e "\nFiles:\n"
|
||||
git diff --name-only
|
||||
echo -e "\nFull diff:\n"
|
||||
git diff
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Create pull request
|
||||
if: failure()
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
commit-message: "source formatting (clang-format v11)"
|
||||
branch: ${{ steps.extract_branch.outputs.branch }}-clang-format
|
||||
delete-branch: true
|
||||
title: "Format source code (via clang-format v11) on ${{ steps.extract_branch.outputs.branch }}"
|
||||
base: ${{ steps.extract_branch.outputs.branch }}
|
||||
|
||||
python:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.10']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: |
|
||||
echo "branch=${GITHUB_HEAD_REF:-${GITHUB_HEAD_REF#refs/heads/}}" >> $GITHUB_OUTPUT
|
||||
id: extract_branch
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install black
|
||||
|
||||
- name: black format
|
||||
run: |
|
||||
black .
|
||||
if [ $(git diff | wc -l) -ne 0 ]; then
|
||||
echo -e "\nError! Python code not formatted. Run black...\n"
|
||||
echo -e "\nFiles:\n"
|
||||
git diff --name-only
|
||||
echo -e "\nFull diff:\n"
|
||||
git diff
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Create pull request
|
||||
if: failure()
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
commit-message: "python formatting (black)"
|
||||
branch: ${{ steps.extract_branch.outputs.branch }}-python-format
|
||||
delete-branch: true
|
||||
title: "Format python code (via black) on ${{ steps.extract_branch.outputs.branch }}"
|
||||
base: ${{ steps.extract_branch.outputs.branch }}
|
||||
@@ -30,3 +30,6 @@
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Build directories
|
||||
/build*
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "external/googletest"]
|
||||
path = external/googletest
|
||||
url = https://github.com/google/googletest.git
|
||||
@@ -0,0 +1,89 @@
|
||||
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND CMAKE_CURRENT_SOURCE_DIR STREQUAL
|
||||
CMAKE_SOURCE_DIR)
|
||||
set(MSG "")
|
||||
message(STATUS "Warning! Building from the source directory is not recommended")
|
||||
message(STATUS "If unintended, please remove 'CMakeCache.txt' and 'CMakeFiles'")
|
||||
message(STATUS "and build from a separate directory")
|
||||
message(AUTHOR_WARNING "In-source build")
|
||||
endif()
|
||||
|
||||
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" FULL_VERSION_STRING LIMIT_COUNT 1)
|
||||
string(REGEX REPLACE "(\n|\r)" "" FULL_VERSION_STRING "${FULL_VERSION_STRING}")
|
||||
string(REGEX REPLACE "([0-9]+)\.([0-9]+)\.([0-9]+)(.*)" "\\1.\\2.\\3" ROCPROFILER_VERSION
|
||||
"${FULL_VERSION_STRING}")
|
||||
|
||||
project(
|
||||
rocprofiler
|
||||
LANGUAGES C CXX
|
||||
VERSION ${ROCPROFILER_VERSION}
|
||||
DESCRIPTION "ROCm GPU performance analysis"
|
||||
HOMEPAGE_URL "https://github.com/ROCm-Developer-Tools/rocprofiler-v2-internal")
|
||||
|
||||
find_package(Git)
|
||||
|
||||
if(Git_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe --tags
|
||||
OUTPUT_VARIABLE ROCPROFILER_GIT_DESCRIBE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE _GIT_DESCRIBE_RESULT
|
||||
ERROR_QUIET)
|
||||
|
||||
if(NOT _GIT_DESCRIBE_RESULT EQUAL 0)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe
|
||||
OUTPUT_VARIABLE ROCPROFILER_GIT_DESCRIBE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE _GIT_DESCRIBE_RESULT
|
||||
ERROR_QUIET)
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
|
||||
OUTPUT_VARIABLE ROCPROFILER_GIT_REVISION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
|
||||
else()
|
||||
set(ROCPROFILER_GIT_DESCRIBE "v${ROCPROFILER_VERSION}")
|
||||
set(ROCPROFILER_GIT_REVISION "")
|
||||
endif()
|
||||
|
||||
message(
|
||||
STATUS
|
||||
"[${PROJECT_NAME}] version ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} (${FULL_VERSION_STRING})"
|
||||
)
|
||||
message(STATUS "[${PROJECT_NAME}] git revision: ${ROCPROFILER_GIT_REVISION}")
|
||||
message(STATUS "[${PROJECT_NAME}] git describe: ${ROCPROFILER_GIT_DESCRIBE}")
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${PROJECT_SOURCE_DIR}/cmake/Modules
|
||||
${CMAKE_MODULE_PATH})
|
||||
|
||||
include(GNUInstallDirs) # install directories
|
||||
|
||||
include(rocprofiler_utilities) # various functions/macros
|
||||
include(rocprofiler_interfaces) # interface libraries
|
||||
include(rocprofiler_compilers) # compiler identification
|
||||
include(rocprofiler_options) # project options
|
||||
include(rocprofiler_build_settings) # build flags
|
||||
include(rocprofiler_formatting) # formatting
|
||||
include(rocprofiler_linting) # clang-tidy
|
||||
include(rocprofiler_config_interfaces) # configure interface libraries
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}")
|
||||
|
||||
add_subdirectory(external)
|
||||
add_subdirectory(source)
|
||||
|
||||
if(ROCPROFILER_BUILD_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
if(ROCPROFILER_BUILD_SAMPLES)
|
||||
add_subdirectory(samples)
|
||||
endif()
|
||||
|
||||
#
|
||||
include(rocprofiler_config_install)
|
||||
include(rocprofiler_config_packaging)
|
||||
@@ -0,0 +1,5 @@
|
||||
# left-hand term originates from ENABLE_LDCONFIG = ON/OFF at package build
|
||||
if [ "@ENABLE_LDCONFIG@" == "ON" ]; then
|
||||
echo @CPACK_PACKAGING_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ > /@CMAKE_INSTALL_SYSCONFDIR@/ld.so.conf.d/librocprofiler64.conf
|
||||
ldconfig
|
||||
fi
|
||||
@@ -0,0 +1,4 @@
|
||||
# left-hand term originates from ENABLE_LDCONFIG = ON/OFF at package build
|
||||
if [ "@ENABLE_LDCONFIG@" == "ON" ]; then
|
||||
rm -f /@CMAKE_INSTALL_SYSCONFDIR@/ld.so.conf.d/librocprofiler64.conf && ldconfig
|
||||
fi
|
||||
@@ -0,0 +1 @@
|
||||
2.0.0
|
||||
@@ -0,0 +1,302 @@
|
||||
#[=======================================================================[.rst:
|
||||
Findrocm_version
|
||||
---------------
|
||||
|
||||
Search the <ROCM_PATH>/.info/version* files to determine the version of ROCm
|
||||
|
||||
Use this module by invoking find_package with the form::
|
||||
|
||||
find_package(rocm_version
|
||||
[version] [EXACT]
|
||||
[REQUIRED])
|
||||
|
||||
This module finds the version info for ROCm. The cached variables are::
|
||||
|
||||
rocm_version_FOUND - Whether the ROCm versioning was found
|
||||
rocm_version_FULL_VERSION - The exact string from `<ROCM_PATH>/.info/version` or similar
|
||||
rocm_version_MAJOR_VERSION - Major version, e.g. 4 in 4.5.2.100-40502
|
||||
rocm_version_MINOR_VERSION - Minor version, e.g. 5 in 4.5.2.100-40502
|
||||
rocm_version_PATCH_VERSION - Patch version, e.g. 2 in 4.5.2.100-40502
|
||||
rocm_version_TWEAK_VERSION - Tweak version, e.g. 100 in 4.5.2.100-40502
|
||||
rocm_version_REVISION_VERSION - Revision version, e.g. 40502 in 4.5.2.100-40502.
|
||||
rocm_version_EPOCH_VERSION - See deb-version for a description of epochs. Epochs are used when versioning system change
|
||||
rocm_version_CANONICAL_VERSION - `[<EPOCH>:]<MAJOR>.<MINOR>.<MINOR>[.<TWEAK>][-<REVISION>]`
|
||||
rocm_version_NUMERIC_VERSION - e.g. `10000*<MAJOR> + 100*<MINOR> + <PATCH>`, e.g. 40502 for ROCm 4.5.2
|
||||
rocm_version_TRIPLE_VERSION - e.g. `<MAJOR>.<MINOR>.<PATCH>`, e.g. 4.5.2 for ROCm 4.5.2
|
||||
|
||||
These variables are relevant for the find procedure::
|
||||
|
||||
rocm_version_DEBUG - Print info about processing
|
||||
rocm_version_VERSION_FILE - `<FILE>` to read from in `<ROCM_PATH>/.info/<FILE>`, e.g. `version`, `version-dev`, `version-hip-libraries`, etc.
|
||||
It may also be a full path
|
||||
rocm_version_DIR - Root location for <ROCM_PATH>
|
||||
#]=======================================================================]
|
||||
|
||||
set(rocm_version_VARIABLES
|
||||
EPOCH
|
||||
MAJOR
|
||||
MINOR
|
||||
PATCH
|
||||
TWEAK
|
||||
REVISION
|
||||
TRIPLE
|
||||
NUMERIC
|
||||
CANONICAL
|
||||
FULL)
|
||||
|
||||
function(ROCM_VERSION_MESSAGE _TYPE)
|
||||
if(rocm_version_DEBUG)
|
||||
message(${_TYPE} "[rocm_version] ${ARGN}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# read a .info/version* file and propagate the variables to the calling scope
|
||||
function(ROCM_VERSION_COMPUTE FULL_VERSION_STRING _VAR_PREFIX)
|
||||
|
||||
# remove any line endings
|
||||
string(REGEX REPLACE "(\n|\r)" "" FULL_VERSION_STRING "${FULL_VERSION_STRING}")
|
||||
|
||||
# store the full version so it can be set later
|
||||
set(FULL_VERSION "${FULL_VERSION_STRING}")
|
||||
|
||||
# get number and remove from full version string
|
||||
string(REGEX REPLACE "([0-9]+)\:(.*)" "\\1" EPOCH_VERSION "${FULL_VERSION_STRING}")
|
||||
string(REGEX REPLACE "([0-9]+)\:(.*)" "\\2" FULL_VERSION_STRING
|
||||
"${FULL_VERSION_STRING}")
|
||||
|
||||
if(EPOCH_VERSION STREQUAL FULL_VERSION)
|
||||
set(EPOCH_VERSION)
|
||||
endif()
|
||||
|
||||
# get number and remove from full version string
|
||||
string(REGEX REPLACE "([0-9]+)(.*)" "\\1" MAJOR_VERSION "${FULL_VERSION_STRING}")
|
||||
string(REGEX REPLACE "([0-9]+)(.*)" "\\2" FULL_VERSION_STRING
|
||||
"${FULL_VERSION_STRING}")
|
||||
|
||||
# get number and remove from full version string
|
||||
string(REGEX REPLACE "\.([0-9]+)(.*)" "\\1" MINOR_VERSION "${FULL_VERSION_STRING}")
|
||||
string(REGEX REPLACE "\.([0-9]+)(.*)" "\\2" FULL_VERSION_STRING
|
||||
"${FULL_VERSION_STRING}")
|
||||
|
||||
# get number and remove from full version string
|
||||
string(REGEX REPLACE "\.([0-9]+)(.*)" "\\1" PATCH_VERSION "${FULL_VERSION_STRING}")
|
||||
string(REGEX REPLACE "\.([0-9]+)(.*)" "\\2" FULL_VERSION_STRING
|
||||
"${FULL_VERSION_STRING}")
|
||||
|
||||
if(NOT PATCH_VERSION LESS 100)
|
||||
set(PATCH_VERSION 0)
|
||||
endif()
|
||||
|
||||
# get number and remove from full version string
|
||||
string(REGEX REPLACE "\.([0-9]+)(.*)" "\\1" TWEAK_VERSION "${FULL_VERSION_STRING}")
|
||||
string(REGEX REPLACE "\.([0-9]+)(.*)" "\\2" FULL_VERSION_STRING
|
||||
"${FULL_VERSION_STRING}")
|
||||
|
||||
# get number
|
||||
string(REGEX REPLACE "-([0-9A-Za-z+~]+)" "\\1" REVISION_VERSION
|
||||
"${FULL_VERSION_STRING}")
|
||||
|
||||
set(CANONICAL_VERSION)
|
||||
set(_MAJOR_SEP ":")
|
||||
set(_MINOR_SEP ".")
|
||||
set(_PATCH_SEP ".")
|
||||
set(_TWEAK_SEP ".")
|
||||
set(_REVISION_SEP "-")
|
||||
|
||||
foreach(_V EPOCH MAJOR MINOR PATCH TWEAK REVISION)
|
||||
if(${_V}_VERSION)
|
||||
set(CANONICAL_VERSION "${CANONICAL_VERSION}${_${_V}_SEP}${${_V}_VERSION}")
|
||||
else()
|
||||
set(CANONICAL_VERSION "${CANONICAL_VERSION}${_${_V}_SEP}0")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(_MAJOR_SEP "")
|
||||
|
||||
foreach(_V MAJOR MINOR PATCH)
|
||||
if(${_V}_VERSION)
|
||||
set(TRIPLE_VERSION "${TRIPLE_VERSION}${_${_V}_SEP}${${_V}_VERSION}")
|
||||
else()
|
||||
set(TRIPLE_VERSION "${TRIPLE_VERSION}${_${_V}_SEP}0")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
math(
|
||||
EXPR
|
||||
NUMERIC_VERSION
|
||||
"(10000 * (${MAJOR_VERSION}+0)) + (100 * (${MINOR_VERSION}+0)) + (${PATCH_VERSION}+0)"
|
||||
)
|
||||
|
||||
# propagate to parent scopes
|
||||
foreach(_V ${rocm_version_VARIABLES})
|
||||
set(${_VAR_PREFIX}_${_V}_VERSION
|
||||
${${_V}_VERSION}
|
||||
PARENT_SCOPE)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# this macro watches for changes in the variables and unsets the remaining cache varaible
|
||||
# when they change
|
||||
function(ROCM_VERSION_WATCH_FOR_CHANGE _var)
|
||||
set(_rocm_version_watch_var_name rocm_version_WATCH_VALUE_${_var})
|
||||
|
||||
if(DEFINED ${_rocm_version_watch_var_name})
|
||||
if("${${_var}}" STREQUAL "${${_rocm_version_watch_var_name}}")
|
||||
if(NOT "${${_var}}" STREQUAL "")
|
||||
rocm_version_message(STATUS "${_var} :: ${${_var}}")
|
||||
endif()
|
||||
|
||||
list(REMOVE_ITEM _REMAIN_VARIABLES ${_var})
|
||||
set(_REMAIN_VARIABLES
|
||||
"${_REMAIN_VARIABLES}"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
else()
|
||||
rocm_version_message(
|
||||
STATUS
|
||||
"${_var} changed :: ${${_rocm_version_watch_var_name}} --> ${${_var}}")
|
||||
|
||||
foreach(_V ${_REMAIN_VARIABLES})
|
||||
rocm_version_message(
|
||||
STATUS "${_var} changed :: Unsetting cache variable ${_V}...")
|
||||
unset(${_V} CACHE)
|
||||
endforeach()
|
||||
endif()
|
||||
else()
|
||||
if(NOT "${${_var}}" STREQUAL "")
|
||||
rocm_version_message(STATUS "${_var} :: ${${_var}}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# store the value for the next run
|
||||
set(${_rocm_version_watch_var_name}
|
||||
"${${_var}}"
|
||||
CACHE INTERNAL "Last value of ${_var}" FORCE)
|
||||
endfunction()
|
||||
|
||||
# scope this to a function to avoid leaking local variables
|
||||
function(ROCM_VERSION_PARSE_VERSION_FILES)
|
||||
|
||||
# the list of variables set by module. when one of these changes, we need to unset the
|
||||
# cache variables after it
|
||||
set(_ALL_VARIABLES)
|
||||
|
||||
foreach(_V ${rocm_version_VARIABLES})
|
||||
list(APPEND _ALL_VARIABLES rocm_version_${_V}_VERSION)
|
||||
endforeach()
|
||||
set(_REMAIN_VARIABLES ${_ALL_VARIABLES})
|
||||
|
||||
# read a .info/version* file and propagate the variables to the calling scope
|
||||
function(ROCM_VERSION_READ_FILE _FILE _VAR_PREFIX)
|
||||
file(READ "${_FILE}" FULL_VERSION_STRING LIMIT_COUNT 1)
|
||||
rocm_version_compute("${FULL_VERSION_STRING}" "${_VAR_PREFIX}")
|
||||
|
||||
# propagate to parent scopes
|
||||
foreach(_V ${rocm_version_VARIABLES})
|
||||
set(${_VAR_PREFIX}_${_V}_VERSION
|
||||
${${_VAR_PREFIX}_${_V}_VERSION}
|
||||
PARENT_SCOPE)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# search for HIP to set ROCM_PATH if(NOT hip_FOUND) find_package(hip) endif()
|
||||
|
||||
function(COMPUTE_ROCM_VERSION_DIR)
|
||||
if(EXISTS "${rocm_version_VERSION_FILE}" AND IS_ABSOLUTE
|
||||
"${rocm_version_VERSION_FILE}")
|
||||
get_filename_component(_VERSION_DIR "${rocm_version_VERSION_FILE}" PATH)
|
||||
get_filename_component(_VERSION_DIR "${_VERSION_DIR}/.." REALPATH)
|
||||
set(rocm_version_DIR
|
||||
"${_VERSION_DIR}"
|
||||
CACHE PATH "Root path to ROCm's .info/${rocm_version_VERSION_FILE}"
|
||||
${ARGN})
|
||||
rocm_version_watch_for_change(rocm_version_DIR)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if(rocm_version_VERSION_FILE)
|
||||
get_filename_component(_VERSION_FILE "${rocm_version_VERSION_FILE}" NAME)
|
||||
set(_VERSION_FILES ${_VERSION_FILE})
|
||||
compute_rocm_version_dir(FORCE)
|
||||
else()
|
||||
set(_VERSION_FILES version version-dev version-hip-libraries version-hiprt
|
||||
version-hiprt-devel version-hip-sdk version-libs version-utils)
|
||||
rocm_version_message(STATUS "rocm_version version files: ${_VERSION_FILES}")
|
||||
endif()
|
||||
|
||||
# convert env to cache if not defined
|
||||
foreach(_PATH rocm_version_DIR rocm_version_ROOT rocm_version_ROOT_DIR
|
||||
ROCPROFILER_DEFAULT_ROCM_PATH ROCM_PATH)
|
||||
if(NOT DEFINED ${_PATH} AND DEFINED ENV{${_PATH}})
|
||||
set(_VAL "$ENV{${_PATH}}")
|
||||
get_filename_component(_VAL "${_VAL}" REALPATH)
|
||||
set(${_PATH}
|
||||
"${_VAL}"
|
||||
CACHE PATH "Search path for ROCm version for rocm_version")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(rocm_version_DIR)
|
||||
set(_PATHS ${rocm_version_DIR})
|
||||
else()
|
||||
set(_PATHS)
|
||||
foreach(
|
||||
_DIR
|
||||
${rocm_version_DIR} ${rocm_version_ROOT} ${rocm_version_ROOT_DIR}
|
||||
$ENV{CMAKE_PREFIX_PATH} ${CMAKE_PREFIX_PATH} ${ROCPROFILER_DEFAULT_ROCM_PATH}
|
||||
${ROCM_PATH} /opt/rocm)
|
||||
if(EXISTS ${_DIR})
|
||||
get_filename_component(_ABS_DIR "${_DIR}" REALPATH)
|
||||
list(APPEND _PATHS ${_ABS_DIR})
|
||||
endif()
|
||||
endforeach()
|
||||
rocm_version_message(STATUS "rocm_version search paths: ${_PATHS}")
|
||||
endif()
|
||||
|
||||
string(REPLACE ":" ";" _PATHS "${_PATHS}")
|
||||
|
||||
foreach(_PATH ${_PATHS})
|
||||
foreach(_FILE ${_VERSION_FILES})
|
||||
set(_F ${_PATH}/.info/${_FILE})
|
||||
if(EXISTS ${_F})
|
||||
set(rocm_version_VERSION_FILE
|
||||
"${_F}"
|
||||
CACHE FILEPATH "File with versioning info")
|
||||
rocm_version_watch_for_change(rocm_version_VERSION_FILE)
|
||||
compute_rocm_version_dir()
|
||||
else()
|
||||
rocm_version_message(AUTHOR_WARNING "File does not exist: ${_F}")
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
if(EXISTS "${rocm_version_VERSION_FILE}")
|
||||
set(_F "${rocm_version_VERSION_FILE}")
|
||||
rocm_version_message(STATUS "Reading ${_F}...")
|
||||
get_filename_component(_B "${_F}" NAME)
|
||||
string(REPLACE "." "_" _B "${_B}")
|
||||
string(REPLACE "-" "_" _B "${_B}")
|
||||
rocm_version_read_file(${_F} ${_B})
|
||||
|
||||
foreach(_V ${rocm_version_VARIABLES})
|
||||
set(_CACHE_VAR rocm_version_${_V}_VERSION)
|
||||
set(_LOCAL_VAR ${_B}_${_V}_VERSION)
|
||||
set(rocm_version_${_V}_VERSION
|
||||
"${${_LOCAL_VAR}}"
|
||||
CACHE STRING "ROCm ${_V} version")
|
||||
rocm_version_watch_for_change(${_CACHE_VAR})
|
||||
endforeach()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# execute
|
||||
rocm_version_parse_version_files()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(
|
||||
rocm_version
|
||||
VERSION_VAR rocm_version_FULL_VERSION
|
||||
REQUIRED_VARS rocm_version_FULL_VERSION rocm_version_TRIPLE_VERSION rocm_version_DIR
|
||||
rocm_version_VERSION_FILE)
|
||||
# don't add major/minor/patch/etc. version variables to required vars because they might
|
||||
# be zero, which will cause CMake to evaluate it as not set
|
||||
@@ -0,0 +1,97 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying file
|
||||
# Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
if(NOT ROCM_PATH AND NOT "$ENV{ROCM_PATH}" STREQUAL "")
|
||||
set(ROCM_PATH "$ENV{ROCM_PATH}")
|
||||
endif()
|
||||
|
||||
foreach(_DIR ${rocm_version_DIR} ${ROCM_PATH} /opt/rocm /opt/rocm/rocprofiler)
|
||||
if(EXISTS ${_DIR})
|
||||
get_filename_component(_ABS_DIR "${_DIR}" REALPATH)
|
||||
list(APPEND _ROCM_ROCPROFILER_PATHS ${_ABS_DIR})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_path(
|
||||
rocprofiler_ROOT_DIR
|
||||
NAMES include/rocprofiler/rocprofiler.h include/rocprofiler.h
|
||||
HINTS ${_ROCM_ROCPROFILER_PATHS}
|
||||
PATHS ${_ROCM_ROCPROFILER_PATHS}
|
||||
PATH_SUFFIXES rocprofiler)
|
||||
|
||||
mark_as_advanced(rocprofiler_ROOT_DIR)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_path(
|
||||
rocprofiler_INCLUDE_DIR
|
||||
NAMES rocprofiler.h
|
||||
HINTS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS}
|
||||
PATHS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS}
|
||||
PATH_SUFFIXES include include/rocprofiler rocprofiler/include)
|
||||
|
||||
mark_as_advanced(rocprofiler_INCLUDE_DIR)
|
||||
|
||||
find_path(
|
||||
rocprofiler_hsa_INCLUDE_DIR
|
||||
NAMES hsa.h
|
||||
HINTS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS}
|
||||
PATHS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS}
|
||||
PATH_SUFFIXES include include/hsa)
|
||||
|
||||
mark_as_advanced(rocprofiler_hsa_INCLUDE_DIR)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_library(
|
||||
rocprofiler_LIBRARY
|
||||
NAMES rocprofiler64 rocprofiler
|
||||
HINTS ${rocprofiler_ROOT_DIR}/rocprofiler ${rocprofiler_ROOT_DIR}
|
||||
${_ROCM_ROCPROFILER_PATHS}
|
||||
PATHS ${rocprofiler_ROOT_DIR}/rocprofiler ${rocprofiler_ROOT_DIR}
|
||||
${_ROCM_ROCPROFILER_PATHS}
|
||||
PATH_SUFFIXES lib lib64
|
||||
NO_DEFAULT_PATH)
|
||||
|
||||
find_library(
|
||||
rocprofiler_hsa-runtime_LIBRARY
|
||||
NAMES hsa-runtime64 hsa-runtime
|
||||
HINTS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS}
|
||||
PATHS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS}
|
||||
PATH_SUFFIXES lib lib64)
|
||||
|
||||
if(rocprofiler_LIBRARY)
|
||||
get_filename_component(rocprofiler_LIBRARY_DIR "${rocprofiler_LIBRARY}" PATH CACHE)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(rocprofiler_LIBRARY rocprofiler_hsa-runtime_LIBRARY)
|
||||
unset(_ROCM_ROCPROFILER_PATHS)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_package_handle_standard_args(
|
||||
rocprofiler DEFAULT_MSG rocprofiler_ROOT_DIR rocprofiler_INCLUDE_DIR
|
||||
rocprofiler_hsa_INCLUDE_DIR rocprofiler_LIBRARY rocprofiler_hsa-runtime_LIBRARY)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
if(rocprofiler_FOUND)
|
||||
add_library(rocprofiler::rocprofiler INTERFACE IMPORTED)
|
||||
add_library(rocprofiler::roctx INTERFACE IMPORTED)
|
||||
set(rocprofiler_INCLUDE_DIRS ${rocprofiler_INCLUDE_DIR}
|
||||
${rocprofiler_hsa_INCLUDE_DIR})
|
||||
set(rocprofiler_LIBRARIES ${rocprofiler_LIBRARY} ${rocprofiler_hsa-runtime_LIBRARY})
|
||||
set(rocprofiler_LIBRARY_DIRS ${rocprofiler_LIBRARY_DIR})
|
||||
|
||||
target_include_directories(
|
||||
rocprofiler::rocprofiler INTERFACE ${rocprofiler_INCLUDE_DIR}
|
||||
${rocprofiler_hsa_INCLUDE_DIR})
|
||||
|
||||
target_link_libraries(rocprofiler::rocprofiler INTERFACE ${rocprofiler_LIBRARIES})
|
||||
endif()
|
||||
@@ -0,0 +1,16 @@
|
||||
#%Module1.0
|
||||
|
||||
module-whatis "@PROJECT_NAME@ (version @PROJECT_VERSION@)"
|
||||
|
||||
proc ModulesHelp { } {
|
||||
puts stderr "Loads @PROJECT_NAME@ v@PROJECT_VERSION@"
|
||||
}
|
||||
|
||||
set ROOT [file normalize [file dirname [file normalize ${ModulesCurrentModulefile}]]/../../..]
|
||||
|
||||
setenv @PROJECT_NAME@_ROOT "${ROOT}"
|
||||
prepend-path CMAKE_PREFIX_PATH "${ROOT}"
|
||||
prepend-path PATH "${ROOT}/bin"
|
||||
prepend-path LD_LIBRARY_PATH "${ROOT}/@CMAKE_INSTALL_LIBDIR@"
|
||||
prepend-path PYTHONPATH "${ROOT}/@CMAKE_INSTALL_PYTHONDIR@"
|
||||
setenv @PROJECT_NAME@_DIR "${ROOT}/@CMAKE_INSTALL_DATAROOTDIR@/cmake/@PROJECT_NAME@"
|
||||
@@ -0,0 +1,56 @@
|
||||
# - Config file for @PROJECT_NAME@ and its component libraries
|
||||
# It defines the following variables:
|
||||
#
|
||||
# @PROJECT_NAME@_INCLUDE_DIRS
|
||||
# @PROJECT_NAME@_LIBRARIES
|
||||
# @PROJECT_NAME@_INTERNAL_DEFINES - used by the test suite
|
||||
|
||||
# compute paths
|
||||
get_filename_component(@PROJECT_NAME@_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
|
||||
# version
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-version.cmake)
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
|
||||
set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_LIB_INSTALL_DIR@")
|
||||
get_filename_component(@PROJECT_NAME@_ROOT_DIR ${@PROJECT_NAME@_INCLUDE_DIR} PATH)
|
||||
|
||||
set(@PROJECT_NAME@_LIBRARIES)
|
||||
|
||||
add_library(@PROJECT_NAME@::@PROJECT_NAME@ INTERFACE IMPORTED)
|
||||
|
||||
include("${@PROJECT_NAME@_CMAKE_DIR}/@PROJECT_NAME@-library-targets.cmake")
|
||||
|
||||
# Library dependencies
|
||||
foreach(TARG @PROJECT_BUILD_TARGETS@)
|
||||
set(TARG @PROJECT_NAME@-${TARG})
|
||||
if(NOT @PROJECT_NAME@_FIND_COMPONENTS)
|
||||
list(APPEND @PROJECT_NAME@_LIBRARIES @PROJECT_NAME@::${TARG})
|
||||
target_link_libraries(@PROJECT_NAME@::@PROJECT_NAME@
|
||||
INTERFACE @PROJECT_NAME@::${TARG})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(@PROJECT_NAME@_FIND_COMPONENTS)
|
||||
foreach(COMP ${@PROJECT_NAME@_FIND_COMPONENTS})
|
||||
set(TARG @PROJECT_NAME@::@PROJECT_NAME@-${COMP})
|
||||
if(TARGET ${TARG})
|
||||
set(@PROJECT_NAME@_${COMP}_FOUND 1)
|
||||
list(APPEND @PROJECT_NAME@_LIBRARIES ${TARG})
|
||||
target_link_libraries(@PROJECT_NAME@::@PROJECT_NAME@
|
||||
INTERFACE ${TARG})
|
||||
else()
|
||||
set(@PROJECT_NAME@_${COMP}_FOUND 0)
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(
|
||||
@PROJECT_NAME@
|
||||
FOUND_VAR @PROJECT_NAME@_FOUND
|
||||
REQUIRED_VARS @PROJECT_NAME@_ROOT_DIR @PROJECT_NAME@_INCLUDE_DIR @PROJECT_NAME@_LIBRARIES
|
||||
VERSION_VAR @PROJECT_NAME@_VERSION
|
||||
HANDLE_COMPONENTS)
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BASEDIR=$(dirname ${BASH_SOURCE[0]})
|
||||
command -v realpath &> /dev/null && BASEDIR=$(realpath ${BASEDIR}/../..) || BASEDIR=$(cd ${BASEDIR}/../.. && pwd)
|
||||
|
||||
if [ ! -d "${BASEDIR}" ]; then
|
||||
echo "${BASEDIR} does not exist"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@PROJECT_NAME@_ROOT=${BASEDIR}
|
||||
PATH=${BASEDIR}/bin:${PATH}
|
||||
LD_LIBRARY_PATH=${BASEDIR}/@CMAKE_INSTALL_LIBDIR@:${LD_LIBRARY_PATH}
|
||||
PYTHONPATH=${BASEDIR}/@CMAKE_INSTALL_PYTHONDIR@:${PYTHONPATH}
|
||||
CMAKE_PREFIX_PATH=${BASEDIR}:${CMAKE_PREFIX_PATH}
|
||||
@PROJECT_NAME@_DIR=${BASEDIR}/@CMAKE_INSTALL_DATAROOTDIR@/cmake/@PROJECT_NAME@
|
||||
|
||||
export @PROJECT_NAME@_ROOT
|
||||
export PATH
|
||||
export LD_LIBRARY_PATH
|
||||
export PYTHONPATH
|
||||
export CMAKE_PREFIX_PATH
|
||||
export @PROJECT_NAME@_DIR
|
||||
@@ -0,0 +1,182 @@
|
||||
# ########################################################################################
|
||||
#
|
||||
# Handles the build settings
|
||||
#
|
||||
# ########################################################################################
|
||||
|
||||
include_guard(DIRECTORY)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
include(rocprofiler_compilers)
|
||||
include(rocprofiler_utilities)
|
||||
|
||||
target_compile_definitions(rocprofiler-build-flags INTERFACE $<$<CONFIG:DEBUG>:DEBUG>)
|
||||
|
||||
if(ROCPROFILER_BUILD_CI)
|
||||
rocprofiler_target_compile_definitions(rocprofiler-build-flags
|
||||
INTERFACE ROCPROFILER_CI)
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# dynamic linking and runtime libraries
|
||||
#
|
||||
if(CMAKE_DL_LIBS AND NOT "${CMAKE_DL_LIBS}" STREQUAL "dl")
|
||||
# if cmake provides dl library, use that
|
||||
set(dl_LIBRARY
|
||||
${CMAKE_DL_LIBS}
|
||||
CACHE FILEPATH "dynamic linking system library")
|
||||
endif()
|
||||
|
||||
foreach(_TYPE dl rt)
|
||||
if(NOT ${_TYPE}_LIBRARY)
|
||||
find_library(${_TYPE}_LIBRARY NAMES ${_TYPE})
|
||||
find_package_handle_standard_args(${_TYPE}-library REQUIRED_VARS ${_TYPE}_LIBRARY)
|
||||
if(${_TYPE}-library_FOUND)
|
||||
string(TOUPPER "${_TYPE}" _TYPE_UC)
|
||||
rocprofiler_target_compile_definitions(rocprofiler-${_TYPE}
|
||||
INTERFACE ROCPROFILER_${_TYPE_UC}=1)
|
||||
target_link_libraries(rocprofiler-${_TYPE} INTERFACE ${${_TYPE}_LIBRARY})
|
||||
if("${_TYPE}" STREQUAL "dl")
|
||||
# This instructs the linker to add all symbols, not only used ones, to the
|
||||
# dynamic symbol table. This option is needed for some uses of dlopen or
|
||||
# to allow obtaining backtraces from within a program.
|
||||
rocprofiler_target_compile_options(
|
||||
rocprofiler-${_TYPE}
|
||||
LANGUAGES C CXX
|
||||
LINK_LANGUAGES C CXX
|
||||
INTERFACE "-rdynamic")
|
||||
endif()
|
||||
else()
|
||||
rocprofiler_target_compile_definitions(rocprofiler-${_TYPE}
|
||||
INTERFACE ROCPROFILER_${_TYPE_UC}=0)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
target_link_libraries(rocprofiler-build-flags INTERFACE rocprofiler::rocprofiler-dl)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# set the compiler flags
|
||||
#
|
||||
rocprofiler_target_compile_options(rocprofiler-build-flags
|
||||
INTERFACE "-W" "-Wall" "-Wno-unknown-pragmas")
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# extra flags for debug information in debug or optimized binaries
|
||||
#
|
||||
|
||||
rocprofiler_target_compile_options(
|
||||
rocprofiler-debug-flags INTERFACE "-g3" "-fno-omit-frame-pointer"
|
||||
"-fno-optimize-sibling-calls")
|
||||
|
||||
target_compile_options(
|
||||
rocprofiler-debug-flags
|
||||
INTERFACE $<$<COMPILE_LANGUAGE:C>:$<$<C_COMPILER_ID:GNU>:-rdynamic>>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:$<$<CXX_COMPILER_ID:GNU>:-rdynamic>>)
|
||||
|
||||
if(NOT APPLE)
|
||||
target_link_options(rocprofiler-debug-flags INTERFACE
|
||||
$<$<CXX_COMPILER_ID:GNU>:-rdynamic>)
|
||||
endif()
|
||||
|
||||
if(dl_LIBRARY)
|
||||
target_link_libraries(rocprofiler-debug-flags INTERFACE ${dl_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(rt_LIBRARY)
|
||||
target_link_libraries(rocprofiler-debug-flags INTERFACE ${rt_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(ROCPROFILER_BUILD_DEBUG)
|
||||
target_link_libraries(rocprofiler-build-flags
|
||||
INTERFACE rocprofiler::rocprofiler-debug-flags)
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# debug-safe optimizations
|
||||
#
|
||||
rocprofiler_target_compile_options(
|
||||
rocprofiler-build-flags
|
||||
LANGUAGES CXX
|
||||
INTERFACE "-faligned-new")
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# fstack-protector
|
||||
#
|
||||
rocprofiler_target_compile_options(
|
||||
rocprofiler-stack-protector
|
||||
LANGUAGES C CXX
|
||||
INTERFACE "-fstack-protector-strong" "-Wstack-protector")
|
||||
|
||||
if(ROCPROFILER_BUILD_STACK_PROTECTOR)
|
||||
target_link_libraries(rocprofiler-build-flags
|
||||
INTERFACE rocprofiler::rocprofiler-stack-protector)
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# developer build flags
|
||||
#
|
||||
rocprofiler_target_compile_options(
|
||||
rocprofiler-developer-flags
|
||||
LANGUAGES C CXX
|
||||
INTERFACE "-Werror" "-Wdouble-promotion" "-Wshadow" "-Wextra"
|
||||
"-Wstack-usage=524288" # 512 KB
|
||||
)
|
||||
|
||||
if(ROCPROFILER_BUILD_DEVELOPER)
|
||||
target_link_libraries(rocprofiler-build-flags
|
||||
INTERFACE rocprofiler::rocprofiler-developer-flags)
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# release build flags
|
||||
#
|
||||
rocprofiler_target_compile_options(
|
||||
rocprofiler-release-flags
|
||||
LANGUAGES C CXX
|
||||
INTERFACE "-g1" "-feliminate-unused-debug-symbols" "-gno-column-info"
|
||||
"-gno-variable-location-views" "-gline-tables-only")
|
||||
|
||||
if(ROCPROFILER_BUILD_RELEASE)
|
||||
target_link_libraries(rocprofiler-build-flags
|
||||
INTERFACE rocprofiler::rocprofiler-release-flags)
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# static lib flags
|
||||
#
|
||||
target_compile_options(
|
||||
rocprofiler-static-libgcc
|
||||
INTERFACE $<$<COMPILE_LANGUAGE:C>:$<$<C_COMPILER_ID:GNU>:-static-libgcc>>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:$<$<CXX_COMPILER_ID:GNU>:-static-libgcc>>)
|
||||
target_link_options(
|
||||
rocprofiler-static-libgcc INTERFACE
|
||||
$<$<COMPILE_LANGUAGE:C>:$<$<C_COMPILER_ID:GNU,Clang>:-static-libgcc>>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:$<$<CXX_COMPILER_ID:GNU,Clang>:-static-libgcc>>)
|
||||
|
||||
target_compile_options(
|
||||
rocprofiler-static-libstdcxx
|
||||
INTERFACE $<$<COMPILE_LANGUAGE:CXX>:$<$<CXX_COMPILER_ID:GNU>:-static-libstdc++>>)
|
||||
target_link_options(
|
||||
rocprofiler-static-libstdcxx INTERFACE
|
||||
$<$<COMPILE_LANGUAGE:CXX>:$<$<CXX_COMPILER_ID:GNU,Clang>:-static-libstdc++>>)
|
||||
|
||||
if(ROCPROFILER_BUILD_STATIC_LIBGCC)
|
||||
target_link_libraries(rocprofiler-build-flags
|
||||
INTERFACE rocprofiler::rocprofiler-static-libgcc)
|
||||
endif()
|
||||
|
||||
if(ROCPROFILER_BUILD_STATIC_LIBSTDCXX)
|
||||
target_link_libraries(rocprofiler-build-flags
|
||||
INTERFACE rocprofiler::rocprofiler-static-libstdcxx)
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# user customization
|
||||
#
|
||||
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
|
||||
if(NOT APPLE OR "$ENV{CONDA_PYTHON_EXE}" STREQUAL "")
|
||||
rocprofiler_target_user_flags(rocprofiler-build-flags "CXX")
|
||||
endif()
|
||||
@@ -0,0 +1,350 @@
|
||||
# include guard
|
||||
# ########################################################################################
|
||||
#
|
||||
# Compilers
|
||||
#
|
||||
# ########################################################################################
|
||||
#
|
||||
# sets (cached):
|
||||
#
|
||||
# CMAKE_C_COMPILER_IS_<TYPE> CMAKE_CXX_COMPILER_IS_<TYPE>
|
||||
#
|
||||
# where TYPE is: - GNU - CLANG - INTEL - INTEL_ICC - INTEL_ICPC - PGI - XLC - HP_ACC -
|
||||
# MIPS - MSVC
|
||||
#
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCSourceCompiles)
|
||||
include(CheckCSourceRuns)
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CheckCXXSourceRuns)
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
include(rocprofiler_utilities)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# macro converting string to list
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
macro(ROCPROFILER_TO_LIST _VAR _STR)
|
||||
string(REPLACE " " " " ${_VAR} "${_STR}")
|
||||
string(REPLACE " " ";" ${_VAR} "${_STR}")
|
||||
endmacro()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# macro converting string to list
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
macro(ROCPROFILER_TO_STRING _VAR _STR)
|
||||
string(REPLACE ";" " " ${_VAR} "${_STR}")
|
||||
endmacro()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# Macro to add to string
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
macro(add _VAR _FLAG)
|
||||
if(NOT "${_FLAG}" STREQUAL "")
|
||||
if("${${_VAR}}" STREQUAL "")
|
||||
set(${_VAR} "${_FLAG}")
|
||||
else()
|
||||
set(${_VAR} "${${_VAR}} ${_FLAG}")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# call before running check_{c,cxx}_compiler_flag
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
macro(ROCPROFILER_BEGIN_FLAG_CHECK)
|
||||
if(ROCPROFILER_QUIET_CONFIG)
|
||||
if(NOT DEFINED CMAKE_REQUIRED_QUIET)
|
||||
set(CMAKE_REQUIRED_QUIET OFF)
|
||||
endif()
|
||||
rocprofiler_save_variables(FLAG_CHECK VARIABLES CMAKE_REQUIRED_QUIET)
|
||||
set(CMAKE_REQUIRED_QUIET ON)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# call after running check_{c,cxx}_compiler_flag
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
macro(ROCPROFILER_END_FLAG_CHECK)
|
||||
if(ROCPROFILER_QUIET_CONFIG)
|
||||
rocprofiler_restore_variables(FLAG_CHECK VARIABLES CMAKE_REQUIRED_QUIET)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# check flag
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
function(ROCPROFILER_TARGET_COMPILE_OPTIONS _TARG_TARGET)
|
||||
cmake_parse_arguments(_TARG "BUILD_INTERFACE;FORCE" ""
|
||||
"PUBLIC;INTERFACE;PRIVATE;LANGUAGES;LINK_LANGUAGES" ${ARGN})
|
||||
|
||||
if(NOT _TARG_MODE)
|
||||
set(_TARG_MODE INTERFACE)
|
||||
endif()
|
||||
|
||||
get_property(_ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
set(_SUPPORTED_LANGUAGES "C" "CXX")
|
||||
|
||||
if(NOT _TARG_LANGUAGES)
|
||||
foreach(_LANG ${_ENABLED_LANGUAGES})
|
||||
if(_LANG IN_LIST _SUPPORTED_LANGUAGES)
|
||||
list(APPEND _TARG_LANGUAGES ${_LANG})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
string(TOLOWER "_${_TARG_TARGET}" _TARG_TARGET_LC)
|
||||
|
||||
function(rocprofiler_target_compile_option_impl _TARGET_IMPL _TARGET_MODE_IMPL
|
||||
_TARGET_LANG_IMPL _TARGET_FLAG_IMPL)
|
||||
if(_TARG_BUILD_INTERFACE)
|
||||
target_compile_options(
|
||||
${_TARGET_IMPL}
|
||||
${_TARGET_MODE_IMPL}
|
||||
$<BUILD_INTERFACE:$<$<COMPILE_LANGUAGE:${_TARGET_LANG_IMPL}>:${_TARGET_FLAG_IMPL}>>
|
||||
)
|
||||
else()
|
||||
target_compile_options(
|
||||
${_TARGET_IMPL} ${_TARGET_MODE_IMPL}
|
||||
$<$<COMPILE_LANGUAGE:${_TARGET_LANG_IMPL}>:${_TARGET_FLAG_IMPL}>)
|
||||
endif()
|
||||
|
||||
if("${_TARGET_LANG_IMPL}" IN_LIST _TARG_LINK_LANGUAGES)
|
||||
if(_TARG_BUILD_INTERFACE)
|
||||
target_link_options(
|
||||
${_TARGET_IMPL}
|
||||
${_TARGET_MODE_IMPL}
|
||||
$<BUILD_INTERFACE:$<$<LINK_LANGUAGE:${_TARGET_LANG_IMPL}>:${_TARGET_FLAG_IMPL}>>
|
||||
)
|
||||
else()
|
||||
target_link_options(
|
||||
${_TARGET_IMPL} ${_TARGET_MODE_IMPL}
|
||||
$<$<LINK_LANGUAGE:${_TARGET_LANG_IMPL}>:${_TARGET_FLAG_IMPL}>)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(rocprofiler_target_compile_option_patch_name _P_LANG _P_IN _P_OUT)
|
||||
string(TOLOWER "${_P_LANG}" _P_LANG)
|
||||
string(REGEX REPLACE "^(/|-)" "${_P_LANG}${_TARG_TARGET_LC}_" _NAME "${_P_IN}")
|
||||
string(REPLACE "-" "_" _NAME "${_NAME}")
|
||||
string(REPLACE " " "_" _NAME "${_NAME}")
|
||||
string(REPLACE "=" "_" _NAME "${_NAME}")
|
||||
set(${_P_OUT}
|
||||
"${_NAME}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(NOT DEFINED rocprofiler_c_error AND NOT DEFINED rocprofiler_cxx_error)
|
||||
rocprofiler_begin_flag_check()
|
||||
check_c_compiler_flag("-Werror" c_rocprofiler_werror)
|
||||
check_cxx_compiler_flag("-Werror" cxx_rocprofiler_werror)
|
||||
rocprofiler_end_flag_check()
|
||||
endif()
|
||||
|
||||
foreach(_TARG_MODE PUBLIC INTERFACE PRIVATE)
|
||||
foreach(_FLAG ${_TARG_${_TARG_MODE}})
|
||||
foreach(_LANG ${_TARG_LANGUAGES})
|
||||
unset(FLAG_NAME)
|
||||
rocprofiler_target_compile_option_patch_name(${_LANG} "${_FLAG}"
|
||||
FLAG_NAME)
|
||||
|
||||
if(_TARG_FORCE)
|
||||
set(${FLAG_NAME}
|
||||
1
|
||||
CACHE INTERNAL "${_LANG} flag: ${_FLAG}")
|
||||
else()
|
||||
rocprofiler_begin_flag_check()
|
||||
|
||||
if("${_LANG}" STREQUAL "C")
|
||||
if(c_rocprofiler_werror)
|
||||
check_c_compiler_flag("${_FLAG} -Werror" ${FLAG_NAME})
|
||||
else()
|
||||
check_c_compiler_flag("${_FLAG}" ${FLAG_NAME})
|
||||
endif()
|
||||
elseif("${_LANG}" STREQUAL "CXX")
|
||||
if(cxx_rocprofiler_werror)
|
||||
check_cxx_compiler_flag("${_FLAG} -Werror" ${FLAG_NAME})
|
||||
else()
|
||||
check_cxx_compiler_flag("${_FLAG}" ${FLAG_NAME})
|
||||
endif()
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"rocprofiler_target_compile_option :: unknown language: ${_LANG}"
|
||||
)
|
||||
endif()
|
||||
|
||||
rocprofiler_end_flag_check()
|
||||
endif()
|
||||
|
||||
if(${FLAG_NAME})
|
||||
rocprofiler_target_compile_option_impl(${_TARG_TARGET} ${_TARG_MODE}
|
||||
${_LANG} "${_FLAG}")
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# add to any language
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
function(ROCPROFILER_TARGET_USER_FLAGS _TARGET _LANGUAGE)
|
||||
|
||||
set(_FLAGS ${${_LANGUAGE}FLAGS} $ENV{${_LANGUAGE}FLAGS} ${${_LANGUAGE}_FLAGS}
|
||||
$ENV{${_LANGUAGE}_FLAGS})
|
||||
|
||||
string(REPLACE " " ";" _FLAGS "${_FLAGS}")
|
||||
|
||||
set(${PROJECT_NAME}_${_LANGUAGE}_FLAGS
|
||||
${${PROJECT_NAME}_${_LANGUAGE}_FLAGS} ${_FLAGS}
|
||||
PARENT_SCOPE)
|
||||
|
||||
set(${PROJECT_NAME}_${_LANGUAGE}_COMPILE_OPTIONS
|
||||
${${PROJECT_NAME}_${_LANGUAGE}_COMPILE_OPTIONS} ${_FLAGS}
|
||||
PARENT_SCOPE)
|
||||
|
||||
target_compile_options(${_TARGET}
|
||||
INTERFACE $<$<COMPILE_LANGUAGE:${_LANGUAGE}>:${_FLAGS}>)
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# add compiler definition
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
function(ROCPROFILER_TARGET_COMPILE_DEFINITIONS _TARG _VIS)
|
||||
foreach(_DEF ${ARGN})
|
||||
if(NOT "${_DEF}" MATCHES "[A-Za-z_]+=.*" AND "${_DEF}" MATCHES "^ROCPROFILER_")
|
||||
set(_DEF "${_DEF}=1")
|
||||
endif()
|
||||
target_compile_definitions(${_TARG} ${_VIS} $<$<COMPILE_LANGUAGE:CXX>:${_DEF}>)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# determine compiler types for each language
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
foreach(LANG C CXX HIP CUDA)
|
||||
|
||||
if(NOT DEFINED CMAKE_${LANG}_COMPILER)
|
||||
set(CMAKE_${LANG}_COMPILER "")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_${LANG}_COMPILER_ID)
|
||||
set(CMAKE_${LANG}_COMPILER_ID "")
|
||||
endif()
|
||||
|
||||
function(SET_COMPILER_VAR VAR _BOOL)
|
||||
set(CMAKE_${LANG}_COMPILER_IS_${VAR}
|
||||
${_BOOL}
|
||||
CACHE INTERNAL "CMake ${LANG} compiler identification (${VAR})" FORCE)
|
||||
mark_as_advanced(CMAKE_${LANG}_COMPILER_IS_${VAR})
|
||||
endfunction()
|
||||
|
||||
if(("${LANG}" STREQUAL "C" AND CMAKE_COMPILER_IS_GNUCC)
|
||||
OR ("${LANG}" STREQUAL "CXX" AND CMAKE_COMPILER_IS_GNUCXX))
|
||||
|
||||
# GNU compiler
|
||||
set_compiler_var(GNU 1)
|
||||
|
||||
elseif(CMAKE_${LANG}_COMPILER MATCHES "icc.*")
|
||||
|
||||
# Intel icc compiler
|
||||
set_compiler_var(INTEL 1)
|
||||
set_compiler_var(INTEL_ICC 1)
|
||||
|
||||
elseif(CMAKE_${LANG}_COMPILER MATCHES "icpc.*")
|
||||
|
||||
# Intel icpc compiler
|
||||
set_compiler_var(INTEL 1)
|
||||
set_compiler_var(INTEL_ICPC 1)
|
||||
|
||||
elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "AppleClang")
|
||||
|
||||
# Clang/LLVM compiler
|
||||
set_compiler_var(CLANG 1)
|
||||
set_compiler_var(APPLE_CLANG 1)
|
||||
|
||||
elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "Clang")
|
||||
|
||||
# Clang/LLVM compiler
|
||||
set_compiler_var(CLANG 1)
|
||||
|
||||
# HIP Clang compiler
|
||||
if(CMAKE_${LANG}_COMPILER MATCHES "hipcc")
|
||||
set_compiler_var(HIPCC 1)
|
||||
endif()
|
||||
|
||||
elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "PGI")
|
||||
|
||||
# PGI compiler
|
||||
set_compiler_var(PGI 1)
|
||||
|
||||
elseif(CMAKE_${LANG}_COMPILER MATCHES "xlC" AND UNIX)
|
||||
|
||||
# IBM xlC compiler
|
||||
set_compiler_var(XLC 1)
|
||||
|
||||
elseif(CMAKE_${LANG}_COMPILER MATCHES "aCC" AND UNIX)
|
||||
|
||||
# HP aC++ compiler
|
||||
set_compiler_var(HP_ACC 1)
|
||||
|
||||
elseif(
|
||||
CMAKE_${LANG}_COMPILER MATCHES "CC"
|
||||
AND CMAKE_SYSTEM_NAME MATCHES "IRIX"
|
||||
AND UNIX)
|
||||
|
||||
# IRIX MIPSpro CC Compiler
|
||||
set_compiler_var(MIPS 1)
|
||||
|
||||
elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "Intel")
|
||||
|
||||
set_compiler_var(INTEL 1)
|
||||
|
||||
set(CTYPE ICC)
|
||||
if("${LANG}" STREQUAL "CXX")
|
||||
set(CTYPE ICPC)
|
||||
endif()
|
||||
|
||||
set_compiler_var(INTEL_${CTYPE} 1)
|
||||
|
||||
elseif(CMAKE_${LANG}_COMPILER MATCHES "MSVC")
|
||||
|
||||
# Windows Visual Studio compiler
|
||||
set_compiler_var(MSVC 1)
|
||||
|
||||
elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "NVIDIA")
|
||||
|
||||
# NVCC
|
||||
set_compiler_var(NVIDIA 1)
|
||||
|
||||
endif()
|
||||
|
||||
# set other to no
|
||||
foreach(
|
||||
TYPE
|
||||
GNU
|
||||
INTEL
|
||||
INTEL_ICC
|
||||
INTEL_ICPC
|
||||
APPLE_CLANG
|
||||
CLANG
|
||||
PGI
|
||||
XLC
|
||||
HP_ACC
|
||||
MIPS
|
||||
MSVC
|
||||
NVIDIA
|
||||
HIPCC)
|
||||
if(NOT DEFINED CMAKE_${LANG}_COMPILER_IS_${TYPE})
|
||||
set_compiler_var(${TYPE} 0)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
endforeach()
|
||||
@@ -0,0 +1,68 @@
|
||||
# include guard
|
||||
include_guard(GLOBAL)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME config)
|
||||
|
||||
install(
|
||||
EXPORT rocprofiler-library-targets
|
||||
FILE rocprofiler-library-targets.cmake
|
||||
NAMESPACE rocprofiler::
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler)
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
# install tree
|
||||
#
|
||||
set(PROJECT_INSTALL_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR})
|
||||
set(PROJECT_BUILD_TARGETS user)
|
||||
|
||||
configure_package_config_file(
|
||||
${PROJECT_SOURCE_DIR}/cmake/Templates/${PROJECT_NAME}-config.cmake.in
|
||||
${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler
|
||||
INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}
|
||||
PATH_VARS PROJECT_INSTALL_DIR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR)
|
||||
|
||||
write_basic_package_version_file(
|
||||
${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-version.cmake
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMinorVersion)
|
||||
|
||||
install(
|
||||
FILES
|
||||
${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake
|
||||
${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-version.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}
|
||||
OPTIONAL)
|
||||
|
||||
export(PACKAGE ${PROJECT_NAME})
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
# build tree
|
||||
#
|
||||
set(_BUILDTREE_EXPORT_DIR
|
||||
"${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler")
|
||||
|
||||
if(NOT EXISTS "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
|
||||
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${_BUILDTREE_EXPORT_DIR}")
|
||||
file(MAKE_DIRECTORY "${_BUILDTREE_EXPORT_DIR}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${_BUILDTREE_EXPORT_DIR}/rocprofiler-library-targets.cmake")
|
||||
file(TOUCH "${_BUILDTREE_EXPORT_DIR}/rocprofiler-library-targets.cmake")
|
||||
endif()
|
||||
|
||||
export(
|
||||
EXPORT rocprofiler-library-targets
|
||||
NAMESPACE rocprofiler::
|
||||
FILE "${_BUILDTREE_EXPORT_DIR}/rocprofiler-library-targets.cmake")
|
||||
|
||||
set(rocprofiler_DIR
|
||||
"${_BUILDTREE_EXPORT_DIR}"
|
||||
CACHE PATH "rocprofiler" FORCE)
|
||||
@@ -0,0 +1,141 @@
|
||||
# include guard
|
||||
include_guard(DIRECTORY)
|
||||
|
||||
# ########################################################################################
|
||||
#
|
||||
# External Packages are found here
|
||||
#
|
||||
# ########################################################################################
|
||||
|
||||
target_include_directories(
|
||||
rocprofiler-headers
|
||||
INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/source/include>
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/source>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
|
||||
# include threading because of rooflines
|
||||
target_link_libraries(rocprofiler-headers INTERFACE rocprofiler::rocprofiler-threading)
|
||||
|
||||
# ensure the env overrides the appending /opt/rocm later
|
||||
string(REPLACE ":" ";" CMAKE_PREFIX_PATH "$ENV{CMAKE_PREFIX_PATH};${CMAKE_PREFIX_PATH}")
|
||||
|
||||
set(ROCPROFILER_DEFAULT_ROCM_PATH
|
||||
/opt/rocm
|
||||
CACHE PATH "Default search path for ROCM")
|
||||
if(EXISTS ${ROCPROFILER_DEFAULT_ROCM_PATH})
|
||||
get_filename_component(_ROCPROFILER_DEFAULT_ROCM_PATH
|
||||
"${ROCPROFILER_DEFAULT_ROCM_PATH}" REALPATH)
|
||||
|
||||
if(NOT "${_ROCPROFILER_DEFAULT_ROCM_PATH}" STREQUAL
|
||||
"${ROCPROFILER_DEFAULT_ROCM_PATH}")
|
||||
set(ROCPROFILER_DEFAULT_ROCM_PATH
|
||||
"${_ROCPROFILER_DEFAULT_ROCM_PATH}"
|
||||
CACHE PATH "Default search path for ROCM" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# Threading
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD ON)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG OFF)
|
||||
|
||||
find_library(pthread_LIBRARY NAMES pthread pthreads)
|
||||
find_package_handle_standard_args(pthread-library REQUIRED_VARS pthread_LIBRARY)
|
||||
|
||||
find_library(pthread_LIBRARY NAMES pthread pthreads)
|
||||
find_package_handle_standard_args(pthread-library REQUIRED_VARS pthread_LIBRARY)
|
||||
|
||||
if(pthread_LIBRARY)
|
||||
target_link_libraries(rocprofiler-threading INTERFACE ${pthread_LIBRARY})
|
||||
else()
|
||||
find_package(Threads ${rocprofiler_FIND_QUIETLY} ${rocprofiler_FIND_REQUIREMENT})
|
||||
if(Threads_FOUND)
|
||||
target_link_libraries(rocprofiler-threading INTERFACE Threads::Threads)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# dynamic linking (dl) and runtime (rt) libraries
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
foreach(_LIB dl rt)
|
||||
find_library(${_LIB}_LIBRARY NAMES ${_LIB})
|
||||
find_package_handle_standard_args(${_LIB}-library REQUIRED_VARS ${_LIB}_LIBRARY)
|
||||
if(${_LIB}_LIBRARY)
|
||||
target_link_libraries(rocprofiler-threading INTERFACE ${${_LIB}_LIBRARY})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# stdc++fs (filesystem) library
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_library(stdcxxfs_LIBRARY NAMES stdc++fs)
|
||||
find_package_handle_standard_args(stdcxxfs-library REQUIRED_VARS stdcxxfs_LIBRARY)
|
||||
|
||||
if(stdcxxfs_LIBRARY)
|
||||
target_link_libraries(rocprofiler-stdcxxfs INTERFACE ${stdcxxfs_LIBRARY})
|
||||
else()
|
||||
target_link_libraries(rocprofiler-stdcxxfs INTERFACE stdc++fs)
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# HIP
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_package(rocm_version REQUIRED)
|
||||
list(APPEND CMAKE_PREFIX_PATH "${rocm_version_DIR}" "${rocm_version_DIR}/llvm")
|
||||
list(APPEND CMAKE_MODULE_PATH "${rocm_version_DIR}/hip/cmake"
|
||||
"${rocm_version_DIR}/lib/cmake")
|
||||
find_package(hip REQUIRED CONFIG)
|
||||
target_link_libraries(rocprofiler-hip INTERFACE hip::host)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# HSA runtime
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_package(
|
||||
hsa-runtime64
|
||||
REQUIRED
|
||||
CONFIG
|
||||
HINTS
|
||||
${rocm_version_DIR}
|
||||
${ROCM_PATH}
|
||||
PATHS
|
||||
${rocm_version_DIR}
|
||||
${ROCM_PATH})
|
||||
|
||||
target_link_libraries(rocprofiler-hsa-runtime INTERFACE hsa-runtime64::hsa-runtime64)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# amd comgr
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_package(
|
||||
amd_comgr
|
||||
REQUIRED
|
||||
CONFIG
|
||||
HINTS
|
||||
${rocm_version_DIR}
|
||||
${ROCM_PATH}
|
||||
PATHS
|
||||
${rocm_version_DIR}
|
||||
${ROCM_PATH}
|
||||
PATH_SUFFIXES
|
||||
lib/cmake/amd_comgr)
|
||||
|
||||
target_link_libraries(rocprofiler-amd-comgr INTERFACE amd_comgr)
|
||||
@@ -0,0 +1,128 @@
|
||||
# configure packaging
|
||||
|
||||
function(rocprofiler_parse_release)
|
||||
if(EXISTS /etc/lsb-release AND NOT IS_DIRECTORY /etc/lsb-release)
|
||||
file(READ /etc/lsb-release _LSB_RELEASE)
|
||||
if(_LSB_RELEASE)
|
||||
string(REGEX
|
||||
REPLACE "DISTRIB_ID=(.*)\nDISTRIB_RELEASE=(.*)\nDISTRIB_CODENAME=.*"
|
||||
"\\1-\\2" _SYSTEM_NAME "${_LSB_RELEASE}")
|
||||
endif()
|
||||
elseif(EXISTS /etc/os-release AND NOT IS_DIRECTORY /etc/os-release)
|
||||
file(READ /etc/os-release _OS_RELEASE)
|
||||
if(_OS_RELEASE)
|
||||
string(REPLACE "\"" "" _OS_RELEASE "${_OS_RELEASE}")
|
||||
string(REPLACE "-" " " _OS_RELEASE "${_OS_RELEASE}")
|
||||
string(REGEX REPLACE "NAME=.*\nVERSION=([0-9\.]+).*\nID=([a-z]+).*" "\\2-\\1"
|
||||
_SYSTEM_NAME "${_OS_RELEASE}")
|
||||
endif()
|
||||
endif()
|
||||
string(TOLOWER "${_SYSTEM_NAME}" _SYSTEM_NAME)
|
||||
if(NOT _SYSTEM_NAME)
|
||||
set(_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}")
|
||||
endif()
|
||||
set(_SYSTEM_NAME
|
||||
"${_SYSTEM_NAME}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# parse either /etc/lsb-release or /etc/os-release
|
||||
rocprofiler_parse_release()
|
||||
|
||||
if(NOT _SYSTEM_NAME)
|
||||
set(_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}")
|
||||
endif()
|
||||
|
||||
# Add packaging directives
|
||||
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
|
||||
set(CPACK_PACKAGE_VENDOR "Advanced Micro Devices, Inc.")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
|
||||
set(CPACK_PACKAGE_CONTACT "jonathan.madsen@amd.com")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
|
||||
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
|
||||
set(ROCPROFILER_CPACK_SYSTEM_NAME
|
||||
"${_SYSTEM_NAME}"
|
||||
CACHE STRING "System name, e.g. Linux or Ubuntu-18.04")
|
||||
set(ROCPROFILER_CPACK_PACKAGE_SUFFIX "")
|
||||
|
||||
set(CPACK_PACKAGE_FILE_NAME
|
||||
"${CPACK_PACKAGE_NAME}-${ROCPROFILER_VERSION}-${ROCPROFILER_CPACK_SYSTEM_NAME}${ROCPROFILER_CPACK_PACKAGE_SUFFIX}"
|
||||
)
|
||||
if(DEFINED ENV{CPACK_PACKAGE_FILE_NAME})
|
||||
set(CPACK_PACKAGE_FILE_NAME $ENV{CPACK_PACKAGE_FILE_NAME})
|
||||
endif()
|
||||
|
||||
set(ROCPROFILER_PACKAGE_FILE_NAME
|
||||
${CPACK_PACKAGE_NAME}-${ROCPROFILER_VERSION}-${ROCPROFILER_CPACK_SYSTEM_NAME}${ROCPROFILER_CPACK_PACKAGE_SUFFIX}
|
||||
)
|
||||
rocprofiler_add_feature(ROCPROFILER_PACKAGE_FILE_NAME "CPack filename")
|
||||
|
||||
# -------------------------------------------------------------------------------------- #
|
||||
#
|
||||
# Debian package specific variables
|
||||
#
|
||||
# -------------------------------------------------------------------------------------- #
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${PROJECT_HOMEPAGE_URL}")
|
||||
set(CPACK_DEBIAN_PACKAGE_RELEASE
|
||||
"${ROCPROFILER_CPACK_SYSTEM_NAME}${ROCPROFILER_CPACK_PACKAGE_SUFFIX}")
|
||||
string(REGEX REPLACE "([a-zA-Z])-([0-9])" "\\1\\2" CPACK_DEBIAN_PACKAGE_RELEASE
|
||||
"${CPACK_DEBIAN_PACKAGE_RELEASE}")
|
||||
string(REPLACE "-" "~" CPACK_DEBIAN_PACKAGE_RELEASE "${CPACK_DEBIAN_PACKAGE_RELEASE}")
|
||||
if(DEFINED ENV{CPACK_DEBIAN_PACKAGE_RELEASE})
|
||||
set(CPACK_DEBIAN_PACKAGE_RELEASE $ENV{CPACK_DEBIAN_PACKAGE_RELEASE})
|
||||
endif()
|
||||
|
||||
set(_DEBIAN_PACKAGE_DEPENDS "")
|
||||
if(rocm_version_FOUND)
|
||||
set(_ROCPROFILER_SUFFIX " (>= 1.0.0.${rocm_version_NUMERIC_VERSION})")
|
||||
set(_ROCTRACER_SUFFIX " (>= 1.0.0.${rocm_version_NUMERIC_VERSION})")
|
||||
set(_ROCM_SMI_SUFFIX
|
||||
" (>= ${rocm_version_MAJOR_VERSION}.0.0.${rocm_version_NUMERIC_VERSION})")
|
||||
endif()
|
||||
string(REPLACE ";" ", " _DEBIAN_PACKAGE_DEPENDS "${_DEBIAN_PACKAGE_DEPENDS}")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS
|
||||
"${_DEBIAN_PACKAGE_DEPENDS}"
|
||||
CACHE STRING "Debian package dependencies" FORCE)
|
||||
rocprofiler_add_feature(CPACK_DEBIAN_PACKAGE_DEPENDS "Debian package dependencies")
|
||||
set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")
|
||||
|
||||
# -------------------------------------------------------------------------------------- #
|
||||
#
|
||||
# RPM package specific variables
|
||||
#
|
||||
# -------------------------------------------------------------------------------------- #
|
||||
|
||||
if(DEFINED CPACK_PACKAGING_INSTALL_PREFIX)
|
||||
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}")
|
||||
endif()
|
||||
|
||||
set(CPACK_RPM_PACKAGE_RELEASE
|
||||
"${ROCPROFILER_CPACK_SYSTEM_NAME}${ROCPROFILER_CPACK_PACKAGE_SUFFIX}")
|
||||
string(REGEX REPLACE "([a-zA-Z])-([0-9])" "\\1\\2" CPACK_RPM_PACKAGE_RELEASE
|
||||
"${CPACK_RPM_PACKAGE_RELEASE}")
|
||||
string(REPLACE "-" "~" CPACK_RPM_PACKAGE_RELEASE "${CPACK_RPM_PACKAGE_RELEASE}")
|
||||
if(DEFINED ENV{CPACK_RPM_PACKAGE_RELEASE})
|
||||
set(CPACK_RPM_PACKAGE_RELEASE $ENV{CPACK_RPM_PACKAGE_RELEASE})
|
||||
endif()
|
||||
|
||||
# Get rpm distro
|
||||
if(CPACK_RPM_PACKAGE_RELEASE)
|
||||
set(CPACK_RPM_PACKAGE_RELEASE_DIST ON)
|
||||
endif()
|
||||
set(CPACK_RPM_FILE_NAME "RPM-DEFAULT")
|
||||
|
||||
# -------------------------------------------------------------------------------------- #
|
||||
#
|
||||
# Prepare final version for the CPACK use
|
||||
#
|
||||
# -------------------------------------------------------------------------------------- #
|
||||
|
||||
set(CPACK_PACKAGE_VERSION
|
||||
"${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}"
|
||||
)
|
||||
|
||||
include(CPack)
|
||||
@@ -0,0 +1,102 @@
|
||||
# ------------------------------------------------------------------------------#
|
||||
#
|
||||
# creates following targets to format code:
|
||||
# - format
|
||||
# - format-source
|
||||
# - format-cmake
|
||||
# - format-python
|
||||
# - format-rocprofiler-source
|
||||
# - format-rocprofiler-cmake
|
||||
# - format-rocprofiler-python
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
include_guard(DIRECTORY)
|
||||
|
||||
find_program(ROCPROFILER_CLANG_FORMAT_EXE NAMES clang-format-11 clang-format-mp-11)
|
||||
find_program(ROCPROFILER_CMAKE_FORMAT_EXE NAMES cmake-format)
|
||||
find_program(ROCPROFILER_BLACK_FORMAT_EXE NAMES black)
|
||||
|
||||
add_custom_target(format-rocprofiler)
|
||||
if(NOT TARGET format)
|
||||
add_custom_target(format)
|
||||
endif()
|
||||
foreach(_TYPE source python cmake)
|
||||
if(NOT TARGET format-${_TYPE})
|
||||
add_custom_target(format-${_TYPE})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(ROCPROFILER_CLANG_FORMAT_EXE
|
||||
OR ROCPROFILER_BLACK_FORMAT_EXE
|
||||
OR ROCPROFILER_CMAKE_FORMAT_EXE)
|
||||
|
||||
set(rocp_source_files)
|
||||
set(rocp_header_files)
|
||||
set(rocp_python_files)
|
||||
set(rocp_cmake_files ${PROJECT_SOURCE_DIR}/CMakeLists.txt
|
||||
${PROJECT_SOURCE_DIR}/external/CMakeLists.txt)
|
||||
|
||||
foreach(_DIR cmake samples source tests)
|
||||
foreach(_TYPE header_files source_files cmake_files python_files)
|
||||
set(${_TYPE})
|
||||
endforeach()
|
||||
file(GLOB_RECURSE header_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.h
|
||||
${PROJECT_SOURCE_DIR}/${_DIR}/*.hpp)
|
||||
file(GLOB_RECURSE source_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.c
|
||||
${PROJECT_SOURCE_DIR}/${_DIR}/*.cpp)
|
||||
file(GLOB_RECURSE cmake_files ${PROJECT_SOURCE_DIR}/${_DIR}/*CMakeLists.txt
|
||||
${PROJECT_SOURCE_DIR}/${_DIR}/*.cmake)
|
||||
file(GLOB_RECURSE python_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.py)
|
||||
foreach(_TYPE header_files source_files cmake_files python_files)
|
||||
list(APPEND rocp_${_TYPE} ${${_TYPE}})
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
foreach(_TYPE header_files source_files cmake_files python_files)
|
||||
if(rocp_${_TYPE})
|
||||
list(REMOVE_DUPLICATES rocp_${_TYPE})
|
||||
list(SORT rocp_${_TYPE})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(ROCPROFILER_CLANG_FORMAT_EXE)
|
||||
add_custom_target(
|
||||
format-rocprofiler-source
|
||||
${ROCPROFILER_CLANG_FORMAT_EXE} -i ${rocp_header_files} ${rocp_source_files}
|
||||
COMMENT
|
||||
"[rocprofiler] Running source formatter ${ROCPROFILER_CLANG_FORMAT_EXE}..."
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ROCPROFILER_BLACK_FORMAT_EXE)
|
||||
add_custom_target(
|
||||
format-rocprofiler-python
|
||||
${ROCPROFILER_BLACK_FORMAT_EXE} -q ${rocp_python_files}
|
||||
COMMENT
|
||||
"[rocprofiler] Running Python formatter ${ROCPROFILER_BLACK_FORMAT_EXE}..."
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ROCPROFILER_CMAKE_FORMAT_EXE)
|
||||
add_custom_target(
|
||||
format-rocprofiler-cmake
|
||||
${ROCPROFILER_CMAKE_FORMAT_EXE} -i ${rocp_cmake_files}
|
||||
COMMENT
|
||||
"[rocprofiler] Running CMake formatter ${ROCPROFILER_CMAKE_FORMAT_EXE}..."
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(_TYPE source python cmake)
|
||||
if(TARGET format-rocprofiler-${_TYPE})
|
||||
add_dependencies(format-rocprofiler format-rocprofiler-${_TYPE})
|
||||
add_dependencies(format-${_TYPE} format-rocprofiler-${_TYPE})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(_TYPE source python)
|
||||
if(TARGET format-rocprofiler-${_TYPE})
|
||||
add_dependencies(format format-rocprofiler-${_TYPE})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
@@ -0,0 +1,44 @@
|
||||
#
|
||||
#
|
||||
# Forward declaration of all INTERFACE targets
|
||||
#
|
||||
#
|
||||
|
||||
include(rocprofiler_utilities)
|
||||
|
||||
#
|
||||
# interfaces for build flags
|
||||
#
|
||||
rocprofiler_add_interface_library(
|
||||
rocprofiler-headers
|
||||
"Provides minimal set of include flags to compile with rocprofiler")
|
||||
rocprofiler_add_interface_library(rocprofiler-build-flags
|
||||
"Provides generalized build flags for rocprofiler")
|
||||
rocprofiler_add_interface_library(rocprofiler-threading "Enables multithreading support")
|
||||
rocprofiler_add_interface_library(rocprofiler-perfetto "Enables Perfetto support")
|
||||
rocprofiler_add_interface_library(rocprofiler-compile-definitions "Compile definitions")
|
||||
rocprofiler_add_interface_library(rocprofiler-static-libgcc
|
||||
"Link to static version of libgcc")
|
||||
rocprofiler_add_interface_library(rocprofiler-static-libstdcxx
|
||||
"Link to static version of libstdc++")
|
||||
rocprofiler_add_interface_library(rocprofiler-developer-flags
|
||||
"Compiler flags for developers (more warnings, etc.)")
|
||||
rocprofiler_add_interface_library(rocprofiler-debug-flags
|
||||
"Compiler flags for more debug info")
|
||||
rocprofiler_add_interface_library(rocprofiler-release-flags
|
||||
"Compiler flags for more debug info")
|
||||
rocprofiler_add_interface_library(rocprofiler-stack-protector
|
||||
"Adds stack-protector compiler flags")
|
||||
rocprofiler_add_interface_library(rocprofiler-memcheck INTERFACE)
|
||||
|
||||
#
|
||||
# interfaces for libraries
|
||||
#
|
||||
rocprofiler_add_interface_library(rocprofiler-dl
|
||||
"Build flags for dynamic linking library")
|
||||
rocprofiler_add_interface_library(rocprofiler-rt "Build flags for runtime library")
|
||||
rocprofiler_add_interface_library(rocprofiler-hip "HIP library")
|
||||
rocprofiler_add_interface_library(rocprofiler-hsa-runtime "HSA runtime library")
|
||||
rocprofiler_add_interface_library(rocprofiler-amd-comgr "AMD comgr library")
|
||||
rocprofiler_add_interface_library(rocprofiler-googletest "Google Test library" INTERNAL)
|
||||
rocprofiler_add_interface_library(rocprofiler-stdcxxfs "C++ filesystem library" INTERNAL)
|
||||
@@ -0,0 +1,36 @@
|
||||
include_guard(GLOBAL)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# Clang Tidy
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_program(ROCPROFILER_CLANG_TIDY_COMMAND NAMES clang-tidy)
|
||||
|
||||
macro(ROCPROFILER_ACTIVATE_CLANG_TIDY)
|
||||
if(ROCPROFILER_ENABLE_CLANG_TIDY)
|
||||
if(NOT ROCPROFILER_CLANG_TIDY_COMMAND)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"ROCPROFILER_ENABLE_CLANG_TIDY is ON but clang-tidy is not found!")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_CLANG_TIDY ${ROCPROFILER_CLANG_TIDY_COMMAND}
|
||||
-header-filter=${PROJECT_SOURCE_DIR}/.*)
|
||||
|
||||
# Create a preprocessor definition that depends on .clang-tidy content so the
|
||||
# compile command will change when .clang-tidy changes. This ensures that a
|
||||
# subsequent build re-runs clang-tidy on all sources even if they do not otherwise
|
||||
# need to be recompiled. Nothing actually uses this definition. We add it to
|
||||
# targets on which we run clang-tidy just to get the build dependency on the
|
||||
# .clang-tidy file.
|
||||
file(SHA1 ${PROJECT_SOURCE_DIR}/.clang-tidy clang_tidy_sha1)
|
||||
set(CLANG_TIDY_DEFINITIONS "CLANG_TIDY_SHA1=${clang_tidy_sha1}")
|
||||
unset(clang_tidy_sha1)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(ROCPROFILER_DEACTIVATE_CLANG_TIDY)
|
||||
set(CMAKE_CXX_CLANG_TIDY)
|
||||
endmacro()
|
||||
@@ -0,0 +1,67 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
set(ROCPROFILER_MEMCHECK_TYPES "ThreadSanitizer" "AddressSanitizer" "LeakSanitizer"
|
||||
"MemorySanitizer" "UndefinedBehaviorSanitizer")
|
||||
|
||||
if(ROCPROFILER_MEMCHECK AND NOT ROCPROFILER_MEMCHECK IN_LIST ROCPROFILER_MEMCHECK_TYPES)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Unsupported memcheck type '${ROCPROFILER_MEMCHECK}'. Options: ${ROCPROFILER_MEMCHECK_TYPES}"
|
||||
)
|
||||
endif()
|
||||
|
||||
set_property(CACHE ROCPROFILER_MEMCHECK PROPERTY STRINGS "${ROCPROFILER_MEMCHECK_TYPES}")
|
||||
|
||||
function(rocprofiler_add_memcheck_flags _TYPE)
|
||||
target_compile_options(
|
||||
rocprofiler-memcheck
|
||||
INTERFACE $<BUILD_INTERFACE:-g3 -Og -fno-omit-frame-pointer
|
||||
-fno-optimize-sibling-calls -fno-inline-functions -fsanitize=${_TYPE}>)
|
||||
target_link_options(rocprofiler-memcheck INTERFACE
|
||||
$<BUILD_INTERFACE:-fsanitize=${_TYPE} -Wl,--no-undefined>)
|
||||
endfunction()
|
||||
|
||||
function(rocprofiler_set_memcheck_env _TYPE _LIB_BASE)
|
||||
set(_LIBS ${_LIB_BASE})
|
||||
|
||||
foreach(_N 6 5 4 3 2 1 0)
|
||||
list(
|
||||
APPEND _LIBS
|
||||
${CMAKE_SHARED_LIBRARY_PREFIX}${_LIB_BASE}${CMAKE_SHARED_LIBRARY_SUFFIX}.${_N}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
foreach(_LIB ${_LIBS})
|
||||
if(NOT ${_TYPE}_LIBRARY)
|
||||
find_library(${_TYPE}_LIBRARY NAMES ${_LIB} ${ARGN})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
target_link_libraries(rocprofiler-memcheck INTERFACE ${_LIB_BASE})
|
||||
|
||||
if(${_TYPE}_LIBRARY)
|
||||
set(ROCPROFILER_MEMCHECK_PRELOAD_ENV
|
||||
" LD_PRELOAD=${${_TYPE}_LIBRARY} "
|
||||
CACHE INTERNAL " LD_PRELOAD env variable for tests " FORCE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# always unset so that it doesn't preload if memcheck disabled
|
||||
unset(ROCPROFILER_MEMCHECK_PRELOAD_ENV CACHE)
|
||||
|
||||
if(ROCPROFILER_MEMCHECK STREQUAL " AddressSanitizer ")
|
||||
rocprofiler_add_memcheck_flags(" address ")
|
||||
rocprofiler_set_memcheck_env(" ${ROCPROFILER_MEMCHECK}" "asan ")
|
||||
elseif(ROCPROFILER_MEMCHECK STREQUAL " LeakSanitizer ")
|
||||
rocprofiler_add_memcheck_flags(" leak ")
|
||||
rocprofiler_set_memcheck_env(" ${ROCPROFILER_MEMCHECK}" "lsan ")
|
||||
elseif(ROCPROFILER_MEMCHECK STREQUAL " MemorySanitizer ")
|
||||
rocprofiler_add_memcheck_flags(" memory ")
|
||||
elseif(ROCPROFILER_MEMCHECK STREQUAL " ThreadSanitizer ")
|
||||
rocprofiler_add_memcheck_flags(" thread ")
|
||||
rocprofiler_set_memcheck_env(" ${ROCPROFILER_MEMCHECK}" "tsan ")
|
||||
elseif(ROCPROFILER_MEMCHECK STREQUAL " UndefinedBehaviorSanitizer ")
|
||||
rocprofiler_add_memcheck_flags(" undefined ")
|
||||
rocprofiler_set_memcheck_env(" ${ROCPROFILER_MEMCHECK}" "ubsan ")
|
||||
endif()
|
||||
@@ -0,0 +1,104 @@
|
||||
#
|
||||
# rocprofiler_options.cmake
|
||||
#
|
||||
# Configure miscellaneous settings
|
||||
#
|
||||
# standard cmake options
|
||||
rocprofiler_add_option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
rocprofiler_add_option(BUILD_STATIC_LIBS "Build static libraries" OFF)
|
||||
rocprofiler_add_option(CMAKE_POSITION_INDEPENDENT_CODE "Build position independent code"
|
||||
ON)
|
||||
|
||||
# export compile commands in the project
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_EXTENSIONS OFF)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
rocprofiler_add_option(ROCPROFILER_BUILD_TESTS "Enable building the tests" OFF)
|
||||
rocprofiler_add_option(ROCPROFILER_BUILD_SAMPLES "Enable building the code samples" OFF)
|
||||
|
||||
# CLI and FILE plugins are always built
|
||||
foreach(_PLUGIN "ATT" "CTF" "PERFETTO")
|
||||
rocprofiler_add_option(ROCPROFILER_BUILD_PLUGIN_${_PLUGIN}
|
||||
"Enable building the ${_PLUGIN} plugin" ON)
|
||||
endforeach()
|
||||
|
||||
rocprofiler_add_option(ROCPROFILER_DEBUG_TRACE "Enable debug tracing" OFF ADVANCED)
|
||||
rocprofiler_add_option(ROCPROFILER_LD_AQLPROFILE
|
||||
"Enable direct loading of AQL-profile HSA extension" OFF ADVANCED)
|
||||
rocprofiler_add_option(ROCPROFILER_BUILD_CI "Enable continuous integration additions" OFF
|
||||
ADVANCED)
|
||||
rocprofiler_add_option(ROCPROFILER_ENABLE_CLANG_TIDY "Enable clang-tidy checks" OFF
|
||||
ADVANCED)
|
||||
rocprofiler_add_option(ROCPROFILER_BUILD_WERROR "Any compiler warnings are errors" OFF
|
||||
ADVANCED)
|
||||
|
||||
rocprofiler_add_option(
|
||||
ROCPROFILER_BUILD_DEVELOPER "Extra build flags for development like -Werror"
|
||||
${ROCPROFILER_BUILD_CI} ADVANCED)
|
||||
rocprofiler_add_option(ROCPROFILER_BUILD_RELEASE "Build with minimal debug info" OFF
|
||||
ADVANCED)
|
||||
rocprofiler_add_option(ROCPROFILER_BUILD_DEBUG "Build with extra debug info" OFF ADVANCED)
|
||||
rocprofiler_add_option(ROCPROFILER_BUILD_STATIC_LIBGCC
|
||||
"Build with -static-libgcc if possible" OFF ADVANCED)
|
||||
rocprofiler_add_option(ROCPROFILER_BUILD_STATIC_LIBSTDCXX
|
||||
"Build with -static-libstdc++ if possible" OFF ADVANCED)
|
||||
rocprofiler_add_option(ROCPROFILER_BUILD_STACK_PROTECTOR "Build with -fstack-protector"
|
||||
OFF ADVANCED)
|
||||
|
||||
# In the future, we will do this even with clang-tidy enabled
|
||||
if(ROCPROFILER_BUILD_CI AND NOT ROCPROFILER_ENABLE_CLANG_TIDY)
|
||||
message(STATUS "Forcing ROCPROFILER_BUILD_WERROR=ON because ROCPROFILER_BUILD_CI=ON")
|
||||
set(ROCPROFILER_BUILD_WERROR
|
||||
ON
|
||||
CACHE BOOL
|
||||
"Any compiler warnings are errors (forced due ROCPROFILER_BUILD_CI=ON)"
|
||||
FORCE)
|
||||
endif()
|
||||
|
||||
set(ROCPROFILER_BUILD_TYPES "Release" "RelWithDebInfo" "Debug" "MinSizeRel" "Coverage")
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE
|
||||
"Release"
|
||||
CACHE STRING "Build type" FORCE)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE IN_LIST ROCPROFILER_BUILD_TYPES)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Unsupported build type '${CMAKE_BUILD_TYPE}'. Options: ${ROCPROFILER_BUILD_TYPES}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ROCPROFILER_BUILD_CI)
|
||||
foreach(_BUILD_TYPE ${ROCPROFILER_BUILD_TYPES})
|
||||
string(TOUPPER "${_BUILD_TYPE}" _BUILD_TYPE)
|
||||
|
||||
# remove NDEBUG preprocessor def so that asserts are triggered
|
||||
string(REGEX REPLACE ".DNDEBUG" "" CMAKE_C_FLAGS_${_BUILD_TYPE}
|
||||
"${CMAKE_C_FLAGS_${_BUILD_TYPE}}")
|
||||
string(REGEX REPLACE ".DNDEBUG" "" CMAKE_CXX_FLAGS_${_BUILD_TYPE}
|
||||
"${CMAKE_CXX_FLAGS_${_BUILD_TYPE}}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${ROCPROFILER_BUILD_TYPES}")
|
||||
endif()
|
||||
|
||||
rocprofiler_add_cache_option(ROCPROFILER_MEMCHECK "" STRING "Memory checker type"
|
||||
ADVANCED)
|
||||
|
||||
# ASAN is defined by testing team on Jenkins
|
||||
if(ASAN)
|
||||
set(ROCPROFILER_MEMCHECK
|
||||
"AddressSanitizer"
|
||||
CACHE STRING "Memory checker type (forced by ASAN defined)" FORCE)
|
||||
endif()
|
||||
|
||||
include(rocprofiler_memcheck)
|
||||
@@ -0,0 +1,928 @@
|
||||
# include guard
|
||||
include_guard(GLOBAL)
|
||||
|
||||
# MacroUtilities - useful macros and functions for generic tasks
|
||||
#
|
||||
|
||||
cmake_policy(PUSH)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
cmake_policy(SET CMP0057 NEW)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# message which handles ROCPROFILER_QUIET_CONFIG settings
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
function(ROCPROFILER_MESSAGE TYPE)
|
||||
if(NOT ROCPROFILER_QUIET_CONFIG)
|
||||
message(${TYPE} "[rocprofiler] ${ARGN}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Save a set of variables with the given prefix
|
||||
# -----------------------------------------------------------------------
|
||||
macro(ROCPROFILER_SAVE_VARIABLES _PREFIX)
|
||||
# parse args
|
||||
cmake_parse_arguments(
|
||||
SAVE
|
||||
"" # options
|
||||
"CONDITION" # single value args
|
||||
"VARIABLES" # multiple value args
|
||||
${ARGN})
|
||||
if(DEFINED SAVE_CONDITION AND NOT "${SAVE_CONDITION}" STREQUAL "")
|
||||
if(${SAVE_CONDITION})
|
||||
foreach(_VAR ${SAVE_VARIABLES})
|
||||
if(DEFINED ${_VAR})
|
||||
set(${_PREFIX}_${_VAR} "${${_VAR}}")
|
||||
else()
|
||||
message(AUTHOR_WARNING "${_VAR} is not defined")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
else()
|
||||
foreach(_VAR ${SAVE_VARIABLES})
|
||||
if(DEFINED ${_VAR})
|
||||
set(${_PREFIX}_${_VAR} "${${_VAR}}")
|
||||
else()
|
||||
message(AUTHOR_WARNING "${_VAR} is not defined")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
unset(SAVE_CONDITION)
|
||||
unset(SAVE_VARIABLES)
|
||||
endmacro()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Restore a set of variables with the given prefix
|
||||
# -----------------------------------------------------------------------
|
||||
macro(ROCPROFILER_RESTORE_VARIABLES _PREFIX)
|
||||
# parse args
|
||||
cmake_parse_arguments(
|
||||
RESTORE
|
||||
"" # options
|
||||
"CONDITION" # single value args
|
||||
"VARIABLES" # multiple value args
|
||||
${ARGN})
|
||||
if(DEFINED RESTORE_CONDITION AND NOT "${RESTORE_CONDITION}" STREQUAL "")
|
||||
if(${RESTORE_CONDITION})
|
||||
foreach(_VAR ${RESTORE_VARIABLES})
|
||||
if(DEFINED ${_PREFIX}_${_VAR})
|
||||
set(${_VAR} ${${_PREFIX}_${_VAR}})
|
||||
unset(${_PREFIX}_${_VAR})
|
||||
else()
|
||||
message(AUTHOR_WARNING "${_PREFIX}_${_VAR} is not defined")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
else()
|
||||
foreach(_VAR ${RESTORE_VARIABLES})
|
||||
if(DEFINED ${_PREFIX}_${_VAR})
|
||||
set(${_VAR} ${${_PREFIX}_${_VAR}})
|
||||
unset(${_PREFIX}_${_VAR})
|
||||
else()
|
||||
message(AUTHOR_WARNING "${_PREFIX}_${_VAR} is not defined")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
unset(RESTORE_CONDITION)
|
||||
unset(RESTORE_VARIABLES)
|
||||
endmacro()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# function - rocprofiler_capitalize - make a string capitalized (first letter is capital)
|
||||
# usage: capitalize("SHARED" CShared) message(STATUS "-- CShared is \"${CShared}\"") $ --
|
||||
# CShared is "Shared"
|
||||
function(ROCPROFILER_CAPITALIZE str var)
|
||||
# make string lower
|
||||
string(TOLOWER "${str}" str)
|
||||
string(SUBSTRING "${str}" 0 1 _first)
|
||||
string(TOUPPER "${_first}" _first)
|
||||
string(SUBSTRING "${str}" 1 -1 _remainder)
|
||||
string(CONCAT str "${_first}" "${_remainder}")
|
||||
set(${var}
|
||||
"${str}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
# function rocprofiler_strip_target(<TARGET> [FORCE] [EXPLICIT])
|
||||
#
|
||||
# Creates a post-build command which strips a binary. FORCE flag will override
|
||||
#
|
||||
function(ROCPROFILER_STRIP_TARGET)
|
||||
cmake_parse_arguments(STRIP "FORCE;EXPLICIT" "" "ARGS" ${ARGN})
|
||||
|
||||
list(LENGTH STRIP_UNPARSED_ARGUMENTS NUM_UNPARSED)
|
||||
|
||||
if(NUM_UNPARSED EQUAL 1)
|
||||
set(_TARGET "${STRIP_UNPARSED_ARGUMENTS}")
|
||||
else()
|
||||
rocprofiler_message(
|
||||
FATAL_ERROR "rocprofiler_strip_target cannot deduce target from \"${ARGN}\"")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET "${_TARGET}")
|
||||
rocprofiler_message(
|
||||
FATAL_ERROR
|
||||
"rocprofiler_strip_target not provided valid target: \"${_TARGET}\"")
|
||||
endif()
|
||||
|
||||
if(CMAKE_STRIP AND (STRIP_FORCE OR ROCPROFILER_STRIP_LIBRARIES))
|
||||
if(STRIP_EXPLICIT)
|
||||
add_custom_command(
|
||||
TARGET ${_TARGET}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_STRIP} ${STRIP_ARGS} $<TARGET_FILE:${_TARGET}>
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Stripping ${_TARGET}...")
|
||||
else()
|
||||
add_custom_command(
|
||||
TARGET ${_TARGET}
|
||||
POST_BUILD
|
||||
COMMAND
|
||||
${CMAKE_STRIP} -w --keep-symbol="rocprofiler_init"
|
||||
--keep-symbol="rocprofiler_finalize"
|
||||
--keep-symbol="rocprofiler_push_trace"
|
||||
--keep-symbol="rocprofiler_pop_trace"
|
||||
--keep-symbol="rocprofiler_push_region"
|
||||
--keep-symbol="rocprofiler_pop_region"
|
||||
--keep-symbol="rocprofiler_set_env"
|
||||
--keep-symbol="rocprofiler_set_mpi"
|
||||
--keep-symbol="rocprofiler_reset_preload"
|
||||
--keep-symbol="rocprofiler_set_instrumented"
|
||||
--keep-symbol="rocprofiler_user_*" --keep-symbol="ompt_start_tool"
|
||||
--keep-symbol="kokkosp_*" --keep-symbol="OnLoad"
|
||||
--keep-symbol="OnUnload" --keep-symbol="OnLoadToolProp"
|
||||
--keep-symbol="OnUnloadTool" --keep-symbol="__libc_start_main"
|
||||
${STRIP_ARGS} $<TARGET_FILE:${_TARGET}>
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Stripping ${_TARGET}...")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
# function add_rocprofiler_test_target()
|
||||
#
|
||||
# Creates a target which runs ctest but depends on all the tests being built.
|
||||
#
|
||||
function(ADD_ROCPROFILER_TEST_TARGET)
|
||||
if(NOT TARGET rocprofiler-test)
|
||||
add_custom_target(
|
||||
rocprofiler-test
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR} --target test
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
COMMENT "Running tests...")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# macro rocprofiler_checkout_git_submodule()
|
||||
#
|
||||
# Run "git submodule update" if a file in a submodule does not exist
|
||||
#
|
||||
# ARGS: RECURSIVE (option) -- add "--recursive" flag RELATIVE_PATH (one value) --
|
||||
# typically the relative path to submodule from PROJECT_SOURCE_DIR WORKING_DIRECTORY (one
|
||||
# value) -- (default: PROJECT_SOURCE_DIR) TEST_FILE (one value) -- file to check for
|
||||
# (default: CMakeLists.txt) ADDITIONAL_CMDS (many value) -- any addition commands to pass
|
||||
#
|
||||
function(ROCPROFILER_CHECKOUT_GIT_SUBMODULE)
|
||||
# parse args
|
||||
cmake_parse_arguments(
|
||||
CHECKOUT "RECURSIVE"
|
||||
"RELATIVE_PATH;WORKING_DIRECTORY;TEST_FILE;REPO_URL;REPO_BRANCH"
|
||||
"ADDITIONAL_CMDS" ${ARGN})
|
||||
|
||||
if(NOT CHECKOUT_WORKING_DIRECTORY)
|
||||
set(CHECKOUT_WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
if(NOT CHECKOUT_TEST_FILE)
|
||||
set(CHECKOUT_TEST_FILE "CMakeLists.txt")
|
||||
endif()
|
||||
|
||||
# default assumption
|
||||
if(NOT CHECKOUT_REPO_BRANCH)
|
||||
set(CHECKOUT_REPO_BRANCH "master")
|
||||
endif()
|
||||
|
||||
find_package(Git)
|
||||
set(_DIR "${CHECKOUT_WORKING_DIRECTORY}/${CHECKOUT_RELATIVE_PATH}")
|
||||
# ensure the (possibly empty) directory exists
|
||||
if(NOT EXISTS "${_DIR}")
|
||||
if(NOT CHECKOUT_REPO_URL)
|
||||
message(FATAL_ERROR "submodule directory does not exist")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# if this file exists --> project has been checked out if not exists --> not been
|
||||
# checked out
|
||||
set(_TEST_FILE "${_DIR}/${CHECKOUT_TEST_FILE}")
|
||||
# assuming a .gitmodules file exists
|
||||
set(_SUBMODULE "${PROJECT_SOURCE_DIR}/.gitmodules")
|
||||
|
||||
set(_TEST_FILE_EXISTS OFF)
|
||||
if(EXISTS "${_TEST_FILE}" AND NOT IS_DIRECTORY "${_TEST_FILE}")
|
||||
set(_TEST_FILE_EXISTS ON)
|
||||
endif()
|
||||
|
||||
if(_TEST_FILE_EXISTS)
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_package(Git REQUIRED)
|
||||
|
||||
set(_SUBMODULE_EXISTS OFF)
|
||||
if(EXISTS "${_SUBMODULE}" AND NOT IS_DIRECTORY "${_SUBMODULE}")
|
||||
set(_SUBMODULE_EXISTS ON)
|
||||
endif()
|
||||
|
||||
set(_HAS_REPO_URL OFF)
|
||||
if(NOT "${CHECKOUT_REPO_URL}" STREQUAL "")
|
||||
set(_HAS_REPO_URL ON)
|
||||
endif()
|
||||
|
||||
# if the module has not been checked out
|
||||
if(NOT _TEST_FILE_EXISTS AND _SUBMODULE_EXISTS)
|
||||
# perform the checkout
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} submodule update --init ${_RECURSE}
|
||||
${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_RELATIVE_PATH}
|
||||
WORKING_DIRECTORY ${CHECKOUT_WORKING_DIRECTORY}
|
||||
RESULT_VARIABLE RET)
|
||||
|
||||
# check the return code
|
||||
if(RET GREATER 0)
|
||||
set(_CMD "${GIT_EXECUTABLE} submodule update --init ${_RECURSE}
|
||||
${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_RELATIVE_PATH}")
|
||||
message(STATUS "function(rocprofiler_checkout_git_submodule) failed.")
|
||||
message(FATAL_ERROR "Command: \"${_CMD}\"")
|
||||
else()
|
||||
set(_TEST_FILE_EXISTS ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT _TEST_FILE_EXISTS AND _HAS_REPO_URL)
|
||||
message(
|
||||
STATUS "Checking out '${CHECKOUT_REPO_URL}' @ '${CHECKOUT_REPO_BRANCH}'...")
|
||||
|
||||
# remove the existing directory
|
||||
if(EXISTS "${_DIR}")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory ${_DIR})
|
||||
endif()
|
||||
|
||||
# perform the checkout
|
||||
execute_process(
|
||||
COMMAND
|
||||
${GIT_EXECUTABLE} clone -b ${CHECKOUT_REPO_BRANCH}
|
||||
${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_REPO_URL} ${CHECKOUT_RELATIVE_PATH}
|
||||
WORKING_DIRECTORY ${CHECKOUT_WORKING_DIRECTORY}
|
||||
RESULT_VARIABLE RET)
|
||||
|
||||
# perform the submodule update
|
||||
if(CHECKOUT_RECURSIVE
|
||||
AND EXISTS "${_DIR}"
|
||||
AND IS_DIRECTORY "${_DIR}")
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} submodule update --init ${_RECURSE}
|
||||
WORKING_DIRECTORY ${_DIR}
|
||||
RESULT_VARIABLE RET)
|
||||
endif()
|
||||
|
||||
# check the return code
|
||||
if(RET GREATER 0)
|
||||
set(_CMD
|
||||
"${GIT_EXECUTABLE} clone -b ${CHECKOUT_REPO_BRANCH}
|
||||
${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_REPO_URL} ${CHECKOUT_RELATIVE_PATH}"
|
||||
)
|
||||
message(STATUS "function(rocprofiler_checkout_git_submodule) failed.")
|
||||
message(FATAL_ERROR "Command: \"${_CMD}\"")
|
||||
else()
|
||||
set(_TEST_FILE_EXISTS ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${_TEST_FILE}" OR NOT _TEST_FILE_EXISTS)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Error checking out submodule: '${CHECKOUT_RELATIVE_PATH}' to '${_DIR}'")
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# try to find a package quietly
|
||||
#
|
||||
function(ROCPROFILER_TEST_FIND_PACKAGE PACKAGE_NAME OUTPUT_VAR)
|
||||
cmake_parse_arguments(PACKAGE "" "" "UNSET" ${ARGN})
|
||||
find_package(${PACKAGE_NAME} QUIET ${PACKAGE_UNPARSED_ARGUMENTS})
|
||||
if(NOT ${PACKAGE_NAME}_FOUND)
|
||||
set(${OUTPUT_VAR}
|
||||
OFF
|
||||
PARENT_SCOPE)
|
||||
else()
|
||||
set(${OUTPUT_VAR}
|
||||
ON
|
||||
PARENT_SCOPE)
|
||||
endif()
|
||||
foreach(_ARG ${PACKAGE_UNSET} FIND_PACKAGE_MESSAGE_DETAILS_${PACKAGE_NAME})
|
||||
unset(${_ARG} CACHE)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# macro to add an interface lib
|
||||
#
|
||||
function(ROCPROFILER_ADD_INTERFACE_LIBRARY _TARGET _DESCRIPT)
|
||||
add_library(${_TARGET} INTERFACE)
|
||||
add_library(${PROJECT_NAME}::${_TARGET} ALIAS ${_TARGET})
|
||||
set(_ARGS "${ARGN}")
|
||||
if(NOT "INTERNAL" IN_LIST _ARGS)
|
||||
install(
|
||||
TARGETS ${_TARGET}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
COMPONENT core
|
||||
EXPORT ${PROJECT_NAME}-library-targets
|
||||
OPTIONAL)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# function add_feature(<NAME> <DOCSTRING>) Add a project feature, whose activation is
|
||||
# specified by the existence of the variable <NAME>, to the list of enabled/disabled
|
||||
# features, plus a docstring describing the feature
|
||||
#
|
||||
function(ROCPROFILER_ADD_FEATURE _var _description)
|
||||
set(EXTRA_DESC "")
|
||||
foreach(currentArg ${ARGN})
|
||||
if(NOT "${currentArg}" STREQUAL "${_var}"
|
||||
AND NOT "${currentArg}" STREQUAL "${_description}"
|
||||
AND NOT "${currentArg}" STREQUAL "CMAKE_DEFINE"
|
||||
AND NOT "${currentArg}" STREQUAL "DOC")
|
||||
set(EXTRA_DESC "${EXTA_DESC}${currentArg}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_FEATURES ${_var})
|
||||
set_property(GLOBAL PROPERTY ${_var}_DESCRIPTION "${_description}${EXTRA_DESC}")
|
||||
|
||||
if("CMAKE_DEFINE" IN_LIST ARGN)
|
||||
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES
|
||||
"${_var} @${_var}@")
|
||||
if(ROCPROFILER_BUILD_DOCS)
|
||||
set_property(
|
||||
GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC
|
||||
"${_var}` | ${_description}${EXTRA_DESC} |")
|
||||
endif()
|
||||
elseif("DOC" IN_LIST ARGN AND ROCPROFILER_BUILD_DOCS)
|
||||
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC
|
||||
"${_var}` | ${_description}${EXTRA_DESC} |")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# function add_option(<OPTION_NAME> <DOCSRING> <DEFAULT_SETTING> [NO_FEATURE]) Add an
|
||||
# option and add as a feature if NO_FEATURE is not provided
|
||||
#
|
||||
function(ROCPROFILER_ADD_OPTION _NAME _MESSAGE _DEFAULT)
|
||||
option(${_NAME} "${_MESSAGE}" ${_DEFAULT})
|
||||
if("NO_FEATURE" IN_LIST ARGN)
|
||||
mark_as_advanced(${_NAME})
|
||||
else()
|
||||
rocprofiler_add_feature(${_NAME} "${_MESSAGE}")
|
||||
if(ROCPROFILER_BUILD_DOCS)
|
||||
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC
|
||||
"${_NAME}` | ${_MESSAGE} |")
|
||||
endif()
|
||||
endif()
|
||||
if("ADVANCED" IN_LIST ARGN)
|
||||
mark_as_advanced(${_NAME})
|
||||
endif()
|
||||
if("CMAKE_DEFINE" IN_LIST ARGN)
|
||||
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES ${_NAME})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# function rocprofiler_add_cache_option(<OPTION_NAME> <DOCSRING> <TYPE> <DEFAULT_VALUE>
|
||||
# [NO_FEATURE] [ADVANCED] [CMAKE_DEFINE])
|
||||
#
|
||||
function(ROCPROFILER_ADD_CACHE_OPTION _NAME _DEFAULT _TYPE _MESSAGE)
|
||||
set(_FORCE)
|
||||
if("FORCE" IN_LIST ARGN)
|
||||
set(_FORCE FORCE)
|
||||
endif()
|
||||
|
||||
set(${_NAME}
|
||||
"${_DEFAULT}"
|
||||
CACHE ${_TYPE} "${_MESSAGE}" ${_FORCE})
|
||||
|
||||
if("NO_FEATURE" IN_LIST ARGN)
|
||||
mark_as_advanced(${_NAME})
|
||||
else()
|
||||
rocprofiler_add_feature(${_NAME} "${_MESSAGE}")
|
||||
|
||||
if(ROCPROFILER_BUILD_DOCS)
|
||||
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC
|
||||
"${_NAME}` | ${_MESSAGE} |")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if("ADVANCED" IN_LIST ARGN)
|
||||
mark_as_advanced(${_NAME})
|
||||
endif()
|
||||
|
||||
if("CMAKE_DEFINE" IN_LIST ARGN)
|
||||
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES ${_NAME})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# function rocprofiler_report_feature_changes() :: print changes in features
|
||||
#
|
||||
function(ROCPROFILER_REPORT_FEATURE_CHANGES)
|
||||
get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES)
|
||||
if(NOT "${_features}" STREQUAL "")
|
||||
list(REMOVE_DUPLICATES _features)
|
||||
list(SORT _features)
|
||||
endif()
|
||||
foreach(_feature ${_features})
|
||||
if("${ARGN}" STREQUAL "")
|
||||
rocprofiler_watch_for_change(${_feature})
|
||||
elseif("${_feature}" IN_LIST ARGN)
|
||||
rocprofiler_watch_for_change(${_feature})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# function print_enabled_features() Print enabled features plus their docstrings.
|
||||
#
|
||||
function(ROCPROFILER_PRINT_ENABLED_FEATURES)
|
||||
set(_basemsg "The following features are defined/enabled (+):")
|
||||
set(_currentFeatureText "${_basemsg}")
|
||||
get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES)
|
||||
if(NOT "${_features}" STREQUAL "")
|
||||
list(REMOVE_DUPLICATES _features)
|
||||
list(SORT _features)
|
||||
endif()
|
||||
foreach(_feature ${_features})
|
||||
if(${_feature})
|
||||
# add feature to text
|
||||
set(_currentFeatureText "${_currentFeatureText}\n ${_feature}")
|
||||
# get description
|
||||
get_property(_desc GLOBAL PROPERTY ${_feature}_DESCRIPTION)
|
||||
# print description, if not standard ON/OFF, print what is set to
|
||||
if(_desc)
|
||||
if(NOT "${${_feature}}" STREQUAL "ON" AND NOT "${${_feature}}" STREQUAL
|
||||
"TRUE")
|
||||
set(_currentFeatureText
|
||||
"${_currentFeatureText}: ${_desc} -- [\"${${_feature}}\"]")
|
||||
else()
|
||||
string(REGEX REPLACE "^${PROJECT_NAME}_USE_" "" _feature_tmp
|
||||
"${_feature}")
|
||||
string(TOLOWER "${_feature_tmp}" _feature_tmp_l)
|
||||
rocprofiler_capitalize("${_feature_tmp}" _feature_tmp_c)
|
||||
foreach(_var _feature _feature_tmp _feature_tmp_l _feature_tmp_c)
|
||||
set(_ver "${${${_var}}_VERSION}")
|
||||
if(NOT "${_ver}" STREQUAL "")
|
||||
set(_desc "${_desc} -- [found version ${_ver}]")
|
||||
break()
|
||||
endif()
|
||||
unset(_ver)
|
||||
endforeach()
|
||||
set(_currentFeatureText "${_currentFeatureText}: ${_desc}")
|
||||
endif()
|
||||
set(_desc NOTFOUND)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT "${_currentFeatureText}" STREQUAL "${_basemsg}")
|
||||
message(STATUS "${_currentFeatureText}\n")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# function print_disabled_features() Print disabled features plus their docstrings.
|
||||
#
|
||||
function(ROCPROFILER_PRINT_DISABLED_FEATURES)
|
||||
set(_basemsg "The following features are NOT defined/enabled (-):")
|
||||
set(_currentFeatureText "${_basemsg}")
|
||||
get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES)
|
||||
if(NOT "${_features}" STREQUAL "")
|
||||
list(REMOVE_DUPLICATES _features)
|
||||
list(SORT _features)
|
||||
endif()
|
||||
foreach(_feature ${_features})
|
||||
if(NOT ${_feature})
|
||||
set(_currentFeatureText "${_currentFeatureText}\n ${_feature}")
|
||||
|
||||
get_property(_desc GLOBAL PROPERTY ${_feature}_DESCRIPTION)
|
||||
|
||||
if(_desc)
|
||||
set(_currentFeatureText "${_currentFeatureText}: ${_desc}")
|
||||
set(_desc NOTFOUND)
|
||||
endif(_desc)
|
||||
endif()
|
||||
endforeach(_feature)
|
||||
|
||||
if(NOT "${_currentFeatureText}" STREQUAL "${_basemsg}")
|
||||
message(STATUS "${_currentFeatureText}\n")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# function print_features() Print all features plus their docstrings.
|
||||
#
|
||||
function(ROCPROFILER_PRINT_FEATURES)
|
||||
rocprofiler_report_feature_changes()
|
||||
rocprofiler_print_enabled_features()
|
||||
rocprofiler_print_disabled_features()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
# this function is provided to easily select which files use alternative compiler:
|
||||
#
|
||||
# GLOBAL --> all files TARGET --> all files in a target SOURCE --> specific
|
||||
# source files DIRECTORY --> all files in directory PROJECT --> all files/targets in
|
||||
# a project/subproject
|
||||
#
|
||||
function(rocprofiler_custom_compilation)
|
||||
cmake_parse_arguments(COMP "GLOBAL;PROJECT" "COMPILER" "DIRECTORY;TARGET;SOURCE"
|
||||
${ARGN})
|
||||
|
||||
# find rocprofiler-launch-compiler
|
||||
find_program(
|
||||
ROCPROFILER_COMPILE_LAUNCHER
|
||||
NAMES rocprofiler-launch-compiler
|
||||
HINTS ${PROJECT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}
|
||||
PATHS ${PROJECT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}
|
||||
PATH_SUFFIXES scripts bin)
|
||||
|
||||
if(NOT COMP_COMPILER)
|
||||
message(
|
||||
FATAL_ERROR "rocprofiler_custom_compilation not provided COMPILER argument")
|
||||
endif()
|
||||
|
||||
if(NOT ROCPROFILER_COMPILE_LAUNCHER)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"rocprofiler could not find 'rocprofiler-launch-compiler'. Please set '-DROCPROFILER_COMPILE_LAUNCHER=/path/to/launcher'"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(COMP_GLOBAL)
|
||||
# if global, don't bother setting others
|
||||
set_property(
|
||||
GLOBAL
|
||||
PROPERTY
|
||||
RULE_LAUNCH_COMPILE
|
||||
"${ROCPROFILER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}")
|
||||
set_property(
|
||||
GLOBAL
|
||||
PROPERTY
|
||||
RULE_LAUNCH_LINK
|
||||
"${ROCPROFILER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}")
|
||||
else()
|
||||
foreach(_TYPE PROJECT DIRECTORY TARGET SOURCE)
|
||||
# make project/subproject scoping easy, e.g.
|
||||
# rocprofiler_custom_compilation(PROJECT) after project(...)
|
||||
if("${_TYPE}" STREQUAL "PROJECT" AND COMP_${_TYPE})
|
||||
list(APPEND COMP_DIRECTORY ${PROJECT_SOURCE_DIR})
|
||||
unset(COMP_${_TYPE})
|
||||
endif()
|
||||
# set the properties if defined
|
||||
if(COMP_${_TYPE})
|
||||
foreach(_VAL ${COMP_${_TYPE}})
|
||||
set_property(
|
||||
${_TYPE} ${_VAL}
|
||||
PROPERTY
|
||||
RULE_LAUNCH_COMPILE
|
||||
"${ROCPROFILER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}"
|
||||
)
|
||||
set_property(
|
||||
${_TYPE} ${_VAL}
|
||||
PROPERTY
|
||||
RULE_LAUNCH_LINK
|
||||
"${ROCPROFILER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}"
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(ROCPROFILER_WATCH_FOR_CHANGE _var)
|
||||
list(LENGTH ARGN _NUM_EXTRA_ARGS)
|
||||
if(_NUM_EXTRA_ARGS EQUAL 1)
|
||||
set(_VAR ${ARGN})
|
||||
else()
|
||||
set(_VAR)
|
||||
endif()
|
||||
|
||||
macro(update_var _VAL)
|
||||
if(_VAR)
|
||||
set(${_VAR}
|
||||
${_VAL}
|
||||
PARENT_SCOPE)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
update_var(OFF)
|
||||
|
||||
set(_rocprofiler_watch_var_name ROCPROFILER_WATCH_VALUE_${_var})
|
||||
if(DEFINED ${_rocprofiler_watch_var_name})
|
||||
if("${${_var}}" STREQUAL "${${_rocprofiler_watch_var_name}}")
|
||||
return()
|
||||
else()
|
||||
rocprofiler_message(
|
||||
STATUS
|
||||
"${_var} changed :: ${${_rocprofiler_watch_var_name}} --> ${${_var}}")
|
||||
update_var(ON)
|
||||
endif()
|
||||
else()
|
||||
if(NOT "${${_var}}" STREQUAL "")
|
||||
rocprofiler_message(STATUS "${_var} :: ${${_var}}")
|
||||
update_var(ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# store the value for the next run
|
||||
set(${_rocprofiler_watch_var_name}
|
||||
"${${_var}}"
|
||||
CACHE INTERNAL "Last value of ${_var}" FORCE)
|
||||
endfunction()
|
||||
|
||||
function(ROCPROFILER_DIRECTORY)
|
||||
cmake_parse_arguments(F "MKDIR;FAIL;FORCE" "PREFIX;OUTPUT_VARIABLE;WORKING_DIRECTORY"
|
||||
"PATHS" ${ARGN})
|
||||
|
||||
if(F_PREFIX AND NOT IS_ABSOLUTE "${F_PREFIX}")
|
||||
if(F_WORKING_DIRECTORY)
|
||||
rocprofiler_message(
|
||||
STATUS
|
||||
"PREFIX was specified as a relative path, using working directory + prefix :: '${F_WORKING_DIRECTORY}/${F_PREFIX}'..."
|
||||
)
|
||||
set(F_PREFIX ${F_WORKING_DIRECTORY}/${F_PREFIX})
|
||||
else()
|
||||
rocprofiler_message(
|
||||
FATAL_ERROR
|
||||
"PREFIX was specified but it is not an absolute path: ${F_PREFIX}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT F_WORKING_DIRECTORY)
|
||||
set(F_WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
foreach(_PATH ${F_PREFIX} ${F_PATHS})
|
||||
if(F_PREFIX AND NOT "${_PATH}" STREQUAL "${F_PREFIX}")
|
||||
# if path is relative, set to prefix + path
|
||||
if(NOT IS_ABSOLUTE "${_PATH}")
|
||||
set(_PATH ${F_PREFIX}/${_PATH})
|
||||
endif()
|
||||
list(APPEND _OUTPUT_VAR ${_PATH})
|
||||
elseif(NOT F_PREFIX)
|
||||
list(APPEND _OUTPUT_VAR ${_PATH})
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${_PATH}" AND F_FAIL)
|
||||
rocprofiler_message(FATAL_ERROR "Directory '${_PATH}' does not exist")
|
||||
elseif(NOT IS_DIRECTORY "${_PATH}" AND F_FAIL)
|
||||
rocprofiler_message(FATAL_ERROR "'${_PATH}' exists but is not a directory")
|
||||
elseif(NOT EXISTS "${_PATH}" AND F_MKDIR)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${_PATH}
|
||||
WORKING_DIRECTORY ${F_WORKING_DIRECTORY})
|
||||
elseif(
|
||||
EXISTS "${_PATH}"
|
||||
AND NOT IS_DIRECTORY "${_PATH}"
|
||||
AND F_MKDIR)
|
||||
if(F_FORCE)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E rm ${_PATH}
|
||||
WORKING_DIRECTORY ${F_WORKING_DIRECTORY})
|
||||
endif()
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${_PATH}
|
||||
WORKING_DIRECTORY ${F_WORKING_DIRECTORY})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(F_OUTPUT_VARIABLE)
|
||||
set(${F_OUTPUT_VARIABLE}
|
||||
"${_OUTPUT_VAR}"
|
||||
PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(ROCPROFILER_CHECK_PYTHON_DIRS_AND_VERSIONS)
|
||||
cmake_parse_arguments(F "FAIL;UNSET" "RESULT_VARIABLE;OUTPUT_VARIABLE" "" ${ARGN})
|
||||
|
||||
list(LENGTH ROCPROFILER_PYTHON_VERSIONS _NUM_PYTHON_VERSIONS)
|
||||
list(LENGTH ROCPROFILER_PYTHON_ROOT_DIRS _NUM_PYTHON_ROOT_DIRS)
|
||||
|
||||
if(NOT _NUM_PYTHON_VERSIONS EQUAL _NUM_PYTHON_ROOT_DIRS)
|
||||
set(_RET 1)
|
||||
else()
|
||||
set(_RET 0)
|
||||
if(F_OUTPUT_VARIABLE)
|
||||
set(${F_OUTPUT_VARIABLE}
|
||||
${_NUM_PYTHON_VERSIONS}
|
||||
PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(F_RESULT_VARIABLE)
|
||||
set(${F_RESULT_VARIABLE}
|
||||
${_RET}
|
||||
PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(NOT ${_RET} EQUAL 0)
|
||||
if(F_FAIL)
|
||||
rocprofiler_message(
|
||||
WARNING
|
||||
"Error! Number of python versions : ${_NUM_PYTHON_VERSIONS}. VERSIONS :: ${ROCPROFILER_PYTHON_VERSIONS}"
|
||||
)
|
||||
rocprofiler_message(
|
||||
WARNING
|
||||
"Error! Number of python root directories : ${_NUM_PYTHON_ROOT_DIRS}. ROOT DIRS :: ${ROCPROFILER_PYTHON_ROOT_DIRS}"
|
||||
)
|
||||
rocprofiler_message(
|
||||
FATAL_ERROR
|
||||
"Error! Number of python versions != number of python root directories")
|
||||
elseif(F_UNSET)
|
||||
unset(ROCPROFILER_PYTHON_VERSIONS CACHE)
|
||||
unset(ROCPROFILER_PYTHON_ROOT_DIRS CACHE)
|
||||
if(F_OUTPUT_VARIABLE)
|
||||
set(${F_OUTPUT_VARIABLE} 0)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Console scripts
|
||||
#
|
||||
function(ROCPROFILER_PYTHON_CONSOLE_SCRIPT SCRIPT_NAME SCRIPT_SUBMODULE)
|
||||
set(options)
|
||||
set(args VERSION ROOT_DIR)
|
||||
set(kwargs)
|
||||
cmake_parse_arguments(ARG "${options}" "${args}" "${kwargs}" ${ARGN})
|
||||
|
||||
if(ARG_VERSION AND ARG_ROOT_DIR)
|
||||
set(Python3_ROOT_DIR "${ARG_ROOT_DIR}")
|
||||
find_package(Python3 ${ARG_VERSION} EXACT QUIET MODULE COMPONENTS Interpreter)
|
||||
set(PYTHON_EXECUTABLE "${Python3_EXECUTABLE}")
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/console-script.in
|
||||
${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} @ONLY)
|
||||
|
||||
if(CMAKE_INSTALL_PYTHONDIR)
|
||||
install(
|
||||
PROGRAMS ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION}
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT python
|
||||
OPTIONAL)
|
||||
endif()
|
||||
|
||||
if(ROCPROFILER_BUILD_TESTING OR ROCPROFILER_BUILD_PYTHON)
|
||||
add_test(
|
||||
NAME ${SCRIPT_NAME}-console-script-test-${ARG_VERSION}
|
||||
COMMAND ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} --help
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
set_tests_properties(
|
||||
${SCRIPT_NAME}-console-script-test-${ARG_VERSION}
|
||||
PROPERTIES LABELS "python;python-${ARG_VERSION};console-script")
|
||||
add_test(
|
||||
NAME ${SCRIPT_NAME}-generic-console-script-test-${ARG_VERSION}
|
||||
COMMAND ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} --help
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
set_tests_properties(
|
||||
${SCRIPT_NAME}-generic-console-script-test-${ARG_VERSION}
|
||||
PROPERTIES ENVIRONMENT "PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}" LABELS
|
||||
"python;python-${ARG_VERSION};console-script")
|
||||
endif()
|
||||
else()
|
||||
set(PYTHON_EXECUTABLE "python3")
|
||||
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/console-script.in
|
||||
${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} @ONLY)
|
||||
|
||||
if(CMAKE_INSTALL_PYTHONDIR)
|
||||
install(
|
||||
PROGRAMS ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT python
|
||||
OPTIONAL)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(ROCPROFILER_FIND_STATIC_LIBRARY)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
find_library(${ARGN})
|
||||
endfunction()
|
||||
|
||||
function(ROCPROFILER_FIND_SHARED_LIBRARY)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
find_library(${ARGN})
|
||||
endfunction()
|
||||
|
||||
function(ROCPROFILER_BUILDTREE_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR)
|
||||
get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION)
|
||||
get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION)
|
||||
get_target_property(_TPL_NAME ${_TPL_TARGET} OUTPUT_NAME)
|
||||
set(_TPL_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX})
|
||||
set(_TPL_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
|
||||
foreach(_TAIL ${_TPL_SUFFIX} ${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
${_TPL_SUFFIX}.${_TPL_VERSION})
|
||||
set(_INP ${_TPL_PREFIX}${_TPL_NAME}${_TAIL})
|
||||
set(_OUT ${_TPL_PREFIX}${_NEW_NAME}${_TAIL})
|
||||
endforeach()
|
||||
|
||||
string(REPLACE " " "-" _TAIL "${ARGN}")
|
||||
|
||||
# build tree symbolic links
|
||||
add_custom_target(
|
||||
${_NEW_NAME}-build-tree-library${_TAIL} ALL
|
||||
${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:${_TPL_TARGET}>
|
||||
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E create_symlink
|
||||
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}
|
||||
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E create_symlink
|
||||
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}
|
||||
WORKING_DIRECTORY ${_BUILD_TREE_DIR}
|
||||
DEPENDS ${_TPL_TARGET}
|
||||
COMMENT "Creating ${_NEW_NAME} from ${_TPL_TARGET}...")
|
||||
endfunction()
|
||||
|
||||
function(ROCPROFILER_INSTALL_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR _COMPONENT)
|
||||
get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION)
|
||||
get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION)
|
||||
get_target_property(_TPL_NAME ${_TPL_TARGET} OUTPUT_NAME)
|
||||
set(_TPL_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX})
|
||||
set(_TPL_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
|
||||
foreach(_TAIL ${_TPL_SUFFIX} ${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
${_TPL_SUFFIX}.${_TPL_VERSION})
|
||||
set(_INP ${_TPL_PREFIX}${_TPL_NAME}${_TAIL})
|
||||
set(_OUT ${_TPL_PREFIX}${_NEW_NAME}${_TAIL})
|
||||
endforeach()
|
||||
|
||||
# build tree symbolic links
|
||||
rocprofiler_buildtree_tpl("${_TPL_TARGET}" "${_NEW_NAME}" "${_BUILD_TREE_DIR}"
|
||||
${ARGN})
|
||||
|
||||
install(
|
||||
FILES $<TARGET_FILE:${_TPL_TARGET}>
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
COMPONENT ${_COMPONENT}
|
||||
RENAME ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION})
|
||||
|
||||
install(
|
||||
FILES
|
||||
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
COMPONENT ${_COMPONENT})
|
||||
|
||||
endfunction()
|
||||
|
||||
function(COMPUTE_POW2_CEIL _OUTPUT _VALUE)
|
||||
find_package(Python3 COMPONENTS Interpreter)
|
||||
|
||||
if(Python3_FOUND)
|
||||
execute_process(
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE} -c
|
||||
"VALUE = ${_VALUE}; ispow2 = lambda x: x if (x and (not(x & (x - 1)))) else None; v = list(filter(ispow2, [x for x in range(VALUE, VALUE**2)])); print(v[0])"
|
||||
RESULT_VARIABLE _POW2_RET
|
||||
OUTPUT_VARIABLE _POW2_OUT
|
||||
ERROR_VARIABLE _POW2_ERR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
if(_POW2_RET EQUAL 0)
|
||||
set(${_OUTPUT}
|
||||
${_POW2_OUT}
|
||||
PARENT_SCOPE)
|
||||
else()
|
||||
set(${_OUTPUT}
|
||||
"-1"
|
||||
PARENT_SCOPE)
|
||||
endif()
|
||||
else()
|
||||
set(${_OUTPUT}
|
||||
"-1"
|
||||
PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
|
||||
cmake_policy(POP)
|
||||
فروخته شده
+29
@@ -0,0 +1,29 @@
|
||||
#
|
||||
#
|
||||
# External dependencies
|
||||
#
|
||||
#
|
||||
|
||||
if(ROCPROFILER_BUILD_TESTS)
|
||||
set(INSTALL_GTEST
|
||||
OFF
|
||||
CACHE BOOL "")
|
||||
set(BUILD_GMOCK
|
||||
OFF
|
||||
CACHE BOOL "")
|
||||
|
||||
add_subdirectory(googletest EXCLUDE_FROM_ALL)
|
||||
|
||||
if(NOT TARGET GTest::gtest)
|
||||
message(FATAL_ERROR "missing GTest::gtest")
|
||||
endif()
|
||||
|
||||
target_link_libraries(rocprofiler-googletest INTERFACE GTest::gtest)
|
||||
target_include_directories(
|
||||
rocprofiler-googletest SYSTEM
|
||||
INTERFACE ${CMAKE_CURRENT_LSIT_DIR}/googletest/googletest/include)
|
||||
|
||||
mark_as_advanced(INSTALL_GTEST)
|
||||
mark_as_advanced(BUILD_GMOCK)
|
||||
mark_as_advanced(GTEST_HAS_ABSL)
|
||||
endif()
|
||||
+1
Submodule external/googletest added at 46db91ef6f
@@ -0,0 +1,25 @@
|
||||
|
||||
[tool.black]
|
||||
line-length = 90
|
||||
target-version = ['py36', 'py37', 'py38', 'py39', 'py310']
|
||||
include = '\.py$'
|
||||
exclude = '''
|
||||
(
|
||||
/(
|
||||
\.eggs
|
||||
| \.git
|
||||
| \.github
|
||||
| \.tox
|
||||
| \.venv
|
||||
| \.misc
|
||||
| \.vscode
|
||||
| \.cache
|
||||
| \.pytest_cache
|
||||
| dist
|
||||
| external
|
||||
| build
|
||||
| build-release
|
||||
| build-rocprofiler
|
||||
)/
|
||||
)
|
||||
'''
|
||||
@@ -0,0 +1,10 @@
|
||||
barectf
|
||||
bcrypt
|
||||
CppHeaderParser
|
||||
lxml
|
||||
matplotlib
|
||||
pandas
|
||||
protobuf
|
||||
pycparser
|
||||
pyparsing
|
||||
websockets
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(bin)
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
add_subdirectory(rocprofiler)
|
||||
@@ -0,0 +1,8 @@
|
||||
#
|
||||
#
|
||||
# Installation of public headers
|
||||
#
|
||||
#
|
||||
set(ROCPROFILER_INCLUDE_FILES config.h rocprofiler.h rocprofiler_plugin.h)
|
||||
install(FILES ${ROCPROFILER_INCLUDE_FILES}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocprofiler)
|
||||
@@ -0,0 +1,189 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <rocprofiler/rocprofiler.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ROCPROFILER_API_VERSION_ID 1
|
||||
#define ROCPROFILER_DOMAIN_OPS_MAX 512
|
||||
#define ROCPROFILER_DOMAIN_OPS_RESERVED ((ROCPROFILER_DOMAIN_OPS_MAX * ACTIVITY_DOMAIN_NUMBER / 8))
|
||||
|
||||
typedef uint64_t (*rocprofiler_external_cid_cb_t)(rocprofiler_tracer_activity_domain_t,
|
||||
uint32_t,
|
||||
uint64_t);
|
||||
typedef int (*rocprofiler_filter_name_t)(const char*);
|
||||
typedef int (*rocprofiler_filter_op_id_t)(uint32_t);
|
||||
typedef int (*rocprofiler_filter_range_t)(uint32_t, uint32_t);
|
||||
typedef int (*rocprofiler_filter_dispatch_id_t)(uint64_t);
|
||||
|
||||
/// permits tools opportunity to modify the correlation id based on the domain, op, and
|
||||
/// the rocprofiler generated correlation id
|
||||
struct rocprofiler_correlation_config
|
||||
{
|
||||
rocprofiler_external_cid_cb_t external_id_callback;
|
||||
};
|
||||
|
||||
/// how the tools specify the tracing domain and (optionally) which operations in the
|
||||
/// domain they want to trace
|
||||
struct rocprofiler_domain_config
|
||||
{
|
||||
rocprofiler_sync_callback_t callback;
|
||||
char reserved0[sizeof(uint64_t)];
|
||||
char reserved1[ROCPROFILER_DOMAIN_OPS_RESERVED];
|
||||
};
|
||||
|
||||
/// for buffered callbacks, the tool provides a callback to create a buffer and the size
|
||||
struct rocprofiler_buffer_config
|
||||
{
|
||||
rocprofiler_buffer_callback_t callback;
|
||||
uint64_t buffer_size;
|
||||
// void* reserved0;
|
||||
char reserved1[sizeof(uint64_t)];
|
||||
};
|
||||
|
||||
/// filters are available to make quick decisions about whether rocprofiler should
|
||||
/// assemble the data necessary for a callback. This is more for convenience and
|
||||
/// performance -- anything decisions here could be made in the callback but rocprofiler
|
||||
/// has to first assemble all the infomation on the callback before it (eventually) gets
|
||||
/// discarded because the tool has decided it (after configuration), that it no longer
|
||||
/// wants info meeting certain requirements
|
||||
struct rocprofiler_filter_config
|
||||
{
|
||||
// filter callbacks
|
||||
rocprofiler_filter_name_t name;
|
||||
rocprofiler_filter_op_id_t hip_function_id;
|
||||
rocprofiler_filter_op_id_t hsa_function_id;
|
||||
rocprofiler_filter_range_t range;
|
||||
rocprofiler_filter_dispatch_id_t dispatch_id;
|
||||
|
||||
// reserved padding
|
||||
char padding[24 * sizeof(void*)];
|
||||
};
|
||||
|
||||
/// this is the "single source of truth" for the capabilities of rocprofiler.
|
||||
/// you can one configuration that activates all the capabilities you want
|
||||
/// and holistically start/stop the sum of those features. Alternatively,
|
||||
/// you can have multiple configurations in order to activate certain features
|
||||
/// modularly.
|
||||
///
|
||||
/// The general workflow is:
|
||||
///
|
||||
/// 1. invoke rocprofiler_allocate_config(...)
|
||||
/// - rocprofiler allocates any space internally needed for the config
|
||||
/// - rocprofiler sets a few initial values:
|
||||
/// - "size" to the size of the config structure used internally
|
||||
/// - "api_version" to the version id of the API in the rocprofiler library that
|
||||
/// is being used.
|
||||
/// - these two values can be used by the tool to identify any potential
|
||||
/// incompatibilities that the tool might want to know about
|
||||
/// - rocprofiler checks whether it is too late to configure the tool, e.g.
|
||||
/// something went wrong and rocprofiler was not able to set itself up as
|
||||
/// the intercepter
|
||||
/// 2. tool sets up the configuration struct and sets the "size" variable to the size of
|
||||
/// their configuration struct and sets the "compat_version" field to the
|
||||
/// ROCPROFILER_API_VERSION_ID defined by the rocprofiler headers when the tool was
|
||||
/// built
|
||||
/// - in other words, the user can communicate to rocprofiler, don't read
|
||||
/// past this distance in my configuration struct and I built against X version
|
||||
/// so assume the default behavior and capabilties of version X.
|
||||
/// 3. tool passes this struct to rocprofiler_validate_config(...)
|
||||
/// - this step checks the config in isolation and will communicate any potential
|
||||
/// warnings/issues with that configuration, e.g. rocprofiler_X_config is needed,
|
||||
/// to HW counters XYZ are not available, etc. The tool then has an opportunity
|
||||
/// to address these issues however they see fit.
|
||||
/// 4. tool passes this struct to rocprofiler_start_config(...)
|
||||
/// - internally, we make a call to rocprofiler_validate_config(...) and if any
|
||||
/// issues still exist with the config in isolation, rocprofiler tells the app
|
||||
/// to abort -- mechanisms were provided to prevent aborting prior to this call,
|
||||
/// aborting the app at this point is to guard against rocprofiler "silently"
|
||||
/// not working because error codes were ignored
|
||||
/// - rocprofiler then checks whether this config can actually be activated
|
||||
/// alongside any other active configuration, e.g. this config wants 4 HW counters
|
||||
/// and another wants 4 HW counters but we can only activate 6 out of 8 of
|
||||
/// them in this run. Any issues here will not abort execution but, instead,
|
||||
/// the features of this configuration will not happen (i.e. config won't be
|
||||
/// activated) and the issues will be communicated with error codes -- giving
|
||||
/// the tool the opportunity to address the conflicts (i.e. only request tracing
|
||||
/// and no HW counters) before attempting to activate the modified config.
|
||||
/// - once rocprofiler determines all features of a config can be activated, it
|
||||
/// makes an internal copy of the config and returns an identifier for that
|
||||
/// configuration. The tool is then free to delete the config and any modification
|
||||
/// to the config will NOT be reflected in the behavior of rocprofiler.
|
||||
///
|
||||
///
|
||||
struct rocprofiler_config
|
||||
{
|
||||
// size is used to ensure that we never read past the end of the version
|
||||
size_t size; // = sizeof(rocprofiler_config)
|
||||
uint32_t compat_version; // set by user
|
||||
uint32_t api_version; // set by rocprofiler
|
||||
uint64_t reserved0; // internal field
|
||||
void* user_data; // data passed to callbacks
|
||||
struct rocprofiler_correlation_config* correlation_id; // = &my_cid_config (optional)
|
||||
struct rocprofiler_buffer_config* buffer; // = &my_buffer_config (required)
|
||||
struct rocprofiler_domain_config* domain; // = &my_domain_config (required)
|
||||
struct rocprofiler_filter_config* filter; // = &my_filter_config (optional)
|
||||
};
|
||||
|
||||
/// \brief returns a properly initialized config struct and allocates any data structures
|
||||
/// necessary for the config to be used
|
||||
///
|
||||
/// \param [out] cfg may adjust config or assign values within structs.
|
||||
rocprofiler_status_t
|
||||
rocprofiler_allocate_config(struct rocprofiler_config* cfg);
|
||||
|
||||
/// \brief rocprofiler validates config, checks for conflicts, etc. Ensures that
|
||||
/// the configuration is valid *in isolation*, e.g. it may check that the user
|
||||
/// set the compat_version field and that required config fields, such as buffer
|
||||
/// are set. This function will be called before \ref rocprofiler_start_config
|
||||
/// but is provided to help the user validate one or more configs without starting
|
||||
/// them
|
||||
///
|
||||
/// \param [in] cfg configuration to validate
|
||||
rocprofiler_status_t
|
||||
rocprofiler_validate_config(const struct rocprofiler_config* cfg);
|
||||
|
||||
/// \brief rocprofiler activates configuration and provides a session identifier
|
||||
/// \param [in] cfg may adjust config or assign values within structs. If error
|
||||
/// occurs, could nullptr valid sub-configs and leave the pointers to
|
||||
/// invalid configs
|
||||
/// \param [out] id the session identifier for this config.
|
||||
rocprofiler_status_t
|
||||
rocprofiler_start_config(struct rocprofiler_config*, rocprofiler_session_id_t* id);
|
||||
|
||||
/// \brief disable the configuration.
|
||||
rocprofiler_status_t rocprofiler_stop_config(rocprofiler_session_id_t);
|
||||
|
||||
///
|
||||
///
|
||||
/// the following 4 functions may be changed to permit removing domain/ops and/or
|
||||
/// identifying domains and operations via strings
|
||||
///
|
||||
///
|
||||
rocprofiler_status_t
|
||||
rocprofiler_domain_set_domain(struct rocprofiler_domain_config*,
|
||||
rocprofiler_tracer_activity_domain_t);
|
||||
|
||||
rocprofiler_status_t
|
||||
rocprofiler_domain_add_domains(struct rocprofiler_domain_config*,
|
||||
rocprofiler_tracer_activity_domain_t*,
|
||||
size_t);
|
||||
|
||||
rocprofiler_status_t
|
||||
rocprofiler_domain_add_op(struct rocprofiler_domain_config*,
|
||||
rocprofiler_tracer_activity_domain_t,
|
||||
uint32_t);
|
||||
|
||||
rocprofiler_status_t
|
||||
rocprofiler_domain_add_ops(struct rocprofiler_domain_config*,
|
||||
rocprofiler_tracer_activity_domain_t,
|
||||
uint32_t*,
|
||||
size_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -0,0 +1,142 @@
|
||||
/* Copyright (c) 2022 Advanced Micro Devices, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE. */
|
||||
|
||||
/** \section rocprofiler_plugin_api ROCProfiler Plugin API
|
||||
*
|
||||
* The ROCProfiler Plugin API is used by the ROCProfiler Tool to output all
|
||||
* profiling information. Different implementations of the ROCProfiler Plugin
|
||||
* API can be developed that output the data in different formats. The
|
||||
* ROCProfiler Tool can be configured to load a specific library that supports
|
||||
* the user desired format.
|
||||
*
|
||||
* The API is not thread safe. It is the responsibility of the ROCProfiler Tool
|
||||
* to ensure the operations are synchronized and not called concurrently. There
|
||||
* is no requirement for the ROCProfiler Tool to report trace data in any
|
||||
* specific order. If the format supported by plugin requires specific
|
||||
* ordering, it is the responsibility of the plugin implementation to perform
|
||||
* any necessary sorting.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* ROCProfiler Tool Plugin API interface.
|
||||
*/
|
||||
|
||||
#ifndef ROCPROFILER_PLUGIN_H_
|
||||
#define ROCPROFILER_PLUGIN_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "rocprofiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/** \defgroup rocprofiler_plugins ROCProfiler Plugin API Specification
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \defgroup initialization_group Initialization and Finalization
|
||||
* \ingroup rocprofiler_plugins
|
||||
*
|
||||
* The ROCProfiler Plugin API must be initialized before using any of the
|
||||
* operations to report trace data, and finalized after the last trace data has
|
||||
* been reported.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize plugin.
|
||||
* Must be called before any other operation.
|
||||
*
|
||||
* @param[in] rocprofiler_major_version The major version of the ROCProfiler API
|
||||
* being used by the ROCProfiler Tool. An error is reported if this does not
|
||||
* match the major version of the ROCProfiler API used to build the plugin
|
||||
* library. This ensures compatibility of the trace data format.
|
||||
* @param[in] rocprofiler_minor_version The minor version of the ROCProfiler API
|
||||
* being used by the ROCProfiler Tool. An error is reported if the
|
||||
* \p rocprofiler_major_version matches and this is greater than the minor
|
||||
* version of the ROCProfiler API used to build the plugin library. This ensures
|
||||
* compatibility of the trace data format.
|
||||
* @param[in] data Pointer to the data passed to the ROCProfiler Plugin by the tool
|
||||
* @return Returns 0 on success and -1 on error.
|
||||
*/
|
||||
ROCPROFILER_EXPORT int
|
||||
rocprofiler_plugin_initialize(uint32_t rocprofiler_major_version,
|
||||
uint32_t rocprofiler_minor_version,
|
||||
void* data);
|
||||
|
||||
/**
|
||||
* Finalize plugin.
|
||||
* This must be called after ::rocprofiler_plugin_initialize and after all
|
||||
* profiling data has been reported by
|
||||
* ::rocprofiler_plugin_write_kernel_records
|
||||
*/
|
||||
ROCPROFILER_EXPORT void
|
||||
rocprofiler_plugin_finalize();
|
||||
|
||||
/** @} */
|
||||
|
||||
/** \defgroup profiling_record_write_functions Profiling data reporting
|
||||
* \ingroup rocprofiler_plugins
|
||||
* Operations to output profiling data.
|
||||
* @{
|
||||
*/
|
||||
|
||||
// TODO(aelwazir): Recheck wording of the description
|
||||
|
||||
/**
|
||||
* Report Buffer Records.
|
||||
*
|
||||
* @param[in] begin Pointer to the first record.
|
||||
* @param[in] end Pointer to one past the last record.
|
||||
* @param[in] session_id Session ID
|
||||
* @param[in] buffer_id Buffer ID
|
||||
* @return Returns 0 on success and -1 on error.
|
||||
*/
|
||||
ROCPROFILER_EXPORT int
|
||||
rocprofiler_plugin_write_buffer_records(const rocprofiler_record_header_t* begin,
|
||||
const rocprofiler_record_header_t* end,
|
||||
rocprofiler_session_id_t session_id,
|
||||
rocprofiler_buffer_id_t buffer_id);
|
||||
|
||||
/**
|
||||
* Report Synchronous Record.
|
||||
*
|
||||
* @param[in] record Synchronous Tracer record.
|
||||
* @param[in] data : api_data
|
||||
* @param[in] tracer_data :Tracer record extra data such as function name and kernel name
|
||||
* @return Returns 0 on success and -1 on error.
|
||||
*/
|
||||
|
||||
ROCPROFILER_EXPORT int
|
||||
rocprofiler_plugin_write_record(rocprofiler_record_tracer_t record);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ROCPROFILER_PLUGIN_H_ */
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(rocprofiler)
|
||||
add_subdirectory(plugins)
|
||||
|
||||
if(ROCPROFILER_BUILD_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
@@ -0,0 +1,26 @@
|
||||
set(common_sources ${CMAKE_CURRENT_LIST_DIR}/config.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/helper.cpp)
|
||||
|
||||
set(common_headers
|
||||
${CMAKE_CURRENT_LIST_DIR}/config.hpp ${CMAKE_CURRENT_LIST_DIR}/defines.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/environment.hpp ${CMAKE_CURRENT_LIST_DIR}/join.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/log.hpp ${CMAKE_CURRENT_LIST_DIR}/helper.hpp)
|
||||
|
||||
add_library(rocprofiler-common-library STATIC)
|
||||
add_library(rocprofiler::rocprofiler-common-library ALIAS rocprofiler-common-library)
|
||||
|
||||
add_subdirectory(container)
|
||||
|
||||
target_sources(rocprofiler-common-library PRIVATE ${common_sources} ${common_headers})
|
||||
target_include_directories(rocprofiler-common-library
|
||||
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/source>)
|
||||
|
||||
target_link_libraries(
|
||||
rocprofiler-common-library
|
||||
PUBLIC rocprofiler::rocprofiler-amd-comgr
|
||||
$<BUILD_INTERFACE:rocprofiler::rocprofiler-build-flags>
|
||||
$<BUILD_INTERFACE:rocprofiler::rocprofiler-memcheck>
|
||||
$<BUILD_INTERFACE:rocprofiler::rocprofiler-stdcxxfs>
|
||||
$<BUILD_INTERFACE:rocprofiler::rocprofiler-dl>)
|
||||
set_target_properties(rocprofiler-common-library PROPERTIES OUTPUT_NAME
|
||||
rocprofiler-common)
|
||||
@@ -0,0 +1,433 @@
|
||||
// Copyright (c) 2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#include "lib/common/config.hpp"
|
||||
#include "lib/common/environment.hpp"
|
||||
#include "lib/common/join.hpp"
|
||||
#include "lib/common/log.hpp"
|
||||
#include "lib/common/helper.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <regex>
|
||||
#include <filesystem>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::time_t* launch_time = new std::time_t{std::time(nullptr)};
|
||||
|
||||
std::vector<std::string>
|
||||
read_command_line(pid_t _pid)
|
||||
{
|
||||
auto _cmdline = std::vector<std::string>{};
|
||||
auto fcmdline = std::stringstream{};
|
||||
fcmdline << "/proc/" << _pid << "/cmdline";
|
||||
auto ifs = std::ifstream{fcmdline.str().c_str()};
|
||||
if(ifs)
|
||||
{
|
||||
char cstr;
|
||||
std::string sarg;
|
||||
while(!ifs.eof())
|
||||
{
|
||||
ifs >> cstr;
|
||||
if(!ifs.eof())
|
||||
{
|
||||
if(cstr != '\0')
|
||||
{
|
||||
sarg += cstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
_cmdline.push_back(sarg);
|
||||
sarg = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
ifs.close();
|
||||
}
|
||||
|
||||
return _cmdline;
|
||||
}
|
||||
|
||||
std::string
|
||||
get_local_datetime(const char* dt_format, std::time_t* dt_curr)
|
||||
{
|
||||
char mbstr[512];
|
||||
if(!dt_curr) dt_curr = launch_time;
|
||||
|
||||
if(std::strftime(mbstr, sizeof(mbstr), dt_format, std::localtime(dt_curr)) != 0)
|
||||
return std::string{mbstr};
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
inline bool
|
||||
not_is_space(int ch)
|
||||
{
|
||||
return std::isspace(ch) == 0;
|
||||
}
|
||||
|
||||
inline std::string
|
||||
ltrim(std::string s, bool (*f)(int) = not_is_space)
|
||||
{
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), f));
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::string
|
||||
rtrim(std::string s, bool (*f)(int) = not_is_space)
|
||||
{
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end());
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::string
|
||||
trim(std::string s, bool (*f)(int) = not_is_space)
|
||||
{
|
||||
ltrim(s, f);
|
||||
rtrim(s, f);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::vector<pid_t>
|
||||
get_siblings(pid_t _id = getppid())
|
||||
{
|
||||
auto _data = std::vector<pid_t>{};
|
||||
|
||||
std::ifstream _ifs{"/proc/" + std::to_string(_id) + "/task/" + std::to_string(_id) +
|
||||
"/children"};
|
||||
while(_ifs)
|
||||
{
|
||||
pid_t _n = 0;
|
||||
_ifs >> _n;
|
||||
if(!_ifs || _n <= 0) break;
|
||||
_data.emplace_back(_n);
|
||||
}
|
||||
return _data;
|
||||
}
|
||||
|
||||
inline auto
|
||||
get_num_siblings(pid_t _id = getppid())
|
||||
{
|
||||
return get_siblings(_id).size();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int
|
||||
get_mpi_size()
|
||||
{
|
||||
static int _v = get_env<int>("OMPI_COMM_WORLD_SIZE",
|
||||
get_env<int>("MV2_COMM_WORLD_SIZE", get_env<int>("MPI_SIZE", 0)));
|
||||
return _v;
|
||||
}
|
||||
|
||||
int
|
||||
get_mpi_rank()
|
||||
{
|
||||
static int _v = get_env<int>("OMPI_COMM_WORLD_RANK",
|
||||
get_env<int>("MV2_COMM_WORLD_RANK", get_env<int>("MPI_RANK", -1)));
|
||||
return _v;
|
||||
}
|
||||
|
||||
std::vector<output_key>
|
||||
output_keys(std::string _tag)
|
||||
{
|
||||
using strpair_t = std::pair<std::string, std::string>;
|
||||
|
||||
auto _cmdline = read_command_line(getpid());
|
||||
|
||||
if(_tag.empty() && !_cmdline.empty()) _tag = ::basename(_cmdline.front().c_str());
|
||||
|
||||
std::string _argv_string = {}; // entire argv cmd
|
||||
std::string _args_string = {}; // cmdline args
|
||||
std::string _argt_string = _tag; // prefix + cmdline args
|
||||
const std::string& _tag0_string = _tag; // only the basic prefix
|
||||
auto _options = std::vector<output_key>{};
|
||||
|
||||
auto _replace = [](auto& _v, const strpair_t& pitr) {
|
||||
auto pos = std::string::npos;
|
||||
while((pos = _v.find(pitr.first)) != std::string::npos)
|
||||
_v.replace(pos, pitr.first.length(), pitr.second);
|
||||
};
|
||||
|
||||
if(_cmdline.size() > 1 && _cmdline.at(1) == "--") _cmdline.erase(_cmdline.begin() + 1);
|
||||
|
||||
for(auto& itr : _cmdline)
|
||||
{
|
||||
itr = trim(itr);
|
||||
_replace(itr, {"/", "_"});
|
||||
while(!itr.empty() && itr.at(0) == '.')
|
||||
itr = itr.substr(1);
|
||||
while(!itr.empty() && itr.at(0) == '_')
|
||||
itr = itr.substr(1);
|
||||
}
|
||||
|
||||
if(!_cmdline.empty())
|
||||
{
|
||||
for(size_t i = 0; i < _cmdline.size(); ++i)
|
||||
{
|
||||
const auto _l = std::string{(i == 0) ? "" : "_"};
|
||||
auto _v = _cmdline.at(i);
|
||||
_argv_string += _l + _v;
|
||||
if(i > 0)
|
||||
{
|
||||
_argt_string += (i > 1) ? (_l + _v) : _v;
|
||||
_args_string += (i > 1) ? (_l + _v) : _v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto* _launch_time = launch_time;
|
||||
auto _time_format = get_env<std::string>("ROCP_TIME_FORMAT", "%F_%H.%M");
|
||||
|
||||
auto _mpi_size = get_env<int>("OMPI_COMM_WORLD_SIZE", get_env<int>("MV2_COMM_WORLD_SIZE", 0));
|
||||
auto _mpi_rank = get_env<int>("OMPI_COMM_WORLD_RANK", get_env<int>("MV2_COMM_WORLD_RANK", -1));
|
||||
|
||||
auto _dmp_size = join("", (_mpi_size) > 0 ? _mpi_size : 1);
|
||||
auto _dmp_rank = join("", (_mpi_rank) > 0 ? _mpi_rank : 0);
|
||||
auto _proc_id = join("", getpid());
|
||||
auto _parent_id = join("", getppid());
|
||||
auto _pgroup_id = join("", getpgid(getpid()));
|
||||
auto _session_id = join("", getsid(getpid()));
|
||||
auto _proc_size = join("", get_num_siblings());
|
||||
auto _pwd_string = get_env<std::string>("PWD", ".");
|
||||
auto _slurm_job_id = get_env<std::string>("SLURM_JOB_ID", "0");
|
||||
auto _slurm_proc_id = get_env("SLURM_PROCID", _dmp_rank);
|
||||
auto _launch_string = get_local_datetime(_time_format.c_str(), _launch_time);
|
||||
|
||||
auto _uniq_id = _proc_id;
|
||||
if(get_env<int32_t>("SLURM_PROCID", -1) >= 0)
|
||||
{
|
||||
_uniq_id = _slurm_proc_id;
|
||||
}
|
||||
else if(_mpi_size > 0 || _mpi_rank >= 0)
|
||||
{
|
||||
_uniq_id = _dmp_rank;
|
||||
}
|
||||
|
||||
for(auto&& itr : std::initializer_list<output_key>{
|
||||
{"%argv%", _argv_string, "Entire command-line condensed into a single string"},
|
||||
{"%argt%",
|
||||
_argt_string,
|
||||
"Similar to `%argv%` except basename of first command line argument"},
|
||||
{"%args%", _args_string, "All command line arguments condensed into a single string"},
|
||||
{"%tag%", _tag0_string, "Basename of first command line argument"}})
|
||||
{
|
||||
_options.emplace_back(itr);
|
||||
}
|
||||
|
||||
if(!_cmdline.empty())
|
||||
{
|
||||
for(size_t i = 0; i < _cmdline.size(); ++i)
|
||||
{
|
||||
auto _v = _cmdline.at(i);
|
||||
_options.emplace_back(join("", "%arg", i, "%"), _v, join("", "Argument #", i));
|
||||
}
|
||||
}
|
||||
|
||||
for(auto&& itr : std::initializer_list<output_key>{
|
||||
{"%pid%", _proc_id, "Process identifier"},
|
||||
{"%ppid%", _parent_id, "Parent process identifier"},
|
||||
{"%pgid%", _pgroup_id, "Process group identifier"},
|
||||
{"%psid%", _session_id, "Process session identifier"},
|
||||
{"%psize%", _proc_size, "Number of sibling process"},
|
||||
{"%job%", _slurm_job_id, "SLURM_JOB_ID env variable"},
|
||||
{"%rank%", _slurm_proc_id, "MPI/UPC++ rank"},
|
||||
{"%size%", _dmp_size, "MPI/UPC++ size"},
|
||||
{"%nid%", _uniq_id, "%rank% if possible, otherwise %pid%"},
|
||||
{"%launch_time%", _launch_string, "Data and/or time of run according to time format"},
|
||||
})
|
||||
{
|
||||
_options.emplace_back(itr);
|
||||
}
|
||||
|
||||
for(auto&& itr : std::initializer_list<output_key>{
|
||||
{"%p", _proc_id, "Shorthand for %pid%"},
|
||||
{"%j", _slurm_job_id, "Shorthand for %job%"},
|
||||
{"%r", _slurm_proc_id, "Shorthand for %rank%"},
|
||||
{"%s", _dmp_size, "Shorthand for %size"},
|
||||
})
|
||||
{
|
||||
_options.emplace_back(itr);
|
||||
}
|
||||
|
||||
return _options;
|
||||
}
|
||||
|
||||
std::string
|
||||
format(std::string _fpath, const std::string& _tag)
|
||||
{
|
||||
if(_fpath.find('%') == std::string::npos && _fpath.find('$') == std::string::npos)
|
||||
return _fpath;
|
||||
|
||||
auto _replace = [](auto& _v, const output_key& pitr) {
|
||||
auto pos = std::string::npos;
|
||||
while((pos = _v.find(pitr.key)) != std::string::npos)
|
||||
_v.replace(pos, pitr.key.length(), pitr.value);
|
||||
};
|
||||
|
||||
for(auto&& itr : output_keys(_tag))
|
||||
_replace(_fpath, itr);
|
||||
|
||||
// environment and configuration variables
|
||||
try
|
||||
{
|
||||
for(const auto& _expr : {std::string{"(.*)%(env|ENV)\\{([A-Z0-9_]+)\\}%(.*)"},
|
||||
std::string{"(.*)\\$(env|ENV)\\{([A-Z0-9_]+)\\}(.*)"}})
|
||||
{
|
||||
std::regex _re{_expr};
|
||||
std::string _cbeg = (_expr.find("(.*)%") == 0) ? "%" : "$";
|
||||
std::string _cend = (_expr.find("(.*)%") == 0) ? "}%" : "}";
|
||||
bool _is_env = (_expr.find("(env|ENV)") != std::string::npos);
|
||||
_cbeg += (_is_env) ? "env{" : "cfg{";
|
||||
while(std::regex_search(_fpath, _re))
|
||||
{
|
||||
auto _var = std::regex_replace(_fpath, _re, "$3");
|
||||
std::string _val = {};
|
||||
if(_is_env)
|
||||
{
|
||||
_val = get_env<std::string>(_var, "");
|
||||
}
|
||||
auto _beg = std::regex_replace(_fpath, _re, "$1");
|
||||
auto _end = std::regex_replace(_fpath, _re, "$4");
|
||||
_fpath = join("", _beg, _val, _end);
|
||||
}
|
||||
}
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s[rocprofiler][%s:%i] %s threw exception :: %s\n%s",
|
||||
log::color::dmesg(),
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
__FUNCTION__,
|
||||
_e.what(),
|
||||
log::color::end());
|
||||
}
|
||||
|
||||
// remove %arg<N>% where N >= argc
|
||||
try
|
||||
{
|
||||
std::regex _re{"(.*)%(arg[0-9]+)%([-/_]*)(.*)"};
|
||||
while(std::regex_search(_fpath, _re))
|
||||
_fpath = std::regex_replace(_fpath, _re, "$1$4");
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s[rocprofiler][%s:%i] %s threw exception :: %s\n%s",
|
||||
log::color::dmesg(),
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
__FUNCTION__,
|
||||
_e.what(),
|
||||
log::color::end());
|
||||
}
|
||||
|
||||
return _fpath;
|
||||
}
|
||||
|
||||
std::string
|
||||
compose_filename(const config& _cfg)
|
||||
{
|
||||
auto _output_path = _cfg.output_path;
|
||||
auto _output_file = _cfg.output_file;
|
||||
auto _output_ext = _cfg.output_ext;
|
||||
|
||||
if(_output_path.empty()) _output_path = ".";
|
||||
if(_cfg.mpi_size > 0)
|
||||
{
|
||||
if(_cfg.mpi_rank >= 0)
|
||||
{
|
||||
_output_file = join('.', _output_file, _cfg.mpi_rank);
|
||||
}
|
||||
else
|
||||
{
|
||||
_output_file = join('.', _output_file, getpid());
|
||||
}
|
||||
}
|
||||
if(!_output_ext.empty())
|
||||
{
|
||||
if(_output_ext.find('.') == std::string::npos) _output_ext.insert(0, ".");
|
||||
if(_output_file.length() < _output_ext.length() ||
|
||||
_output_file.find(_output_ext) != _output_file.length() - _output_ext.length())
|
||||
_output_file += _output_ext;
|
||||
}
|
||||
|
||||
// join <OUTPUT_PATH>/<OUTPUT_FILE> and replace any keys with values
|
||||
auto _prefix = format(std::filesystem::path{_output_path} / _output_file);
|
||||
|
||||
// return on empty
|
||||
if(_prefix.empty()) return std::string{};
|
||||
|
||||
// get the absolute path
|
||||
auto _fname = std::filesystem::absolute(std::filesystem::path{_prefix});
|
||||
|
||||
// create the directory if necessary
|
||||
auto _fname_path = _fname.parent_path();
|
||||
if(!std::filesystem::exists(_fname_path))
|
||||
std::filesystem::create_directories(_fname.parent_path());
|
||||
|
||||
return _fname.string();
|
||||
}
|
||||
|
||||
std::string
|
||||
format_name(std::string_view _name, const config& _cfg)
|
||||
{
|
||||
if(_cfg.demangle && _cfg.truncate)
|
||||
{
|
||||
return truncate_name(cxx_demangle(_name));
|
||||
}
|
||||
|
||||
if(_cfg.demangle)
|
||||
{
|
||||
return cxx_demangle(_name);
|
||||
}
|
||||
|
||||
if(_cfg.truncate)
|
||||
{
|
||||
return truncate_name(_name);
|
||||
}
|
||||
|
||||
return std::string{_name};
|
||||
}
|
||||
|
||||
void
|
||||
initialize()
|
||||
{
|
||||
(void) get_config<config_context::global>();
|
||||
}
|
||||
|
||||
output_key::output_key(std::string _key, std::string _val, std::string _desc)
|
||||
: key{std::move(_key)}
|
||||
, value{std::move(_val)}
|
||||
, description{std::move(_desc)}
|
||||
{}
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lib/common/environment.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
enum class config_context
|
||||
{
|
||||
global = 0,
|
||||
att_plugin,
|
||||
cli_plugin,
|
||||
ctf_plugin,
|
||||
file_plugin,
|
||||
perfetto_plugin,
|
||||
};
|
||||
|
||||
int
|
||||
get_mpi_size();
|
||||
int
|
||||
get_mpi_rank();
|
||||
|
||||
struct config
|
||||
{
|
||||
bool demangle = get_env("ROCP_DEMANGLE_KERNELS", true);
|
||||
bool truncate = get_env("ROCP_TRUNCATE_KERNELS", false);
|
||||
int mpi_size = get_mpi_size();
|
||||
int mpi_rank = get_mpi_rank();
|
||||
std::string output_path = get_env<std::string>("ROCP_OUTPUT_PATH", ".");
|
||||
std::string output_file = get_env<std::string>("ROCP_OUTPUT_FILE", "results");
|
||||
std::string output_ext = {};
|
||||
};
|
||||
|
||||
template <config_context ContextT = config_context::global>
|
||||
config&
|
||||
get_config()
|
||||
{
|
||||
if constexpr(ContextT == config_context::global)
|
||||
{
|
||||
static auto _v = config{};
|
||||
return _v;
|
||||
}
|
||||
else
|
||||
{
|
||||
// context specific config copied from global config
|
||||
static auto _v = get_config<config_context::global>();
|
||||
return _v;
|
||||
}
|
||||
}
|
||||
|
||||
struct output_key
|
||||
{
|
||||
output_key(std::string _key, std::string _val, std::string _desc = {});
|
||||
|
||||
operator std::pair<std::string, std::string>() const;
|
||||
|
||||
std::string key = {};
|
||||
std::string value = {};
|
||||
std::string description = {};
|
||||
};
|
||||
|
||||
std::vector<output_key>
|
||||
output_keys(std::string _tag = {});
|
||||
std::string
|
||||
compose_filename(const config&);
|
||||
std::string
|
||||
format(std::string _fpath, const std::string& _tag = {});
|
||||
std::string
|
||||
format_name(std::string_view _name, const config& = get_config<>());
|
||||
|
||||
void
|
||||
initialize();
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
set(containers_sources)
|
||||
|
||||
set(containers_headers atomic_ring_buffer.hpp c_array.hpp operators.hpp ring_buffer.hpp
|
||||
stable_vector.hpp static_vector.hpp)
|
||||
|
||||
set(containers_sources atomic_ring_buffer.cpp ring_buffer.cpp)
|
||||
|
||||
target_sources(rocprofiler-common-library PRIVATE ${containers_sources}
|
||||
${containers_headers})
|
||||
@@ -0,0 +1,297 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "atomic_ring_buffer.hpp"
|
||||
#include "lib/common/units.hpp"
|
||||
#include "lib/common/environment.hpp"
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <sys/mman.h>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
namespace base
|
||||
{
|
||||
atomic_ring_buffer::atomic_ring_buffer(size_t _size, bool _use_mmap)
|
||||
{
|
||||
set_use_mmap(_use_mmap);
|
||||
init(_size);
|
||||
}
|
||||
|
||||
atomic_ring_buffer::~atomic_ring_buffer() { destroy(); }
|
||||
|
||||
atomic_ring_buffer::atomic_ring_buffer(const atomic_ring_buffer& rhs)
|
||||
: m_use_mmap{rhs.m_use_mmap}
|
||||
, m_use_mmap_explicit{rhs.m_use_mmap_explicit}
|
||||
{
|
||||
init(rhs.m_size);
|
||||
}
|
||||
|
||||
atomic_ring_buffer::atomic_ring_buffer(atomic_ring_buffer&& rhs) noexcept
|
||||
: m_init{rhs.m_init}
|
||||
, m_use_mmap{rhs.m_use_mmap}
|
||||
, m_use_mmap_explicit{rhs.m_use_mmap_explicit}
|
||||
, m_ptr{rhs.m_ptr}
|
||||
, m_size{rhs.m_size}
|
||||
, m_read_count{rhs.m_read_count.load()}
|
||||
, m_write_count{rhs.m_write_count.load()}
|
||||
{
|
||||
rhs.reset();
|
||||
}
|
||||
|
||||
atomic_ring_buffer&
|
||||
atomic_ring_buffer::operator=(const atomic_ring_buffer& rhs)
|
||||
{
|
||||
if(this == &rhs) return *this;
|
||||
destroy();
|
||||
m_use_mmap = rhs.m_use_mmap;
|
||||
m_use_mmap_explicit = rhs.m_use_mmap_explicit;
|
||||
init(rhs.m_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
atomic_ring_buffer&
|
||||
atomic_ring_buffer::operator=(atomic_ring_buffer&& rhs) noexcept
|
||||
{
|
||||
if(this == &rhs) return *this;
|
||||
destroy();
|
||||
m_init = rhs.m_init;
|
||||
m_use_mmap = rhs.m_use_mmap;
|
||||
m_use_mmap_explicit = rhs.m_use_mmap_explicit;
|
||||
m_ptr = rhs.m_ptr;
|
||||
m_size = rhs.m_size;
|
||||
m_read_count = rhs.m_read_count.load();
|
||||
m_write_count = rhs.m_write_count.load();
|
||||
rhs.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
atomic_ring_buffer::init(size_t _size)
|
||||
{
|
||||
if(m_init)
|
||||
throw std::runtime_error(
|
||||
"tim::base::atomic_ring_buffer::init(size_t) :: already initialized");
|
||||
|
||||
m_init = true;
|
||||
|
||||
// Round up to multiple of page size.
|
||||
_size += units::get_page_size() - ((_size % units::get_page_size() > 0)
|
||||
? (_size % units::get_page_size())
|
||||
: units::get_page_size());
|
||||
|
||||
if((_size % units::get_page_size()) > 0)
|
||||
{
|
||||
std::ostringstream _oss{};
|
||||
_oss << "Error! size is not a multiple of page size: " << _size << " % "
|
||||
<< units::get_page_size() << " = " << (_size % units::get_page_size());
|
||||
throw std::runtime_error(_oss.str());
|
||||
}
|
||||
|
||||
m_size = _size;
|
||||
m_read_count = 0;
|
||||
m_write_count = 0;
|
||||
|
||||
if(!m_use_mmap_explicit) m_use_mmap = get_env("ROCPROFILER_USE_MMAP", m_use_mmap);
|
||||
|
||||
if(!m_use_mmap)
|
||||
{
|
||||
m_ptr = malloc(m_size * sizeof(char));
|
||||
return;
|
||||
}
|
||||
|
||||
// Map twice the buffer size.
|
||||
if((m_ptr =
|
||||
mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)) ==
|
||||
MAP_FAILED)
|
||||
{
|
||||
destroy();
|
||||
auto _err = errno;
|
||||
// TIMEMORY_PRINTF_FATAL(stderr, "Error using mmap: %s\n", strerror(_err));
|
||||
throw std::runtime_error(strerror(_err));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
atomic_ring_buffer::destroy()
|
||||
{
|
||||
if(m_ptr && m_init)
|
||||
{
|
||||
if(!m_use_mmap)
|
||||
{
|
||||
::free(m_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unmap the mapped virtual memmory.
|
||||
auto ret = munmap(m_ptr, m_size);
|
||||
if(ret != 0) perror("munmap");
|
||||
}
|
||||
}
|
||||
m_init = false;
|
||||
m_size = 0;
|
||||
m_read_count = 0;
|
||||
m_write_count = 0;
|
||||
m_ptr = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
atomic_ring_buffer::set_use_mmap(bool _v)
|
||||
{
|
||||
if(m_init)
|
||||
throw std::runtime_error("tim::base::atomic_ring_buffer::set_use_mmap(bool) cannot be "
|
||||
"called after initialization");
|
||||
m_use_mmap = _v;
|
||||
m_use_mmap_explicit = true;
|
||||
}
|
||||
|
||||
std::string
|
||||
atomic_ring_buffer::as_string() const
|
||||
{
|
||||
std::ostringstream ss{};
|
||||
ss << std::boolalpha << "is_initialized: " << is_initialized() << ", capacity: " << capacity()
|
||||
<< ", count: " << count() << ", free: " << free() << ", is_empty: " << is_empty()
|
||||
<< ", is_full: " << is_full() << ", pointer: " << m_ptr << ", read count: " << m_read_count
|
||||
<< ", write count: " << m_write_count;
|
||||
return ss.str();
|
||||
}
|
||||
//
|
||||
|
||||
void*
|
||||
atomic_ring_buffer::request(size_t _length)
|
||||
{
|
||||
if(m_ptr == nullptr || m_size == 0) return nullptr;
|
||||
|
||||
if(is_full()) return retrieve(_length);
|
||||
|
||||
// if write count is at the tail of buffer, bump to the end of buffer
|
||||
size_t _write_count = 0;
|
||||
size_t _offset = 0;
|
||||
do
|
||||
{
|
||||
// Make sure we don't put in more than there's room for, by writing no
|
||||
// more than there is free.
|
||||
if(_length > free()) return nullptr;
|
||||
|
||||
_offset = 0;
|
||||
_write_count = m_write_count.load();
|
||||
auto _modulo = m_size - (_write_count % m_size);
|
||||
if(_modulo < _length) _offset = _modulo;
|
||||
} while(!m_write_count.compare_exchange_strong(
|
||||
_write_count, _write_count + _length + _offset, std::memory_order_seq_cst));
|
||||
|
||||
// pointer in buffer
|
||||
void* _out = write_ptr(_write_count);
|
||||
|
||||
return _out;
|
||||
}
|
||||
//
|
||||
|
||||
void*
|
||||
atomic_ring_buffer::retrieve(size_t _length) const
|
||||
{
|
||||
if(m_ptr == nullptr || m_size == 0) return nullptr;
|
||||
|
||||
// Make sure we don't put in more than there's room for, by writing no
|
||||
// more than there is free.
|
||||
|
||||
// if read count is at the tail of buffer, bump to the end of buffer
|
||||
size_t _read_count = 0;
|
||||
size_t _offset = 0;
|
||||
do
|
||||
{
|
||||
if(_length > count()) return nullptr;
|
||||
_offset = 0;
|
||||
_read_count = m_read_count.load();
|
||||
auto _modulo = m_size - (_read_count % m_size);
|
||||
if(_modulo < _length) _offset = _modulo;
|
||||
} while(!m_read_count.compare_exchange_strong(
|
||||
_read_count, _read_count + _length + _offset, std::memory_order_seq_cst));
|
||||
|
||||
// pointer in buffer
|
||||
void* _out = read_ptr(_read_count);
|
||||
|
||||
return _out;
|
||||
}
|
||||
//
|
||||
|
||||
void
|
||||
atomic_ring_buffer::reset()
|
||||
{
|
||||
m_init = false;
|
||||
m_size = 0;
|
||||
m_ptr = nullptr;
|
||||
m_read_count.store(0);
|
||||
m_write_count.store(0);
|
||||
}
|
||||
//
|
||||
|
||||
void
|
||||
atomic_ring_buffer::save(std::fstream& _fs)
|
||||
{
|
||||
auto _read_count = m_read_count.load();
|
||||
auto _write_count = m_write_count.load();
|
||||
_fs.write(reinterpret_cast<char*>(&m_use_mmap), sizeof(m_use_mmap));
|
||||
_fs.write(reinterpret_cast<char*>(&m_use_mmap_explicit), sizeof(m_use_mmap_explicit));
|
||||
_fs.write(reinterpret_cast<char*>(&m_size), sizeof(m_size));
|
||||
_fs.write(reinterpret_cast<char*>(&_read_count), sizeof(_read_count));
|
||||
_fs.write(reinterpret_cast<char*>(&_write_count), sizeof(_write_count));
|
||||
_fs.write(reinterpret_cast<char*>(m_ptr), m_size * sizeof(char));
|
||||
}
|
||||
//
|
||||
|
||||
void
|
||||
atomic_ring_buffer::load(std::fstream& _fs)
|
||||
{
|
||||
destroy();
|
||||
size_t _read_count = 0;
|
||||
size_t _write_count = 0;
|
||||
|
||||
_fs.read(reinterpret_cast<char*>(&m_use_mmap), sizeof(m_use_mmap));
|
||||
_fs.read(reinterpret_cast<char*>(&m_use_mmap_explicit), sizeof(m_use_mmap_explicit));
|
||||
_fs.read(reinterpret_cast<char*>(&m_size), sizeof(m_size));
|
||||
|
||||
init(m_size);
|
||||
if(!m_ptr) m_ptr = malloc(m_size);
|
||||
|
||||
_fs.read(reinterpret_cast<char*>(&_read_count), sizeof(_read_count));
|
||||
_fs.read(reinterpret_cast<char*>(&_write_count), sizeof(_write_count));
|
||||
_fs.read(reinterpret_cast<char*>(m_ptr), m_size * sizeof(char));
|
||||
|
||||
m_read_count.store(_read_count);
|
||||
m_write_count.store(_write_count);
|
||||
}
|
||||
} // namespace base
|
||||
} // namespace container
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,426 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lib/common/units.hpp"
|
||||
#include "lib/common/environment.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
template <typename Tp>
|
||||
struct atomic_ring_buffer;
|
||||
//
|
||||
namespace base
|
||||
{
|
||||
/// \struct tim::base::atomic_ring_buffer
|
||||
/// \brief Ring buffer implementation, with support for mmap as backend (Linux only).
|
||||
struct atomic_ring_buffer
|
||||
{
|
||||
template <typename Tp>
|
||||
friend struct container::atomic_ring_buffer;
|
||||
|
||||
atomic_ring_buffer() = default;
|
||||
explicit atomic_ring_buffer(bool _use_mmap) { set_use_mmap(_use_mmap); }
|
||||
explicit atomic_ring_buffer(size_t _size) { init(_size); }
|
||||
atomic_ring_buffer(size_t _size, bool _use_mmap);
|
||||
|
||||
~atomic_ring_buffer();
|
||||
|
||||
atomic_ring_buffer(const atomic_ring_buffer&);
|
||||
atomic_ring_buffer& operator=(const atomic_ring_buffer&);
|
||||
|
||||
atomic_ring_buffer(atomic_ring_buffer&&) noexcept;
|
||||
atomic_ring_buffer& operator=(atomic_ring_buffer&&) noexcept;
|
||||
|
||||
/// Returns whether the buffer has been allocated
|
||||
bool is_initialized() const { return m_init; }
|
||||
|
||||
/// Get the total number of bytes supported
|
||||
size_t capacity() const { return m_size; }
|
||||
|
||||
/// Creates new ring buffer.
|
||||
void init(size_t size);
|
||||
|
||||
/// Destroy ring buffer.
|
||||
void destroy();
|
||||
|
||||
/// Request a pointer for writing at least \param n bytes.
|
||||
void* request(size_t n);
|
||||
|
||||
/// Retrieve a pointer for reading at least \param n bytes.
|
||||
void* retrieve(size_t n) const;
|
||||
|
||||
/// Write class-type data to buffer (uses placement new).
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*> write(Tp* in, std::enable_if_t<std::is_class<Tp>::value, int> = 0);
|
||||
|
||||
/// Write non-class-type data to buffer (uses memcpy).
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*> write(Tp* in, std::enable_if_t<!std::is_class<Tp>::value, int> = 0);
|
||||
|
||||
/// Request a pointer to an allocation. This is similar to a "write" except the
|
||||
/// memory is uninitialized. Typically used by allocators. If Tp is a class type,
|
||||
/// be sure to use a placement new instead of a memcpy.
|
||||
template <typename Tp>
|
||||
Tp* request();
|
||||
|
||||
/// Read class-type data from buffer (uses placement new).
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*> read(Tp* _dest,
|
||||
std::enable_if_t<std::is_class<Tp>::value, int> = 0) const;
|
||||
|
||||
/// Read non-class-type data from buffer (uses memcpy).
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*> read(Tp* _dest,
|
||||
std::enable_if_t<!std::is_class<Tp>::value, int> = 0) const;
|
||||
|
||||
/// Retrieve a pointer to the head allocation (read).
|
||||
template <typename Tp>
|
||||
Tp* retrieve() const;
|
||||
|
||||
/// Returns number of bytes currently held by the buffer.
|
||||
size_t count() const { return (m_write_count - m_read_count); }
|
||||
|
||||
/// Returns how many bytes are availiable in the buffer.
|
||||
size_t free() const { return (m_size - count()); }
|
||||
|
||||
/// Returns if the buffer is empty.
|
||||
bool is_empty() const { return (count() == 0); }
|
||||
|
||||
/// Returns if the buffer is full.
|
||||
bool is_full() const { return (count() == m_size); }
|
||||
|
||||
/// explicitly configure to use mmap if avail
|
||||
void set_use_mmap(bool);
|
||||
|
||||
/// query whether using mmap
|
||||
bool get_use_mmap() const { return m_use_mmap; }
|
||||
|
||||
std::string as_string() const;
|
||||
|
||||
void save(std::fstream& _fs);
|
||||
void load(std::fstream& _fs);
|
||||
|
||||
private:
|
||||
/// Returns the current write pointer.
|
||||
void* write_ptr(size_t _write_count) const
|
||||
{
|
||||
return static_cast<char*>(m_ptr) + (_write_count % m_size);
|
||||
}
|
||||
|
||||
/// Returns the current read pointer.
|
||||
void* read_ptr(size_t _read_count) const
|
||||
{
|
||||
return static_cast<char*>(m_ptr) + (_read_count % m_size);
|
||||
}
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
bool m_init = false;
|
||||
bool m_use_mmap = true;
|
||||
bool m_use_mmap_explicit = false;
|
||||
void* m_ptr = nullptr;
|
||||
size_t m_size = 0;
|
||||
mutable std::atomic<size_t> m_read_count = 0;
|
||||
std::atomic<size_t> m_write_count = 0;
|
||||
};
|
||||
//
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*>
|
||||
atomic_ring_buffer::write(Tp* in, std::enable_if_t<std::is_class<Tp>::value, int>)
|
||||
{
|
||||
if(in == nullptr || m_ptr == nullptr) return {0, nullptr};
|
||||
|
||||
auto _length = sizeof(Tp);
|
||||
void* _out_p = request(_length);
|
||||
|
||||
if(_out_p == nullptr) return {0, nullptr};
|
||||
|
||||
// Copy in.
|
||||
new(_out_p) Tp{std::move(*in)};
|
||||
|
||||
// pointer in buffer
|
||||
Tp* _out = reinterpret_cast<Tp*>(_out_p);
|
||||
|
||||
return {_length, _out};
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*>
|
||||
atomic_ring_buffer::write(Tp* in, std::enable_if_t<!std::is_class<Tp>::value, int>)
|
||||
{
|
||||
if(in == nullptr || m_ptr == nullptr) return {0, nullptr};
|
||||
|
||||
auto _length = sizeof(Tp);
|
||||
void* _out_p = request(_length);
|
||||
|
||||
if(_out_p == nullptr) return {0, nullptr};
|
||||
|
||||
// Copy in.
|
||||
memcpy(_out_p, in, _length);
|
||||
|
||||
// pointer in buffer
|
||||
Tp* _out = reinterpret_cast<Tp*>(_out_p);
|
||||
|
||||
return {_length, _out};
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
Tp*
|
||||
atomic_ring_buffer::request()
|
||||
{
|
||||
if(m_ptr == nullptr) return nullptr;
|
||||
|
||||
return request(sizeof(Tp));
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*>
|
||||
atomic_ring_buffer::read(Tp* _dest, std::enable_if_t<std::is_class<Tp>::value, int>) const
|
||||
{
|
||||
if(is_empty() || _dest == nullptr) return {0, nullptr};
|
||||
|
||||
auto _length = sizeof(Tp);
|
||||
void* _out_p = retrieve(_length);
|
||||
|
||||
if(_out_p == nullptr) return {0, nullptr};
|
||||
|
||||
// pointer in buffer
|
||||
Tp* in = reinterpret_cast<Tp*>(_out_p);
|
||||
|
||||
// Copy out for BYTE, nothing magic here.
|
||||
*_dest = *in;
|
||||
|
||||
return {_length, in};
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*>
|
||||
atomic_ring_buffer::read(Tp* _dest, std::enable_if_t<!std::is_class<Tp>::value, int>) const
|
||||
{
|
||||
if(is_empty() || _dest == nullptr) return {0, nullptr};
|
||||
|
||||
auto _length = sizeof(Tp);
|
||||
void* _out_p = retrieve(_length);
|
||||
|
||||
if(_out_p == nullptr) return {0, nullptr};
|
||||
|
||||
// pointer in buffer
|
||||
Tp* in = reinterpret_cast<Tp*>(_out_p);
|
||||
|
||||
using Up = typename std::remove_const<Tp>::type;
|
||||
|
||||
// Copy out for BYTE, nothing magic here.
|
||||
Up* _out = const_cast<Up*>(_dest);
|
||||
memcpy(_out, in, _length);
|
||||
|
||||
return {_length, in};
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
Tp*
|
||||
atomic_ring_buffer::retrieve() const
|
||||
{
|
||||
if(m_ptr == nullptr) return nullptr;
|
||||
|
||||
return retrieve(sizeof(Tp));
|
||||
}
|
||||
//
|
||||
} // namespace base
|
||||
//
|
||||
/// \struct tim::data_storage::atomic_ring_buffer
|
||||
/// \brief Ring buffer wrapper around \ref tim::base::atomic_ring_buffer for data of type
|
||||
/// Tp. If the data object size is larger than the page size (typically 4KB), behavior is
|
||||
/// undefined. During initialization, one requests a minimum number of objects and the
|
||||
/// buffer will support that number of object + the remainder of the page, e.g. if a page
|
||||
/// is 1000 bytes, the object is 1 byte, and the buffer is requested to support 1500
|
||||
/// objects, then an allocation supporting 2000 objects (i.e. 2 pages) will be created.
|
||||
template <typename Tp>
|
||||
struct atomic_ring_buffer : private base::atomic_ring_buffer
|
||||
{
|
||||
using base_type = base::atomic_ring_buffer;
|
||||
|
||||
static size_t get_items_per_page();
|
||||
|
||||
atomic_ring_buffer() = default;
|
||||
~atomic_ring_buffer() = default;
|
||||
|
||||
explicit atomic_ring_buffer(bool _use_mmap)
|
||||
: base_type{_use_mmap}
|
||||
{}
|
||||
|
||||
explicit atomic_ring_buffer(size_t _size)
|
||||
: base_type{_size * sizeof(Tp)}
|
||||
{}
|
||||
|
||||
atomic_ring_buffer(size_t _size, bool _use_mmap)
|
||||
: base_type{_size * sizeof(Tp), _use_mmap}
|
||||
{}
|
||||
|
||||
atomic_ring_buffer(const atomic_ring_buffer&);
|
||||
atomic_ring_buffer(atomic_ring_buffer&&) noexcept = default;
|
||||
|
||||
atomic_ring_buffer& operator=(const atomic_ring_buffer&);
|
||||
atomic_ring_buffer& operator=(atomic_ring_buffer&&) noexcept = default;
|
||||
|
||||
/// Returns whether the buffer has been allocated
|
||||
bool is_initialized() const { return base_type::is_initialized(); }
|
||||
|
||||
/// Get the total number of Tp instances supported
|
||||
size_t capacity() const { return (base_type::capacity()) / sizeof(Tp); }
|
||||
|
||||
/// Creates new ring buffer.
|
||||
void init(size_t _size) { base_type::init(_size * sizeof(Tp)); }
|
||||
|
||||
/// Destroy ring buffer.
|
||||
void destroy() { base_type::destroy(); }
|
||||
|
||||
/// Write data to buffer.
|
||||
size_t data_size() const { return sizeof(Tp); }
|
||||
|
||||
/// Write data to buffer. Return pointer to location of write
|
||||
Tp* write(Tp* in) { return base_type::write<Tp>(in).second; }
|
||||
|
||||
/// Read data from buffer. Return pointer to location of read
|
||||
Tp* read(Tp* _dest) const { return base_type::read<Tp>(_dest).second; }
|
||||
|
||||
/// Get an uninitialized address at tail of buffer.
|
||||
Tp* request() { return base_type::request<Tp>(); }
|
||||
|
||||
/// Read data from head of buffer.
|
||||
Tp* retrieve() { return base_type::retrieve<Tp>(); }
|
||||
|
||||
/// Returns number of Tp instances currently held by the buffer.
|
||||
size_t count() const { return (base_type::count()) / sizeof(Tp); }
|
||||
|
||||
/// Returns how many Tp instances are availiable in the buffer.
|
||||
size_t free() const { return (base_type::free()) / sizeof(Tp); }
|
||||
|
||||
/// Returns if the buffer is empty.
|
||||
bool is_empty() const { return base_type::is_empty(); }
|
||||
|
||||
/// Returns if the buffer is full.
|
||||
bool is_full() const { return (base_type::free() < sizeof(Tp)); }
|
||||
|
||||
template <typename... Args>
|
||||
auto emplace(Args&&... args)
|
||||
{
|
||||
Tp _obj{std::forward<Args>(args)...};
|
||||
return write(&_obj);
|
||||
}
|
||||
|
||||
using base_type::get_use_mmap;
|
||||
using base_type::load;
|
||||
using base_type::save;
|
||||
using base_type::set_use_mmap;
|
||||
|
||||
std::string as_string() const
|
||||
{
|
||||
std::ostringstream ss{};
|
||||
size_t _w = std::log10(base_type::capacity()) + 1;
|
||||
ss << std::boolalpha << std::right << "data size: " << std::setw(_w) << data_size()
|
||||
<< " B, is_initialized: " << std::setw(5) << is_initialized()
|
||||
<< ", is_empty: " << std::setw(5) << is_empty() << ", is_full: " << std::setw(5)
|
||||
<< is_full() << ", capacity: " << std::setw(_w) << capacity()
|
||||
<< ", count: " << std::setw(_w) << count() << ", free: " << std::setw(_w) << free()
|
||||
<< ", raw capacity: " << std::setw(_w) << base_type::capacity()
|
||||
<< " B, raw count: " << std::setw(_w) << base_type::count()
|
||||
<< " B, raw free: " << std::setw(_w) << base_type::free()
|
||||
<< " B, pointer: " << std::setw(15) << base_type::m_ptr
|
||||
<< ", raw read count: " << std::setw(_w) << base_type::m_read_count
|
||||
<< ", raw write count: " << std::setw(_w) << base_type::m_write_count;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const atomic_ring_buffer& obj)
|
||||
{
|
||||
return os << obj.as_string();
|
||||
}
|
||||
};
|
||||
//
|
||||
template <typename Tp>
|
||||
size_t
|
||||
atomic_ring_buffer<Tp>::get_items_per_page()
|
||||
{
|
||||
return std::max<size_t>(units::get_page_size() / sizeof(Tp), 1);
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
atomic_ring_buffer<Tp>::atomic_ring_buffer(const atomic_ring_buffer<Tp>& rhs)
|
||||
: base_type{rhs}
|
||||
{
|
||||
size_t _n = rhs.count();
|
||||
char* _end = static_cast<char*>(rhs.m_ptr) + rhs.m_size;
|
||||
for(size_t i = 0; i < _n; ++i)
|
||||
{
|
||||
char* _addr = static_cast<char*>(rhs.read_ptr(m_read_count)) + (i * sizeof(Tp));
|
||||
if((_addr + sizeof(Tp)) > _end) _addr = static_cast<char*>(rhs.m_ptr);
|
||||
Tp* _in = static_cast<Tp*>(static_cast<void*>(_addr));
|
||||
write(_in);
|
||||
}
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
atomic_ring_buffer<Tp>&
|
||||
atomic_ring_buffer<Tp>::operator=(const atomic_ring_buffer<Tp>& rhs)
|
||||
{
|
||||
if(this == &rhs) return *this;
|
||||
|
||||
base_type::operator=(rhs);
|
||||
size_t _n = rhs.count();
|
||||
char* _end = static_cast<char*>(rhs.m_ptr) + rhs.m_size;
|
||||
for(size_t i = 0; i < _n; ++i)
|
||||
{
|
||||
char* _addr = static_cast<char*>(rhs.read_ptr(m_read_count)) + (i * sizeof(Tp));
|
||||
if((_addr + sizeof(Tp)) > _end) _addr = static_cast<char*>(rhs.m_ptr);
|
||||
Tp* _in = static_cast<Tp*>(static_cast<void*>(_addr));
|
||||
write(_in);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
} // namespace container
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,136 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
template <typename Tp>
|
||||
struct c_array
|
||||
{
|
||||
// Construct an array wrapper from a base pointer and array size
|
||||
c_array(Tp* _base, size_t _size)
|
||||
: m_base{_base}
|
||||
, m_size{_size}
|
||||
{}
|
||||
|
||||
~c_array() = default;
|
||||
c_array(const c_array&) = default;
|
||||
c_array& operator=(const c_array&) = default;
|
||||
c_array& operator=(c_array&&) noexcept = default;
|
||||
|
||||
// Get the size of the wrapped array
|
||||
size_t size() const { return m_size; }
|
||||
|
||||
// Access an element by index
|
||||
Tp& operator[](size_t i) { return m_base[i]; }
|
||||
|
||||
// Access an element by index
|
||||
const Tp& operator[](size_t i) const { return m_base[i]; }
|
||||
|
||||
// Access an element by index with bounds check
|
||||
Tp& at(size_t i)
|
||||
{
|
||||
if(i < m_size) return m_base[i];
|
||||
throw std::out_of_range(std::string{typeid(*this).name()} + std::to_string(i) +
|
||||
" exceeds size " + std::to_string(m_size));
|
||||
}
|
||||
|
||||
// Access an element by index with bounds check
|
||||
const Tp& at(size_t i) const
|
||||
{
|
||||
if(i < m_size) return m_base[i];
|
||||
throw std::out_of_range(std::string{typeid(*this).name()} + std::to_string(i) +
|
||||
" exceeds size " + std::to_string(m_size));
|
||||
}
|
||||
|
||||
// Get a slice of this array, from a start index (inclusive) to end index (exclusive)
|
||||
c_array<Tp> slice(size_t start, size_t end) { return c_array<Tp>(&m_base[start], end - start); }
|
||||
|
||||
void pop_front()
|
||||
{
|
||||
++m_base;
|
||||
--m_size;
|
||||
}
|
||||
|
||||
void pop_back() { --m_size; }
|
||||
|
||||
operator Tp*() const { return m_base; }
|
||||
|
||||
// Iterator class for convenient range-based for loop support
|
||||
template <typename Up>
|
||||
struct iterator
|
||||
{
|
||||
// Start the iterator at a given pointer
|
||||
explicit iterator(Tp* p)
|
||||
: m_ptr{p}
|
||||
{}
|
||||
|
||||
// Advance to the next element
|
||||
void operator++() { ++m_ptr; }
|
||||
void operator++(int) { m_ptr++; }
|
||||
|
||||
// Get the current element
|
||||
Up& operator*() const { return *m_ptr; }
|
||||
|
||||
// Compare iterators
|
||||
bool operator==(const iterator& rhs) const { return m_ptr == rhs.m_ptr; }
|
||||
bool operator!=(const iterator& rhs) const { return m_ptr != rhs.m_ptr; }
|
||||
|
||||
private:
|
||||
Tp* m_ptr = nullptr;
|
||||
};
|
||||
|
||||
// Get an iterator positioned at the beginning of the wrapped array
|
||||
iterator<Tp> begin() { return iterator<Tp>{m_base}; }
|
||||
iterator<const Tp> begin() const { return iterator<const Tp>{m_base}; }
|
||||
|
||||
// Get an iterator positioned at the end of the wrapped array
|
||||
iterator<Tp> end() { return iterator<Tp>{&m_base[m_size]}; }
|
||||
iterator<const Tp> end() const { return iterator<const Tp>{&m_base[m_size]}; }
|
||||
|
||||
private:
|
||||
Tp* m_base = nullptr;
|
||||
size_t m_size = 0;
|
||||
};
|
||||
|
||||
// Function for automatic template argument deduction
|
||||
template <typename Tp>
|
||||
c_array<Tp>
|
||||
wrap_c_array(Tp* base, size_t size)
|
||||
{
|
||||
return c_array<Tp>(base, size);
|
||||
}
|
||||
} // namespace container
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,239 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#define ROCPROFILER_IMPORT_TEMPLATE2(template_name)
|
||||
#define ROCPROFILER_IMPORT_TEMPLATE1(template_name)
|
||||
|
||||
// Import a 2-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
#define ROCPROFILER_OPERATOR_TEMPLATE2(template_name2) \
|
||||
ROCPROFILER_IMPORT_TEMPLATE2(template_name2) \
|
||||
template <typename T, typename U, typename B> \
|
||||
struct is_chained_base<::rocprofiler::container::template_name2<T, U, B>> \
|
||||
{ \
|
||||
using value = ::rocprofiler::container::true_t; \
|
||||
};
|
||||
|
||||
// Import a 1-type-argument operator template into boost (if necessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
#define ROCPROFILER_OPERATOR_TEMPLATE1(template_name1) \
|
||||
ROCPROFILER_IMPORT_TEMPLATE1(template_name1) \
|
||||
template <typename T, typename B> \
|
||||
struct is_chained_base<::rocprofiler::container::template_name1<T, B>> \
|
||||
{ \
|
||||
using value = ::rocprofiler::container::true_t; \
|
||||
};
|
||||
|
||||
#define ROCPROFILER_OPERATOR_TEMPLATE(template_name) \
|
||||
template <typename T, \
|
||||
typename U = T, \
|
||||
typename B = empty_base<T>, \
|
||||
typename O = typename is_chained_base<U>::value> \
|
||||
struct template_name; \
|
||||
\
|
||||
template <typename T, typename U, typename B> \
|
||||
struct template_name<T, U, B, false_t> : template_name##2 < T \
|
||||
, U \
|
||||
, B > \
|
||||
{}; \
|
||||
\
|
||||
template <typename T, typename U> \
|
||||
struct template_name<T, U, empty_base<T>, true_t> : template_name##1 < T \
|
||||
, U > \
|
||||
{}; \
|
||||
\
|
||||
template <typename T, typename B> \
|
||||
struct template_name<T, T, B, false_t> : template_name##1 < T \
|
||||
, B > \
|
||||
{}; \
|
||||
\
|
||||
template <typename T, typename U, typename B, typename O> \
|
||||
struct is_chained_base<template_name<T, U, B, O>> \
|
||||
{ \
|
||||
using value = ::rocprofiler::container::true_t; \
|
||||
}; \
|
||||
\
|
||||
ROCPROFILER_OPERATOR_TEMPLATE2(template_name##2) \
|
||||
ROCPROFILER_OPERATOR_TEMPLATE1(template_name##1)
|
||||
|
||||
#define ROCPROFILER_BINARY_OPERATOR_COMMUTATIVE(NAME, OP) \
|
||||
template <typename T, typename U, typename B = empty_base<T>> \
|
||||
struct NAME##2 : B{friend T operator OP(T lhs, const U& rhs){return lhs OP## = rhs; \
|
||||
} \
|
||||
friend T operator OP(const U& lhs, T rhs) { return rhs OP## = lhs; } \
|
||||
} \
|
||||
; \
|
||||
\
|
||||
template <typename T, typename B = empty_base<T>> \
|
||||
struct NAME##1 : B{friend T operator OP(T lhs, const T& rhs){return lhs OP## = rhs; \
|
||||
} \
|
||||
} \
|
||||
;
|
||||
|
||||
#define ROCPROFILER_BINARY_OPERATOR_NON_COMMUTATIVE(NAME, OP) \
|
||||
template <typename T, typename U, typename B = empty_base<T>> \
|
||||
struct NAME##2 : B{friend T operator OP(T lhs, const U& rhs){return lhs OP## = rhs; \
|
||||
} \
|
||||
} \
|
||||
;
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
struct true_t
|
||||
{};
|
||||
|
||||
struct false_t
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
class empty_base
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
struct is_chained_base
|
||||
{
|
||||
using value = true_t;
|
||||
};
|
||||
|
||||
ROCPROFILER_BINARY_OPERATOR_COMMUTATIVE(addable, +)
|
||||
ROCPROFILER_BINARY_OPERATOR_NON_COMMUTATIVE(subtractable, -)
|
||||
|
||||
ROCPROFILER_OPERATOR_TEMPLATE(addable)
|
||||
|
||||
template <typename T, typename B = empty_base<T>>
|
||||
struct incrementable : B
|
||||
{
|
||||
friend T operator++(T& x, int)
|
||||
{
|
||||
incrementable_type nrv(x);
|
||||
++x;
|
||||
return nrv;
|
||||
}
|
||||
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
typedef T incrementable_type;
|
||||
};
|
||||
|
||||
template <typename T, typename B = empty_base<T>>
|
||||
struct decrementable : B
|
||||
{
|
||||
friend T operator--(T& x, int)
|
||||
{
|
||||
decrementable_type nrv(x);
|
||||
--x;
|
||||
return nrv;
|
||||
}
|
||||
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
typedef T decrementable_type;
|
||||
};
|
||||
|
||||
template <typename T, typename P, typename B = empty_base<T>>
|
||||
struct dereferenceable : B
|
||||
{
|
||||
P operator->() const { return ::std::addressof(*static_cast<const T&>(*this)); }
|
||||
};
|
||||
|
||||
template <typename T, typename I, typename R, typename B = empty_base<T>>
|
||||
struct indexable : B
|
||||
{
|
||||
R operator[](I n) const { return *(static_cast<const T&>(*this) + n); }
|
||||
};
|
||||
|
||||
template <typename T, typename B = empty_base<T>>
|
||||
struct equality_comparable1 : B
|
||||
{
|
||||
friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
|
||||
};
|
||||
|
||||
template <typename T, typename P, typename B = empty_base<T>>
|
||||
struct input_iteratable : equality_comparable1<T, incrementable<T, dereferenceable<T, P, B>>>
|
||||
{};
|
||||
|
||||
template <typename T, typename B = empty_base<T>>
|
||||
struct output_iteratable : incrementable<T, B>
|
||||
{};
|
||||
|
||||
template <typename T, typename P, typename B = empty_base<T>>
|
||||
struct forward_iteratable : input_iteratable<T, P, B>
|
||||
{};
|
||||
|
||||
template <typename T, typename P, typename B = empty_base<T>>
|
||||
struct bidirectional_iteratable : forward_iteratable<T, P, decrementable<T, B>>
|
||||
{};
|
||||
|
||||
// template <typename T, typename U, typename B = empty_base<T>>
|
||||
// struct subtractable2;
|
||||
|
||||
template <typename T, typename U, typename B = empty_base<T>>
|
||||
struct additive2 : addable2<T, U, subtractable2<T, U, B>>
|
||||
{};
|
||||
|
||||
template <typename T, typename B = empty_base<T>>
|
||||
struct less_than_comparable1 : B
|
||||
{
|
||||
friend bool operator>(const T& x, const T& y) { return y < x; }
|
||||
friend bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); }
|
||||
friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
|
||||
};
|
||||
|
||||
// To avoid repeated derivation from equality_comparable,
|
||||
// which is an indirect base typename of bidirectional_iterable,
|
||||
// random_access_iteratable must not be derived from totally_ordered1
|
||||
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
|
||||
template <typename T, typename P, typename D, typename R, typename B = empty_base<T>>
|
||||
struct random_access_iteratable
|
||||
: bidirectional_iteratable<T, P, less_than_comparable1<T, additive2<T, D, indexable<T, D, R, B>>>>
|
||||
{};
|
||||
|
||||
template <typename CategoryT,
|
||||
typename Tp,
|
||||
typename DistanceT = std::ptrdiff_t,
|
||||
typename PointerT = Tp*,
|
||||
typename ReferenceT = Tp&>
|
||||
struct iterator_helper
|
||||
{
|
||||
using iterator_category = CategoryT;
|
||||
using value_type = Tp;
|
||||
using difference_type = DistanceT;
|
||||
using pointer = PointerT;
|
||||
using reference = ReferenceT;
|
||||
};
|
||||
|
||||
template <typename T, typename V, typename D = std::ptrdiff_t, typename P = V*, typename R = V&>
|
||||
struct random_access_iterator_helper
|
||||
: random_access_iteratable<T, P, D, R, iterator_helper<std::random_access_iterator_tag, V, D, P, R>>
|
||||
{
|
||||
friend D requires_difference_operator(const T& x, const T& y) { return x - y; }
|
||||
}; // random_access_iterator_helper
|
||||
} // namespace container
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,289 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "ring_buffer.hpp"
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sys/mman.h>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
namespace base
|
||||
{
|
||||
ring_buffer::ring_buffer(size_t _size, bool _use_mmap)
|
||||
{
|
||||
set_use_mmap(_use_mmap);
|
||||
init(_size);
|
||||
}
|
||||
|
||||
ring_buffer::~ring_buffer() { destroy(); }
|
||||
|
||||
ring_buffer::ring_buffer(const ring_buffer& rhs)
|
||||
: m_use_mmap{rhs.m_use_mmap}
|
||||
, m_use_mmap_explicit{rhs.m_use_mmap_explicit}
|
||||
{
|
||||
init(rhs.m_size);
|
||||
}
|
||||
|
||||
ring_buffer::ring_buffer(ring_buffer&& rhs) noexcept
|
||||
: m_init{rhs.m_init}
|
||||
, m_use_mmap{rhs.m_use_mmap}
|
||||
, m_use_mmap_explicit{rhs.m_use_mmap_explicit}
|
||||
, m_ptr{rhs.m_ptr}
|
||||
, m_size{rhs.m_size}
|
||||
, m_read_count{rhs.m_read_count}
|
||||
, m_write_count{rhs.m_write_count}
|
||||
{
|
||||
rhs.reset();
|
||||
}
|
||||
|
||||
ring_buffer&
|
||||
ring_buffer::operator=(const ring_buffer& rhs)
|
||||
{
|
||||
if(this == &rhs) return *this;
|
||||
destroy();
|
||||
m_use_mmap = rhs.m_use_mmap;
|
||||
m_use_mmap_explicit = rhs.m_use_mmap_explicit;
|
||||
init(rhs.m_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ring_buffer&
|
||||
ring_buffer::operator=(ring_buffer&& rhs) noexcept
|
||||
{
|
||||
if(this == &rhs) return *this;
|
||||
destroy();
|
||||
m_init = rhs.m_init;
|
||||
m_use_mmap = rhs.m_use_mmap;
|
||||
m_use_mmap_explicit = rhs.m_use_mmap_explicit;
|
||||
m_ptr = rhs.m_ptr;
|
||||
m_size = rhs.m_size;
|
||||
m_read_count = rhs.m_read_count;
|
||||
m_write_count = rhs.m_write_count;
|
||||
rhs.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
ring_buffer::init(size_t _size)
|
||||
{
|
||||
if(m_init)
|
||||
throw std::runtime_error("tim::base::ring_buffer::init(size_t) :: already initialized");
|
||||
|
||||
m_init = true;
|
||||
|
||||
// Round up to multiple of page size.
|
||||
_size += units::get_page_size() - ((_size % units::get_page_size() > 0)
|
||||
? (_size % units::get_page_size())
|
||||
: units::get_page_size());
|
||||
|
||||
if((_size % units::get_page_size()) > 0)
|
||||
{
|
||||
std::ostringstream _oss{};
|
||||
_oss << "Error! size is not a multiple of page size: " << _size << " % "
|
||||
<< units::get_page_size() << " = " << (_size % units::get_page_size());
|
||||
throw std::runtime_error(_oss.str());
|
||||
}
|
||||
|
||||
m_size = _size;
|
||||
m_read_count = 0;
|
||||
m_write_count = 0;
|
||||
|
||||
if(!m_use_mmap_explicit) m_use_mmap = get_env("ROCPROFILER_USE_MMAP", m_use_mmap);
|
||||
|
||||
if(!m_use_mmap)
|
||||
{
|
||||
m_ptr = malloc(m_size * sizeof(char));
|
||||
return;
|
||||
}
|
||||
|
||||
// Map twice the buffer size.
|
||||
if((m_ptr =
|
||||
mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)) ==
|
||||
MAP_FAILED)
|
||||
{
|
||||
destroy();
|
||||
auto _err = errno;
|
||||
// TIMEMORY_PRINTF_FATAL(stderr, "Error using mmap: %s\n", strerror(_err));
|
||||
throw std::runtime_error(strerror(_err));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ring_buffer::destroy()
|
||||
{
|
||||
if(m_ptr && m_init)
|
||||
{
|
||||
if(!m_use_mmap)
|
||||
{
|
||||
::free(m_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unmap the mapped virtual memmory.
|
||||
auto ret = munmap(m_ptr, m_size);
|
||||
if(ret != 0) perror("munmap");
|
||||
}
|
||||
}
|
||||
m_init = false;
|
||||
m_size = 0;
|
||||
m_read_count = 0;
|
||||
m_write_count = 0;
|
||||
m_ptr = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ring_buffer::set_use_mmap(bool _v)
|
||||
{
|
||||
if(!m_init)
|
||||
{
|
||||
m_use_mmap = _v;
|
||||
m_use_mmap_explicit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("tim::base::ring_buffer::set_use_mmap(bool) cannot be "
|
||||
"called after initialization");
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
ring_buffer::as_string() const
|
||||
{
|
||||
std::ostringstream ss{};
|
||||
ss << std::boolalpha << "is_initialized: " << is_initialized() << ", capacity: " << capacity()
|
||||
<< ", count: " << count() << ", free: " << free() << ", is_empty: " << is_empty()
|
||||
<< ", is_full: " << is_full() << ", pointer: " << m_ptr << ", read count: " << m_read_count
|
||||
<< ", write count: " << m_write_count;
|
||||
return ss.str();
|
||||
}
|
||||
//
|
||||
|
||||
void*
|
||||
ring_buffer::request(size_t _length)
|
||||
{
|
||||
if(m_ptr == nullptr) return nullptr;
|
||||
|
||||
// Make sure we don't put in more than there's room for, by writing no
|
||||
// more than there is free.
|
||||
if(_length > free())
|
||||
throw std::runtime_error("heap-buffer-overflow :: ring buffer is full. read data "
|
||||
"to avoid data corruption");
|
||||
|
||||
// if write count is at the tail of buffer, bump to the end of buffer
|
||||
auto _modulo = m_size - (m_write_count % m_size);
|
||||
if(_modulo < _length) m_write_count += _modulo;
|
||||
|
||||
// pointer in buffer
|
||||
void* _out = write_ptr();
|
||||
|
||||
// Update write count
|
||||
m_write_count += _length;
|
||||
|
||||
return _out;
|
||||
}
|
||||
//
|
||||
|
||||
void*
|
||||
ring_buffer::retrieve(size_t _length)
|
||||
{
|
||||
if(m_ptr == nullptr) return nullptr;
|
||||
|
||||
// Make sure we don't put in more than there's room for, by writing no
|
||||
// more than there is free.
|
||||
if(_length > count()) throw std::runtime_error("ring buffer is empty");
|
||||
|
||||
// if read count is at the tail of buffer, bump to the end of buffer
|
||||
auto _modulo = m_size - (m_read_count % m_size);
|
||||
if(_modulo < _length) m_read_count += _modulo;
|
||||
|
||||
// pointer in buffer
|
||||
void* _out = read_ptr();
|
||||
|
||||
// Update write count
|
||||
m_read_count += _length;
|
||||
|
||||
return _out;
|
||||
}
|
||||
//
|
||||
|
||||
size_t
|
||||
ring_buffer::rewind(size_t n) const
|
||||
{
|
||||
if(n > m_read_count) n = m_read_count;
|
||||
m_read_count -= n;
|
||||
return n;
|
||||
}
|
||||
//
|
||||
|
||||
void
|
||||
ring_buffer::reset()
|
||||
{
|
||||
m_init = false;
|
||||
m_ptr = nullptr;
|
||||
m_size = 0;
|
||||
m_read_count = 0;
|
||||
m_write_count = 0;
|
||||
}
|
||||
//
|
||||
|
||||
void
|
||||
ring_buffer::save(std::fstream& _fs)
|
||||
{
|
||||
_fs.write(reinterpret_cast<char*>(&m_use_mmap), sizeof(m_use_mmap));
|
||||
_fs.write(reinterpret_cast<char*>(&m_use_mmap_explicit), sizeof(m_use_mmap_explicit));
|
||||
_fs.write(reinterpret_cast<char*>(&m_size), sizeof(m_size));
|
||||
_fs.write(reinterpret_cast<char*>(&m_read_count), sizeof(m_read_count));
|
||||
_fs.write(reinterpret_cast<char*>(&m_write_count), sizeof(m_write_count));
|
||||
_fs.write(reinterpret_cast<char*>(m_ptr), m_size * sizeof(char));
|
||||
}
|
||||
//
|
||||
|
||||
void
|
||||
ring_buffer::load(std::fstream& _fs)
|
||||
{
|
||||
destroy();
|
||||
|
||||
_fs.read(reinterpret_cast<char*>(&m_use_mmap), sizeof(m_use_mmap));
|
||||
_fs.read(reinterpret_cast<char*>(&m_use_mmap_explicit), sizeof(m_use_mmap_explicit));
|
||||
_fs.read(reinterpret_cast<char*>(&m_size), sizeof(m_size));
|
||||
|
||||
init(m_size);
|
||||
if(!m_ptr) m_ptr = malloc(m_size);
|
||||
|
||||
_fs.read(reinterpret_cast<char*>(&m_read_count), sizeof(m_read_count));
|
||||
_fs.read(reinterpret_cast<char*>(&m_write_count), sizeof(m_write_count));
|
||||
_fs.read(reinterpret_cast<char*>(m_ptr), m_size * sizeof(char));
|
||||
}
|
||||
} // namespace base
|
||||
} // namespace container
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,495 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lib/common/environment.hpp"
|
||||
#include "lib/common/units.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
template <typename Tp>
|
||||
struct ring_buffer;
|
||||
//
|
||||
namespace base
|
||||
{
|
||||
/// \struct tim::base::ring_buffer
|
||||
/// \brief Ring buffer implementation, with support for mmap as backend (Linux only).
|
||||
struct ring_buffer
|
||||
{
|
||||
template <typename Tp>
|
||||
friend struct container::ring_buffer;
|
||||
|
||||
ring_buffer() = default;
|
||||
explicit ring_buffer(bool _use_mmap) { set_use_mmap(_use_mmap); }
|
||||
explicit ring_buffer(size_t _size) { init(_size); }
|
||||
ring_buffer(size_t _size, bool _use_mmap);
|
||||
|
||||
~ring_buffer();
|
||||
|
||||
ring_buffer(const ring_buffer&);
|
||||
ring_buffer& operator=(const ring_buffer&);
|
||||
|
||||
ring_buffer(ring_buffer&&) noexcept;
|
||||
ring_buffer& operator=(ring_buffer&&) noexcept;
|
||||
|
||||
/// Returns whether the buffer has been allocated
|
||||
bool is_initialized() const { return m_init; }
|
||||
|
||||
/// Get the total number of bytes supported
|
||||
size_t capacity() const { return m_size; }
|
||||
|
||||
/// Creates new ring buffer.
|
||||
void init(size_t size);
|
||||
|
||||
/// Destroy ring buffer.
|
||||
void destroy();
|
||||
|
||||
/// Write class-type data to buffer (uses placement new).
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*> write(Tp* in, std::enable_if_t<std::is_class<Tp>::value, int> = 0);
|
||||
|
||||
/// Write non-class-type data to buffer (uses memcpy).
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*> write(Tp* in, std::enable_if_t<!std::is_class<Tp>::value, int> = 0);
|
||||
|
||||
/// Request a pointer to an allocation. This is similar to a "write" except the
|
||||
/// memory is uninitialized. Typically used by allocators. If Tp is a class type,
|
||||
/// be sure to use a placement new instead of a memcpy.
|
||||
template <typename Tp>
|
||||
Tp* request();
|
||||
|
||||
/// Request a pointer to an allocation for at least \param n bytes.
|
||||
void* request(size_t n);
|
||||
|
||||
/// Read class-type data from buffer (uses placement new).
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*> read(Tp* out, std::enable_if_t<std::is_class<Tp>::value, int> = 0) const;
|
||||
|
||||
/// Read non-class-type data from buffer (uses memcpy).
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*> read(Tp* out,
|
||||
std::enable_if_t<!std::is_class<Tp>::value, int> = 0) const;
|
||||
|
||||
/// Retrieve a pointer to the head allocation (read).
|
||||
template <typename Tp>
|
||||
Tp* retrieve();
|
||||
|
||||
/// Retrieve a pointer to the head allocation of at least \param n bytes (read).
|
||||
void* retrieve(size_t n);
|
||||
|
||||
/// Returns number of bytes currently held by the buffer.
|
||||
size_t count() const { return (m_write_count - m_read_count); }
|
||||
|
||||
/// Returns how many bytes are availiable in the buffer.
|
||||
size_t free() const { return (m_size - count()); }
|
||||
|
||||
/// Returns if the buffer is empty.
|
||||
bool is_empty() const { return (count() == 0); }
|
||||
|
||||
/// Returns if the buffer is full.
|
||||
bool is_full() const { return (count() == m_size); }
|
||||
|
||||
/// Rewind the read position n bytes
|
||||
size_t rewind(size_t n) const;
|
||||
|
||||
/// explicitly configure to use mmap if avail
|
||||
void set_use_mmap(bool);
|
||||
|
||||
/// query whether using mmap
|
||||
bool get_use_mmap() const { return m_use_mmap; }
|
||||
|
||||
std::string as_string() const;
|
||||
|
||||
void save(std::fstream& _fs);
|
||||
void load(std::fstream& _fs);
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const ring_buffer& obj)
|
||||
{
|
||||
return os << obj.as_string();
|
||||
}
|
||||
|
||||
private:
|
||||
/// Returns the current write pointer.
|
||||
void* write_ptr() const { return static_cast<char*>(m_ptr) + (m_write_count % m_size); }
|
||||
|
||||
/// Returns the current read pointer.
|
||||
void* read_ptr() const { return static_cast<char*>(m_ptr) + (m_read_count % m_size); }
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
bool m_init = false;
|
||||
bool m_use_mmap = true;
|
||||
bool m_use_mmap_explicit = false;
|
||||
void* m_ptr = nullptr;
|
||||
size_t m_size = 0;
|
||||
mutable size_t m_read_count = 0;
|
||||
size_t m_write_count = 0;
|
||||
};
|
||||
//
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*>
|
||||
ring_buffer::write(Tp* in, std::enable_if_t<std::is_class<Tp>::value, int>)
|
||||
{
|
||||
if(in == nullptr || m_ptr == nullptr) return {0, nullptr};
|
||||
|
||||
auto _length = sizeof(Tp);
|
||||
|
||||
// Make sure we don't put in more than there's room for, by writing no
|
||||
// more than there is free.
|
||||
if(_length > free())
|
||||
throw std::runtime_error("heap-buffer-overflow :: ring buffer is full. read data "
|
||||
"to avoid data corruption");
|
||||
|
||||
// if write count is at the tail of buffer, bump to the end of buffer
|
||||
auto _modulo = m_size - (m_write_count % m_size);
|
||||
if(_modulo < _length) m_write_count += _modulo;
|
||||
|
||||
// pointer in buffer
|
||||
Tp* out = reinterpret_cast<Tp*>(write_ptr());
|
||||
|
||||
// Copy in.
|
||||
new((void*) out) Tp{std::move(*in)};
|
||||
|
||||
// Update write count
|
||||
m_write_count += _length;
|
||||
|
||||
return {_length, out};
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*>
|
||||
ring_buffer::write(Tp* in, std::enable_if_t<!std::is_class<Tp>::value, int>)
|
||||
{
|
||||
if(in == nullptr || m_ptr == nullptr) return {0, nullptr};
|
||||
|
||||
auto _length = sizeof(Tp);
|
||||
|
||||
// Make sure we don't put in more than there's room for, by writing no
|
||||
// more than there is free.
|
||||
if(_length > free())
|
||||
throw std::runtime_error("heap-buffer-overflow :: ring buffer is full. read data "
|
||||
"to avoid data corruption");
|
||||
|
||||
// if write count is at the tail of buffer, bump to the end of buffer
|
||||
auto _modulo = m_size - (m_write_count % m_size);
|
||||
if(_modulo < _length) m_write_count += _modulo;
|
||||
|
||||
// pointer in buffer
|
||||
Tp* out = reinterpret_cast<Tp*>(write_ptr());
|
||||
|
||||
// Copy in.
|
||||
memcpy((void*) out, in, _length);
|
||||
|
||||
// Update write count
|
||||
m_write_count += _length;
|
||||
|
||||
return {_length, out};
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
Tp*
|
||||
ring_buffer::request()
|
||||
{
|
||||
if(m_ptr == nullptr) return nullptr;
|
||||
|
||||
auto _length = sizeof(Tp);
|
||||
|
||||
// Make sure we don't put in more than there's room for, by writing no
|
||||
// more than there is free.
|
||||
if(_length > free())
|
||||
throw std::runtime_error("heap-buffer-overflow :: ring buffer is full. read data "
|
||||
"to avoid data corruption");
|
||||
|
||||
// if write count is at the tail of buffer, bump to the end of buffer
|
||||
auto _modulo = m_size - (m_write_count % m_size);
|
||||
if(_modulo < _length) m_write_count += _modulo;
|
||||
|
||||
// pointer in buffer
|
||||
Tp* _out = reinterpret_cast<Tp*>(write_ptr());
|
||||
|
||||
// Update write count
|
||||
m_write_count += _length;
|
||||
|
||||
return _out;
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*>
|
||||
ring_buffer::read(Tp* out, std::enable_if_t<std::is_class<Tp>::value, int>) const
|
||||
{
|
||||
if(is_empty() || out == nullptr) return {0, nullptr};
|
||||
|
||||
auto _length = sizeof(Tp);
|
||||
|
||||
// Make sure we do not read out more than there is actually in the buffer.
|
||||
if(_length > count()) throw std::runtime_error("ring buffer is empty");
|
||||
|
||||
// if read count is at the tail of buffer, bump to the end of buffer
|
||||
auto _modulo = m_size - (m_read_count % m_size);
|
||||
if(_modulo < _length) m_read_count += _modulo;
|
||||
|
||||
// pointer in buffer
|
||||
Tp* in = reinterpret_cast<Tp*>(read_ptr());
|
||||
|
||||
// Copy out for BYTE, nothing magic here.
|
||||
*out = *in;
|
||||
|
||||
// Update read count.
|
||||
m_read_count += _length;
|
||||
|
||||
return {_length, in};
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
std::pair<size_t, Tp*>
|
||||
ring_buffer::read(Tp* out, std::enable_if_t<!std::is_class<Tp>::value, int>) const
|
||||
{
|
||||
if(is_empty() || out == nullptr) return {0, nullptr};
|
||||
|
||||
auto _length = sizeof(Tp);
|
||||
|
||||
using Up = typename std::remove_const<Tp>::type;
|
||||
|
||||
// Make sure we do not read out more than there is actually in the buffer.
|
||||
if(_length > count()) throw std::runtime_error("ring buffer is empty");
|
||||
|
||||
// if read count is at the tail of buffer, bump to the end of buffer
|
||||
auto _modulo = m_size - (m_read_count % m_size);
|
||||
if(_modulo < _length) m_read_count += _modulo;
|
||||
|
||||
// pointer in buffer
|
||||
Tp* in = reinterpret_cast<Tp*>(read_ptr());
|
||||
|
||||
// Copy out for BYTE, nothing magic here.
|
||||
Up* _out = const_cast<Up*>(out);
|
||||
memcpy(_out, in, _length);
|
||||
|
||||
// Update read count.
|
||||
m_read_count += _length;
|
||||
|
||||
return {_length, in};
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
Tp*
|
||||
ring_buffer::retrieve()
|
||||
{
|
||||
if(m_ptr == nullptr) return nullptr;
|
||||
|
||||
auto _length = sizeof(Tp);
|
||||
|
||||
// Make sure we don't put in more than there's room for, by writing no
|
||||
// more than there is free.
|
||||
if(_length > count()) throw std::runtime_error("ring buffer is empty");
|
||||
|
||||
// if read count is at the tail of buffer, bump to the end of buffer
|
||||
auto _modulo = m_size - (m_read_count % m_size);
|
||||
if(_modulo < _length) m_read_count += _modulo;
|
||||
|
||||
// pointer in buffer
|
||||
Tp* _out = reinterpret_cast<Tp*>(read_ptr());
|
||||
|
||||
// Update write count
|
||||
m_read_count += _length;
|
||||
|
||||
return _out;
|
||||
}
|
||||
//
|
||||
} // namespace base
|
||||
///
|
||||
/// \struct rocprofiler::container::ring_buffer
|
||||
/// \brief Ring buffer wrapper around \ref tim::base::ring_buffer for data of type Tp. If
|
||||
/// the data object size is larger than the page size (typically 4KB), behavior is
|
||||
/// undefined. During initialization, one requests a minimum number of objects and the
|
||||
/// buffer will support that number of object + the remainder of the page, e.g. if a page
|
||||
/// is 1000 bytes, the object is 1 byte, and the buffer is requested to support 1500
|
||||
/// objects, then an allocation supporting 2000 objects (i.e. 2 pages) will be created.
|
||||
template <typename Tp>
|
||||
struct ring_buffer : private base::ring_buffer
|
||||
{
|
||||
using base_type = base::ring_buffer;
|
||||
|
||||
static size_t get_items_per_page();
|
||||
|
||||
ring_buffer() = default;
|
||||
~ring_buffer() = default;
|
||||
|
||||
explicit ring_buffer(bool _use_mmap)
|
||||
: base_type{_use_mmap}
|
||||
{}
|
||||
|
||||
explicit ring_buffer(size_t _size)
|
||||
: base_type{_size * sizeof(Tp)}
|
||||
{}
|
||||
|
||||
ring_buffer(size_t _size, bool _use_mmap)
|
||||
: base_type{_size * sizeof(Tp), _use_mmap}
|
||||
{}
|
||||
|
||||
ring_buffer(const ring_buffer&);
|
||||
ring_buffer(ring_buffer&&) noexcept = default;
|
||||
|
||||
ring_buffer& operator=(const ring_buffer&);
|
||||
ring_buffer& operator=(ring_buffer&&) noexcept = default;
|
||||
|
||||
/// Returns whether the buffer has been allocated
|
||||
bool is_initialized() const { return base_type::is_initialized(); }
|
||||
|
||||
/// Get the total number of Tp instances supported
|
||||
size_t capacity() const { return (base_type::capacity()) / sizeof(Tp); }
|
||||
|
||||
/// Creates new ring buffer.
|
||||
void init(size_t _size) { base_type::init(_size * sizeof(Tp)); }
|
||||
|
||||
/// Destroy ring buffer.
|
||||
void destroy() { base_type::destroy(); }
|
||||
|
||||
/// Write data to buffer.
|
||||
size_t data_size() const { return sizeof(Tp); }
|
||||
|
||||
/// Write data to buffer. Return pointer to location of write
|
||||
Tp* write(Tp* in) { return base_type::write<Tp>(in).second; }
|
||||
|
||||
/// Read data from buffer. Return pointer to location of read
|
||||
Tp* read(Tp* out) const { return base_type::read<Tp>(out).second; }
|
||||
|
||||
/// Get an uninitialized address at tail of buffer.
|
||||
Tp* request() { return base_type::request<Tp>(); }
|
||||
|
||||
/// Read data from head of buffer.
|
||||
Tp* retrieve() { return base_type::retrieve<Tp>(); }
|
||||
|
||||
/// Returns number of Tp instances currently held by the buffer.
|
||||
size_t count() const { return (base_type::count()) / sizeof(Tp); }
|
||||
|
||||
/// Returns how many Tp instances are availiable in the buffer.
|
||||
size_t free() const { return (base_type::free()) / sizeof(Tp); }
|
||||
|
||||
/// Returns if the buffer is empty.
|
||||
bool is_empty() const { return base_type::is_empty(); }
|
||||
|
||||
/// Returns if the buffer is full.
|
||||
bool is_full() const { return (base_type::free() < sizeof(Tp)); }
|
||||
|
||||
/// Rewinds the read pointer
|
||||
size_t rewind(size_t n) const { return base_type::rewind(n); }
|
||||
|
||||
template <typename... Args>
|
||||
auto emplace(Args&&... args)
|
||||
{
|
||||
Tp _obj{std::forward<Args>(args)...};
|
||||
return write(&_obj);
|
||||
}
|
||||
|
||||
using base_type::get_use_mmap;
|
||||
using base_type::load;
|
||||
using base_type::save;
|
||||
using base_type::set_use_mmap;
|
||||
|
||||
std::string as_string() const
|
||||
{
|
||||
std::ostringstream ss{};
|
||||
size_t _w = std::log10(base_type::capacity()) + 1;
|
||||
ss << std::boolalpha << std::right << "data size: " << std::setw(_w) << data_size()
|
||||
<< " B, is_initialized: " << std::setw(5) << is_initialized()
|
||||
<< ", is_empty: " << std::setw(5) << is_empty() << ", is_full: " << std::setw(5)
|
||||
<< is_full() << ", capacity: " << std::setw(_w) << capacity()
|
||||
<< ", count: " << std::setw(_w) << count() << ", free: " << std::setw(_w) << free()
|
||||
<< ", raw capacity: " << std::setw(_w) << base_type::capacity()
|
||||
<< " B, raw count: " << std::setw(_w) << base_type::count()
|
||||
<< " B, raw free: " << std::setw(_w) << base_type::free()
|
||||
<< " B, pointer: " << std::setw(15) << base_type::m_ptr
|
||||
<< ", raw read count: " << std::setw(_w) << base_type::m_read_count
|
||||
<< ", raw write count: " << std::setw(_w) << base_type::m_write_count;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const ring_buffer& obj)
|
||||
{
|
||||
return os << obj.as_string();
|
||||
}
|
||||
};
|
||||
//
|
||||
template <typename Tp>
|
||||
size_t
|
||||
ring_buffer<Tp>::get_items_per_page()
|
||||
{
|
||||
return std::max<size_t>(units::get_page_size() / sizeof(Tp), 1);
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
ring_buffer<Tp>::ring_buffer(const ring_buffer<Tp>& rhs)
|
||||
: base_type{rhs}
|
||||
{
|
||||
size_t _n = rhs.count();
|
||||
char* _end = static_cast<char*>(rhs.m_ptr) + rhs.m_size;
|
||||
for(size_t i = 0; i < _n; ++i)
|
||||
{
|
||||
char* _addr = static_cast<char*>(rhs.read_ptr()) + (i * sizeof(Tp));
|
||||
if((_addr + sizeof(Tp)) > _end) _addr = static_cast<char*>(rhs.m_ptr);
|
||||
Tp* _in = static_cast<Tp*>(static_cast<void*>(_addr));
|
||||
write(_in);
|
||||
}
|
||||
}
|
||||
//
|
||||
template <typename Tp>
|
||||
ring_buffer<Tp>&
|
||||
ring_buffer<Tp>::operator=(const ring_buffer<Tp>& rhs)
|
||||
{
|
||||
if(this == &rhs) return *this;
|
||||
|
||||
base_type::operator=(rhs);
|
||||
size_t _n = rhs.count();
|
||||
char* _end = static_cast<char*>(rhs.m_ptr) + rhs.m_size;
|
||||
for(size_t i = 0; i < _n; ++i)
|
||||
{
|
||||
char* _addr = static_cast<char*>(rhs.read_ptr()) + (i * sizeof(Tp));
|
||||
if((_addr + sizeof(Tp)) > _end) _addr = static_cast<char*>(rhs.m_ptr);
|
||||
Tp* _in = static_cast<Tp*>(static_cast<void*>(_addr));
|
||||
write(_in);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
} // namespace container
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,389 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lib/common/container/operators.hpp"
|
||||
#include "lib/common/container/static_vector.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
template <typename Tp, size_t ChunkSizeV = 64>
|
||||
class stable_vector
|
||||
{
|
||||
public:
|
||||
using value_type = Tp;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using size_type = size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
static constexpr const size_t chunk_size = ChunkSizeV;
|
||||
|
||||
private:
|
||||
template <size_t N>
|
||||
struct is_pow2
|
||||
{
|
||||
static constexpr bool value = (N & (N - 1)) == 0;
|
||||
};
|
||||
|
||||
static_assert(ChunkSizeV > 0, "ChunkSize needs to be greater than zero");
|
||||
static_assert(is_pow2<ChunkSizeV>::value, "ChunkSize needs to be a power of 2");
|
||||
|
||||
using this_type = stable_vector<Tp, ChunkSizeV>;
|
||||
using const_this_type = const stable_vector<Tp, ChunkSizeV>;
|
||||
|
||||
template <typename ContainerT>
|
||||
struct iterator_base
|
||||
{
|
||||
iterator_base(ContainerT* c = nullptr, size_type i = 0)
|
||||
: m_container(c)
|
||||
, m_index(i)
|
||||
{}
|
||||
|
||||
iterator_base& operator+=(size_type i)
|
||||
{
|
||||
m_index += i;
|
||||
return *this;
|
||||
}
|
||||
iterator_base& operator-=(size_type i)
|
||||
{
|
||||
m_index -= i;
|
||||
return *this;
|
||||
}
|
||||
iterator_base& operator++()
|
||||
{
|
||||
++m_index;
|
||||
return *this;
|
||||
}
|
||||
iterator_base& operator--()
|
||||
{
|
||||
--m_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
difference_type operator-(const iterator_base& it)
|
||||
{
|
||||
assert(m_container == it.m_container);
|
||||
return m_index - it.m_index;
|
||||
}
|
||||
|
||||
bool operator<(const iterator_base& it) const
|
||||
{
|
||||
assert(m_container == it.m_container);
|
||||
return m_index < it.m_index;
|
||||
}
|
||||
bool operator==(const iterator_base& it) const
|
||||
{
|
||||
return m_container == it.m_container && m_index == it.m_index;
|
||||
}
|
||||
|
||||
protected:
|
||||
ContainerT* m_container;
|
||||
size_type m_index;
|
||||
};
|
||||
|
||||
public:
|
||||
struct const_iterator;
|
||||
|
||||
struct iterator
|
||||
: public iterator_base<this_type>
|
||||
//, std::iterator<std::random_access_iterator_tag, value_type>
|
||||
, public random_access_iterator_helper<iterator, value_type>
|
||||
{
|
||||
using iterator_base<this_type>::iterator_base;
|
||||
friend struct const_iterator;
|
||||
|
||||
reference operator*() { return (*this->m_container)[this->m_index]; }
|
||||
};
|
||||
|
||||
struct const_iterator
|
||||
: public iterator_base<const_this_type>
|
||||
//, std::iterator<std::random_access_iterator_tag, const value_type>
|
||||
, public random_access_iterator_helper<const_iterator, const value_type>
|
||||
{
|
||||
using iterator_base<const_this_type>::iterator_base;
|
||||
|
||||
explicit const_iterator(const iterator& it)
|
||||
: iterator_base<const_this_type>(it.m_container, it.m_index)
|
||||
{}
|
||||
|
||||
const_reference operator*() const { return (*this->m_container)[this->m_index]; }
|
||||
|
||||
bool operator==(const const_iterator& it) const
|
||||
{
|
||||
return iterator_base<const_this_type>::operator==(it);
|
||||
}
|
||||
|
||||
friend bool operator==(const iterator& l, const const_iterator& r) { return r == l; }
|
||||
};
|
||||
|
||||
stable_vector() = default;
|
||||
explicit stable_vector(size_type count, const Tp& value);
|
||||
explicit stable_vector(size_type count);
|
||||
|
||||
template <typename InputItrT,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<typename std::iterator_traits<InputItrT>::iterator_category,
|
||||
std::input_iterator_tag>::value>>
|
||||
stable_vector(InputItrT first, InputItrT last);
|
||||
|
||||
explicit stable_vector(std::initializer_list<Tp>);
|
||||
|
||||
stable_vector(const stable_vector& other);
|
||||
stable_vector(stable_vector&& other) noexcept;
|
||||
|
||||
stable_vector& operator=(stable_vector v);
|
||||
|
||||
iterator begin() noexcept { return {this, 0}; }
|
||||
const_iterator begin() const noexcept { return {this, 0}; }
|
||||
const_iterator cbegin() const noexcept { return begin(); }
|
||||
|
||||
iterator end() noexcept { return {this, size()}; }
|
||||
const_iterator end() const noexcept { return {this, size()}; }
|
||||
const_iterator cend() const noexcept { return end(); }
|
||||
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return empty() ? 0 : (m_chunks.size() - 1) * ChunkSizeV + m_chunks.back()->size();
|
||||
}
|
||||
size_type max_size() const noexcept { return std::numeric_limits<size_type>::max(); }
|
||||
size_type capacity() const noexcept { return m_chunks.size() * ChunkSizeV; }
|
||||
|
||||
bool empty() const noexcept { return m_chunks.size() == 0; }
|
||||
|
||||
void reserve(size_type new_capacity);
|
||||
void shrink_to_fit() noexcept {}
|
||||
|
||||
bool operator==(const this_type& c) const
|
||||
{
|
||||
return size() == c.size() && std::equal(cbegin(), cend(), c.cbegin());
|
||||
}
|
||||
bool operator!=(const this_type& c) const { return !operator==(c); }
|
||||
|
||||
void swap(this_type& v) { std::swap(m_chunks, v.m_chunks); }
|
||||
|
||||
friend void swap(this_type& l, this_type& r) { l.swap(r); }
|
||||
|
||||
reference front() { return m_chunks.front()->front(); }
|
||||
const_reference front() const { return front(); }
|
||||
|
||||
reference back() { return m_chunks.back()->back(); }
|
||||
const_reference back() const { return back(); }
|
||||
|
||||
void push_back(const Tp& t);
|
||||
void push_back(Tp&& t);
|
||||
|
||||
template <typename... Args>
|
||||
void emplace_back(Args&&... args);
|
||||
|
||||
reference operator[](size_type i);
|
||||
|
||||
const_reference operator[](size_type i) const;
|
||||
|
||||
reference at(size_type i);
|
||||
|
||||
const_reference at(size_type i) const;
|
||||
|
||||
private:
|
||||
using chunk_type = container::static_vector<Tp, ChunkSizeV, true>;
|
||||
using storage_type = std::vector<std::unique_ptr<chunk_type>>;
|
||||
|
||||
void add_chunk();
|
||||
chunk_type& last_chunk();
|
||||
|
||||
storage_type m_chunks;
|
||||
};
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(size_type count, const Tp& value)
|
||||
{
|
||||
for(size_type i = 0; i < count; ++i)
|
||||
{
|
||||
push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(size_type count)
|
||||
{
|
||||
for(size_type i = 0; i < count; ++i)
|
||||
{
|
||||
emplace_back();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
template <typename InputItrT, typename>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(InputItrT first, InputItrT last)
|
||||
{
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
push_back(*first);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(const stable_vector& other)
|
||||
{
|
||||
for(const auto& chunk : other.m_chunks)
|
||||
{
|
||||
m_chunks.emplace_back(std::make_unique<chunk_type>(*chunk));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(stable_vector&& other) noexcept
|
||||
: m_chunks(std::move(other.m_chunks))
|
||||
{}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>::stable_vector(std::initializer_list<Tp> ilist)
|
||||
{
|
||||
for(const auto& t : ilist)
|
||||
{
|
||||
push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
stable_vector<Tp, ChunkSizeV>&
|
||||
stable_vector<Tp, ChunkSizeV>::operator=(stable_vector v)
|
||||
{
|
||||
swap(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
void
|
||||
stable_vector<Tp, ChunkSizeV>::add_chunk()
|
||||
{
|
||||
m_chunks.emplace_back(std::make_unique<chunk_type>());
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
typename stable_vector<Tp, ChunkSizeV>::chunk_type&
|
||||
stable_vector<Tp, ChunkSizeV>::last_chunk()
|
||||
{
|
||||
if(ROCPROFILER_UNLIKELY(m_chunks.empty() || m_chunks.back()->size() == ChunkSizeV))
|
||||
{
|
||||
add_chunk();
|
||||
}
|
||||
|
||||
return *m_chunks.back();
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
void
|
||||
stable_vector<Tp, ChunkSizeV>::reserve(size_type new_capacity)
|
||||
{
|
||||
const size_t initial_capacity = capacity();
|
||||
for(difference_type i = new_capacity - initial_capacity; i > 0; i -= ChunkSizeV)
|
||||
{
|
||||
add_chunk();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
void
|
||||
stable_vector<Tp, ChunkSizeV>::push_back(const Tp& t)
|
||||
{
|
||||
last_chunk().push_back(t);
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
void
|
||||
stable_vector<Tp, ChunkSizeV>::push_back(Tp&& t)
|
||||
{
|
||||
last_chunk().push_back(std::move(t));
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
template <typename... Args>
|
||||
void
|
||||
stable_vector<Tp, ChunkSizeV>::emplace_back(Args&&... args)
|
||||
{
|
||||
last_chunk().emplace_back(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
typename stable_vector<Tp, ChunkSizeV>::reference
|
||||
stable_vector<Tp, ChunkSizeV>::operator[](size_type i)
|
||||
{
|
||||
return (*m_chunks[i / ChunkSizeV])[i % ChunkSizeV];
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
typename stable_vector<Tp, ChunkSizeV>::const_reference
|
||||
stable_vector<Tp, ChunkSizeV>::operator[](size_type i) const
|
||||
{
|
||||
return const_cast<this_type&>(*this)[i];
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
typename stable_vector<Tp, ChunkSizeV>::reference
|
||||
stable_vector<Tp, ChunkSizeV>::at(size_type i)
|
||||
{
|
||||
if(ROCPROFILER_UNLIKELY(i >= size()))
|
||||
{
|
||||
throw ::rocprofiler::exception<std::out_of_range>("stable_vector::at(" + std::to_string(i) +
|
||||
"). size is " + std::to_string(size()));
|
||||
}
|
||||
|
||||
return operator[](i);
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV>
|
||||
typename stable_vector<Tp, ChunkSizeV>::const_reference
|
||||
stable_vector<Tp, ChunkSizeV>::at(size_type i) const
|
||||
{
|
||||
return const_cast<this_type&>(*this).at(i);
|
||||
}
|
||||
|
||||
template <typename Tp, size_t ChunkSizeV, typename... Args>
|
||||
auto
|
||||
resize(stable_vector<Tp, ChunkSizeV>& _v, size_t _n, Args&&... args)
|
||||
{
|
||||
if(_n > _v.capacity()) _v.reserve(_n);
|
||||
|
||||
while(_v.size() < _n)
|
||||
_v.emplace_back(std::forward<Args>(args)...);
|
||||
|
||||
return _v.size();
|
||||
}
|
||||
} // namespace container
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,221 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lib/common/container/c_array.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstdlib>
|
||||
#include <initializer_list>
|
||||
#include <cstddef>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
template <typename Tp, size_t N, bool AtomicSizeV = false>
|
||||
struct static_vector
|
||||
{
|
||||
using count_type = std::conditional_t<AtomicSizeV, std::atomic<size_t>, size_t>;
|
||||
using this_type = static_vector<Tp, N>;
|
||||
using value_type = Tp;
|
||||
|
||||
static_vector() = default;
|
||||
static_vector(const static_vector&) = default;
|
||||
static_vector(static_vector&&) noexcept = default;
|
||||
static_vector& operator=(const static_vector&) = default;
|
||||
static_vector& operator=(static_vector&&) noexcept = default;
|
||||
|
||||
explicit static_vector(size_t _n, Tp _v = {});
|
||||
explicit static_vector(c_array<Tp>&&);
|
||||
|
||||
template <size_t M>
|
||||
explicit static_vector(std::array<Tp, M>&&);
|
||||
|
||||
static_vector& operator=(std::initializer_list<Tp>&& _v);
|
||||
static_vector& operator=(std::pair<std::array<Tp, N>, size_t>&&);
|
||||
|
||||
template <typename... Args>
|
||||
value_type& emplace_back(Args&&... _v);
|
||||
|
||||
template <typename Up>
|
||||
decltype(auto) push_back(Up&& _v)
|
||||
{
|
||||
return emplace_back(Tp{std::forward<Up>(_v)});
|
||||
}
|
||||
|
||||
void pop_back() { --m_size; }
|
||||
|
||||
void clear();
|
||||
void reserve(size_t) noexcept {}
|
||||
void shrink_to_fit() noexcept {}
|
||||
auto capacity() noexcept { return N; }
|
||||
|
||||
size_t size() const { return m_size; }
|
||||
bool empty() const { return (size() == 0); }
|
||||
|
||||
auto begin() { return m_data.begin(); }
|
||||
auto begin() const { return m_data.begin(); }
|
||||
auto cbegin() const { return m_data.cbegin(); }
|
||||
|
||||
auto end() { return m_data.begin() + size(); }
|
||||
auto end() const { return m_data.begin() + size(); }
|
||||
auto cend() const { return m_data.cbegin() + size(); }
|
||||
|
||||
decltype(auto) operator[](size_t _idx) { return m_data[_idx]; }
|
||||
decltype(auto) operator[](size_t _idx) const { return m_data[_idx]; }
|
||||
|
||||
decltype(auto) at(size_t _idx) { return m_data.at(_idx); }
|
||||
decltype(auto) at(size_t _idx) const { return m_data.at(_idx); }
|
||||
|
||||
decltype(auto) front() { return m_data.front(); }
|
||||
decltype(auto) front() const { return m_data.front(); }
|
||||
decltype(auto) back() { return *(m_data.begin() + size() - 1); }
|
||||
decltype(auto) back() const { return *(m_data.begin() + size() - 1); }
|
||||
|
||||
auto* data() { return m_data.data(); }
|
||||
const auto* data() const { return m_data.data(); }
|
||||
|
||||
void swap(this_type& _v);
|
||||
|
||||
friend void swap(this_type& _lhs, this_type& _rhs) { _lhs.swap(_rhs); }
|
||||
|
||||
private:
|
||||
void update_size(size_t);
|
||||
|
||||
private:
|
||||
count_type m_size = count_type{0};
|
||||
std::array<Tp, N> m_data = {};
|
||||
};
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
static_vector<Tp, N, AtomicSizeV>::static_vector(size_t _n, Tp _v)
|
||||
{
|
||||
m_data.fill(_v);
|
||||
update_size(_n);
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
static_vector<Tp, N, AtomicSizeV>::static_vector(c_array<Tp>&& _v)
|
||||
{
|
||||
auto _n = std::min<size_t>(N, _v.size());
|
||||
for(size_t i = 0; i < _n; ++i, ++m_size)
|
||||
m_data[i] = _v[i];
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
template <size_t M>
|
||||
static_vector<Tp, N, AtomicSizeV>::static_vector(std::array<Tp, M>&& _v)
|
||||
{
|
||||
auto _n = std::min<size_t>(N, M);
|
||||
for(size_t i = 0; i < _n; ++i, ++m_size)
|
||||
m_data[i] = _v[i];
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
static_vector<Tp, N, AtomicSizeV>&
|
||||
static_vector<Tp, N, AtomicSizeV>::operator=(std::initializer_list<Tp>&& _v)
|
||||
{
|
||||
if(ROCPROFILER_UNLIKELY(_v.size() > N))
|
||||
{
|
||||
throw exception<std::out_of_range>(
|
||||
std::string{"static_vector::operator=(initializer_list) size > "} + std::to_string(N));
|
||||
}
|
||||
|
||||
clear();
|
||||
for(auto&& itr : _v)
|
||||
m_data[m_size++] = itr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
static_vector<Tp, N, AtomicSizeV>&
|
||||
static_vector<Tp, N, AtomicSizeV>::operator=(std::pair<std::array<Tp, N>, size_t>&& _v)
|
||||
{
|
||||
update_size(0);
|
||||
m_data = std::move(_v.first);
|
||||
update_size(_v.second);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
void
|
||||
static_vector<Tp, N, AtomicSizeV>::clear()
|
||||
{
|
||||
update_size(0);
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
void
|
||||
static_vector<Tp, N, AtomicSizeV>::swap(this_type& _v)
|
||||
{
|
||||
if constexpr(AtomicSizeV)
|
||||
{
|
||||
auto _t_size = m_size;
|
||||
auto _v_size = _v.m_size;
|
||||
std::swap(m_data, _v.m_data);
|
||||
update_size(_v_size);
|
||||
_v.update_size(_t_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::swap(m_size, _v.m_size);
|
||||
std::swap(m_data, _v.m_data);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
template <typename... Args>
|
||||
Tp&
|
||||
static_vector<Tp, N, AtomicSizeV>::emplace_back(Args&&... _v)
|
||||
{
|
||||
auto _idx = m_size++;
|
||||
if(_idx >= N)
|
||||
{
|
||||
throw exception<std::out_of_range>(
|
||||
std::string{"static_vector::emplace_back - reached capacity "} + std::to_string(N));
|
||||
}
|
||||
|
||||
if constexpr(std::is_assignable<Tp, decltype(std::forward<Args>(_v))...>::value)
|
||||
m_data[_idx] = {std::forward<Args>(_v)...};
|
||||
else
|
||||
m_data[_idx] = Tp{std::forward<Args>(_v)...};
|
||||
return m_data[_idx];
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N, bool AtomicSizeV>
|
||||
void
|
||||
static_vector<Tp, N, AtomicSizeV>::update_size(size_t _n)
|
||||
{
|
||||
if constexpr(AtomicSizeV)
|
||||
m_size.store(_n);
|
||||
else
|
||||
m_size = _n;
|
||||
}
|
||||
} // namespace container
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2018-2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ROCPROFILER_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
|
||||
#define ROCPROFILER_VISIBILITY(MODE) ROCPROFILER_ATTRIBUTE(visibility(MODE))
|
||||
#define ROCPROFILER_PUBLIC_API ROCPROFILER_VISIBILITY("default")
|
||||
#define ROCPROFILER_HIDDEN_API ROCPROFILER_VISIBILITY("hidden")
|
||||
#define ROCPROFILER_INTERNAL_API ROCPROFILER_VISIBILITY("internal")
|
||||
#define ROCPROFILER_INLINE ROCPROFILER_ATTRIBUTE(always_inline) inline
|
||||
#define ROCPROFILER_NOINLINE ROCPROFILER_ATTRIBUTE(noinline)
|
||||
#define ROCPROFILER_HOT ROCPROFILER_ATTRIBUTE(hot)
|
||||
#define ROCPROFILER_COLD ROCPROFILER_ATTRIBUTE(cold)
|
||||
#define ROCPROFILER_CONST ROCPROFILER_ATTRIBUTE(const)
|
||||
#define ROCPROFILER_PURE ROCPROFILER_ATTRIBUTE(pure)
|
||||
#define ROCPROFILER_WEAK ROCPROFILER_ATTRIBUTE(weak)
|
||||
#define ROCPROFILER_PACKED ROCPROFILER_ATTRIBUTE(__packed__)
|
||||
#define ROCPROFILER_PACKED_ALIGN(VAL) ROCPROFILER_PACKED ROCPROFILER_ATTRIBUTE(__aligned__(VAL))
|
||||
#define ROCPROFILER_LIKELY(...) __builtin_expect((__VA_ARGS__), 1)
|
||||
#define ROCPROFILER_UNLIKELY(...) __builtin_expect((__VA_ARGS__), 0)
|
||||
|
||||
#if defined(ROCPROFILER_CI) && ROCPROFILER_CI > 0
|
||||
# if defined(NDEBUG)
|
||||
# undef NDEBUG
|
||||
# endif
|
||||
# if !defined(DEBUG)
|
||||
# define DEBUG 1
|
||||
# endif
|
||||
# if defined(__cplusplus)
|
||||
# include <cassert>
|
||||
# else
|
||||
# include <assert.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define ROCPROFILER_STRINGIZE(X) ROCPROFILER_STRINGIZE2(X)
|
||||
#define ROCPROFILER_STRINGIZE2(X) #X
|
||||
#define ROCPROFILER_VAR_NAME_COMBINE(X, Y) X##Y
|
||||
#define ROCPROFILER_VARIABLE(X, Y) ROCPROFILER_VAR_NAME_COMBINE(X, Y)
|
||||
#define ROCPROFILER_LINESTR ROCPROFILER_STRINGIZE(__LINE__)
|
||||
#define ROCPROFILER_ESC(...) __VA_ARGS__
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# if !defined(ROCPROFILER_FOLD_EXPRESSION)
|
||||
# define ROCPROFILER_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
|
||||
# endif
|
||||
#endif
|
||||
@@ -0,0 +1,185 @@
|
||||
// Copyright (c) 2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lib/common/log.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(ROCPROFILER_ENVIRON_LOG_NAME)
|
||||
# if defined(ROCPROFILER_COMMON_LIBRARY_NAME)
|
||||
# define ROCPROFILER_ENVIRON_LOG_NAME "[" ROCPROFILER_COMMON_LIBRARY_NAME "]"
|
||||
# else
|
||||
# define ROCPROFILER_ENVIRON_LOG_NAME "[environ]"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(ROCPROFILER_ENVIRON_LOG_START)
|
||||
# if defined(ROCPROFILER_COMMON_LIBRARY_LOG_START)
|
||||
# define ROCPROFILER_ENVIRON_LOG_START ROCPROFILER_COMMON_LIBRARY_LOG_START
|
||||
# elif defined(ROCPROFILER_LOG_COLORS_AVAILABLE)
|
||||
# define ROCPROFILER_ENVIRON_LOG_START \
|
||||
fprintf(stderr, "%s", ::rocprofiler::common::log::color::dmesg());
|
||||
# else
|
||||
# define ROCPROFILER_ENVIRON_LOG_START
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(ROCPROFILER_ENVIRON_LOG_END)
|
||||
# if defined(ROCPROFILER_COMMON_LIBRARY_LOG_END)
|
||||
# define ROCPROFILER_ENVIRON_LOG_END ROCPROFILER_COMMON_LIBRARY_LOG_END
|
||||
# elif defined(ROCPROFILER_LOG_COLORS_AVAILABLE)
|
||||
# define ROCPROFILER_ENVIRON_LOG_END \
|
||||
fprintf(stderr, "%s", ::rocprofiler::common::log::color::dmesg());
|
||||
# else
|
||||
# define ROCPROFILER_ENVIRON_LOG_END
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define ROCPROFILER_ENVIRON_LOG(CONDITION, ...) \
|
||||
if(CONDITION) \
|
||||
{ \
|
||||
fflush(stderr); \
|
||||
ROCPROFILER_ENVIRON_LOG_START \
|
||||
fprintf(stderr, "[rocprofiler]" ROCPROFILER_ENVIRON_LOG_NAME "[%i] ", getpid()); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
ROCPROFILER_ENVIRON_LOG_END \
|
||||
fflush(stderr); \
|
||||
}
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace
|
||||
{
|
||||
inline std::string
|
||||
get_env_impl(std::string_view env_id, std::string_view _default)
|
||||
{
|
||||
if(env_id.empty()) return std::string{_default};
|
||||
char* env_var = ::std::getenv(env_id.data());
|
||||
if(env_var) return std::string{env_var};
|
||||
return std::string{_default};
|
||||
}
|
||||
|
||||
inline std::string
|
||||
get_env_impl(std::string_view env_id, const char* _default)
|
||||
{
|
||||
return get_env_impl(env_id, std::string_view{_default});
|
||||
}
|
||||
|
||||
inline int
|
||||
get_env_impl(std::string_view env_id, int _default)
|
||||
{
|
||||
if(env_id.empty()) return _default;
|
||||
char* env_var = ::std::getenv(env_id.data());
|
||||
if(env_var)
|
||||
{
|
||||
try
|
||||
{
|
||||
return std::stoi(env_var);
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[rocprofiler][get_env] Exception thrown converting getenv(\"%s\") = "
|
||||
"%s to integer :: %s. Using default value of %i\n",
|
||||
env_id.data(),
|
||||
env_var,
|
||||
_e.what(),
|
||||
_default);
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
|
||||
inline bool
|
||||
get_env_impl(std::string_view env_id, bool _default)
|
||||
{
|
||||
if(env_id.empty()) return _default;
|
||||
char* env_var = ::std::getenv(env_id.data());
|
||||
if(env_var)
|
||||
{
|
||||
if(std::string_view{env_var}.empty())
|
||||
{
|
||||
throw std::runtime_error(std::string{"No boolean value provided for "} +
|
||||
std::string{env_id});
|
||||
}
|
||||
|
||||
if(std::string_view{env_var}.find_first_not_of("0123456789") == std::string_view::npos)
|
||||
{
|
||||
return static_cast<bool>(std::stoi(env_var));
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < strlen(env_var); ++i)
|
||||
env_var[i] = tolower(env_var[i]);
|
||||
for(const auto& itr : {"off", "false", "no", "n", "f", "0"})
|
||||
if(strcmp(env_var, itr) == 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename Tp>
|
||||
inline auto
|
||||
get_env(std::string_view env_id, Tp&& _default)
|
||||
{
|
||||
if constexpr(std::is_enum<Tp>::value)
|
||||
{
|
||||
using Up = std::underlying_type_t<Tp>;
|
||||
// cast to underlying type -> get_env -> cast to enum type
|
||||
return static_cast<Tp>(get_env_impl(env_id, static_cast<Up>(_default)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_env_impl(env_id, std::forward<Tp>(_default));
|
||||
}
|
||||
}
|
||||
|
||||
struct env_config
|
||||
{
|
||||
std::string env_name = {};
|
||||
std::string env_value = {};
|
||||
int override = 0;
|
||||
|
||||
auto operator()(bool _verbose = false) const
|
||||
{
|
||||
if(env_name.empty()) return -1;
|
||||
ROCPROFILER_ENVIRON_LOG(_verbose,
|
||||
"setenv(\"%s\", \"%s\", %i)\n",
|
||||
env_name.c_str(),
|
||||
env_value.c_str(),
|
||||
override);
|
||||
return setenv(env_name.c_str(), env_value.c_str(), override);
|
||||
}
|
||||
};
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,373 @@
|
||||
/* Copyright (c) 2022 Advanced Micro Devices, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE. */
|
||||
|
||||
#include "lib/common/helper.hpp"
|
||||
|
||||
#include <amd_comgr/amd_comgr.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <cxxabi.h>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#define ENABLE_BACKTRACE
|
||||
#if defined(ENABLE_BACKTRACE)
|
||||
# include <backtrace.h>
|
||||
#endif
|
||||
|
||||
#define amd_comgr_(call) \
|
||||
do \
|
||||
{ \
|
||||
if(amd_comgr_status_t status = amd_comgr_##call; status != AMD_COMGR_STATUS_SUCCESS) \
|
||||
{ \
|
||||
const char* reason = ""; \
|
||||
amd_comgr_status_string(status, &reason); \
|
||||
fprintf(stderr, #call " failed: %s\n", reason); \
|
||||
abort(); \
|
||||
} \
|
||||
} while(false)
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
std::string
|
||||
cxa_demangle(std::string_view _mangled_name, int* _status)
|
||||
{
|
||||
constexpr size_t buffer_len = 4096;
|
||||
// return the mangled since there is no buffer
|
||||
if(_mangled_name.empty())
|
||||
{
|
||||
*_status = -2;
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
auto _demangled_name = std::string{_mangled_name};
|
||||
|
||||
// PARAMETERS to __cxa_demangle
|
||||
// mangled_name:
|
||||
// A NULL-terminated character string containing the name to be demangled.
|
||||
// buffer:
|
||||
// A region of memory, allocated with malloc, of *length bytes, into which the
|
||||
// demangled name is stored. If output_buffer is not long enough, it is expanded
|
||||
// using realloc. output_buffer may instead be NULL; in that case, the demangled
|
||||
// name is placed in a region of memory allocated with malloc.
|
||||
// _buflen:
|
||||
// If length is non-NULL, the length of the buffer containing the demangled name
|
||||
// is placed in *length.
|
||||
// status:
|
||||
// *status is set to one of the following values
|
||||
size_t _demang_len = 0;
|
||||
char* _demang = abi::__cxa_demangle(_demangled_name.c_str(), nullptr, &_demang_len, _status);
|
||||
switch(*_status)
|
||||
{
|
||||
// 0 : The demangling operation succeeded.
|
||||
// -1 : A memory allocation failure occurred.
|
||||
// -2 : mangled_name is not a valid name under the C++ ABI mangling rules.
|
||||
// -3 : One of the arguments is invalid.
|
||||
case 0:
|
||||
{
|
||||
if(_demang) _demangled_name = std::string{_demang};
|
||||
break;
|
||||
}
|
||||
case -1:
|
||||
{
|
||||
char _msg[buffer_len];
|
||||
::memset(_msg, '\0', buffer_len * sizeof(char));
|
||||
::snprintf(_msg,
|
||||
buffer_len,
|
||||
"memory allocation failure occurred demangling %s",
|
||||
_demangled_name.c_str());
|
||||
::perror(_msg);
|
||||
break;
|
||||
}
|
||||
case -2: break;
|
||||
case -3:
|
||||
{
|
||||
char _msg[buffer_len];
|
||||
::memset(_msg, '\0', buffer_len * sizeof(char));
|
||||
::snprintf(_msg,
|
||||
buffer_len,
|
||||
"Invalid argument in: (\"%s\", nullptr, nullptr, %p)",
|
||||
_demangled_name.c_str(),
|
||||
(void*) _status);
|
||||
::perror(_msg);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
};
|
||||
|
||||
// if it "demangled" but the length is zero, set the status to -2
|
||||
if(_demang_len == 0 && *_status == 0) *_status = -2;
|
||||
|
||||
// free allocated buffer
|
||||
::free(_demang);
|
||||
return _demangled_name;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
#if defined(ENABLE_BACKTRACE)
|
||||
|
||||
// struct BackTraceInfo
|
||||
// {
|
||||
// struct ::backtrace_state* state = nullptr;
|
||||
// std::stringstream sstream{};
|
||||
// int depth = 0;
|
||||
// int error = 0;
|
||||
// };
|
||||
|
||||
// void
|
||||
// errorCallback(void* data, const char* message, int errnum)
|
||||
// {
|
||||
// BackTraceInfo* info = static_cast<BackTraceInfo*>(data);
|
||||
// info->sstream << "ROCProfiler: error: " << message << '(' << errnum << ')';
|
||||
// info->error = 1;
|
||||
// }
|
||||
|
||||
// void
|
||||
// syminfoCallback(void* data,
|
||||
// uintptr_t /* pc */,
|
||||
// const char* symname,
|
||||
// uintptr_t /* symval */,
|
||||
// uintptr_t /* symsize */)
|
||||
// {
|
||||
// BackTraceInfo* info = static_cast<BackTraceInfo*>(data);
|
||||
|
||||
// if(symname == nullptr) return;
|
||||
|
||||
// int status = 0;
|
||||
// auto&& _demangled = cxa_demangle(symname, &status);
|
||||
// info->sstream << ' '
|
||||
// << (status == 0 ? std::string_view{_demangled} : std::string_view{symname});
|
||||
// }
|
||||
|
||||
// int
|
||||
// fullCallback(void* data, uintptr_t pc, const char* filename, int lineno, const char* function)
|
||||
// {
|
||||
// BackTraceInfo* info = static_cast<BackTraceInfo*>(data);
|
||||
|
||||
// info->sstream << std::endl
|
||||
// << " #" << std::dec << info->depth++ << ' ' << "0x" << std::noshowbase
|
||||
// << std::hex << std::setfill('0') << std::setw(sizeof(pc) * 2) << pc;
|
||||
// if(function == nullptr)
|
||||
// {
|
||||
// backtrace_syminfo(info->state, pc, syminfoCallback, errorCallback, data);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// int status = 0;
|
||||
// auto&& _demangled = cxa_demangle(function, &status);
|
||||
// info->sstream << ' '
|
||||
// << (status == 0 ? std::string_view{_demangled} :
|
||||
// std::string_view{function});
|
||||
|
||||
// if(filename != nullptr)
|
||||
// {
|
||||
// info->sstream << " in " << filename;
|
||||
// if(lineno != 0) info->sstream << ':' << std::dec << lineno;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return info->error;
|
||||
// }
|
||||
#endif // defined (ENABLE_BACKTRACE)
|
||||
} // namespace
|
||||
|
||||
/* The function extracts the kernel name from
|
||||
input string. By using the iterators it finds the
|
||||
window in the string which contains only the kernel name.
|
||||
For example 'Foo<int, float>::foo(a[], int (int))' -> 'foo'*/
|
||||
std::string
|
||||
truncate_name(std::string_view name)
|
||||
{
|
||||
auto rit = name.rbegin();
|
||||
auto rend = name.rend();
|
||||
uint32_t counter = 0;
|
||||
char open_token = 0;
|
||||
char close_token = 0;
|
||||
while(rit != rend)
|
||||
{
|
||||
if(counter == 0)
|
||||
{
|
||||
switch(*rit)
|
||||
{
|
||||
case ')':
|
||||
counter = 1;
|
||||
open_token = ')';
|
||||
close_token = '(';
|
||||
break;
|
||||
case '>':
|
||||
counter = 1;
|
||||
open_token = '>';
|
||||
close_token = '<';
|
||||
break;
|
||||
case ']':
|
||||
counter = 1;
|
||||
open_token = ']';
|
||||
close_token = '[';
|
||||
break;
|
||||
case ' ': ++rit; continue;
|
||||
}
|
||||
if(counter == 0) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(*rit == open_token) counter++;
|
||||
if(*rit == close_token) counter--;
|
||||
}
|
||||
++rit;
|
||||
}
|
||||
auto rbeg = rit;
|
||||
while((rit != rend) && (*rit != ' ') && (*rit != ':'))
|
||||
rit++;
|
||||
return std::string{name.substr(rend - rit, rit - rbeg)};
|
||||
}
|
||||
|
||||
// C++ symbol demangle
|
||||
std::string
|
||||
cxx_demangle(std::string_view symbol)
|
||||
{
|
||||
int _status = 0;
|
||||
auto demangled_str = cxa_demangle(symbol, &_status);
|
||||
if(_status == 0)
|
||||
{
|
||||
return demangled_str;
|
||||
}
|
||||
|
||||
amd_comgr_data_t mangled_data;
|
||||
amd_comgr_(create_data(AMD_COMGR_DATA_KIND_BYTES, &mangled_data));
|
||||
amd_comgr_(set_data(mangled_data, symbol.size(), symbol.data()));
|
||||
|
||||
amd_comgr_data_t demangled_data;
|
||||
amd_comgr_(demangle_symbol_name(mangled_data, &demangled_data));
|
||||
|
||||
size_t demangled_size = 0;
|
||||
amd_comgr_(get_data(demangled_data, &demangled_size, nullptr));
|
||||
|
||||
demangled_str.resize(demangled_size);
|
||||
amd_comgr_(get_data(demangled_data, &demangled_size, demangled_str.data()));
|
||||
|
||||
amd_comgr_(release_data(mangled_data));
|
||||
amd_comgr_(release_data(demangled_data));
|
||||
return demangled_str;
|
||||
}
|
||||
|
||||
// check if string has special char
|
||||
bool
|
||||
has_special_char(std::string_view str)
|
||||
{
|
||||
return std::find_if(str.begin(), str.end(), [](unsigned char ch) {
|
||||
return !((isalnum(ch) != 0) || ch == '_' || ch == ':' || ch == ' ');
|
||||
}) != str.end();
|
||||
}
|
||||
|
||||
// check if string has correct counter format
|
||||
bool
|
||||
has_counter_format(std::string_view str)
|
||||
{
|
||||
return std::find_if(str.begin(), str.end(), [](unsigned char ch) {
|
||||
return ((isalnum(ch) != 0) || ch == '_');
|
||||
}) != str.end();
|
||||
}
|
||||
|
||||
// trims the begining of the line for spaces
|
||||
std::string
|
||||
left_trim(std::string_view s)
|
||||
{
|
||||
constexpr std::string_view WHITESPACE = " \n\r\t\f\v";
|
||||
size_t start = s.find_first_not_of(WHITESPACE);
|
||||
if(start == std::string_view::npos) return std::string{};
|
||||
return std::string{s.substr(start)};
|
||||
}
|
||||
|
||||
// trims begining and end of input line in place
|
||||
void
|
||||
trim(std::string& str)
|
||||
{
|
||||
// Remove leading spaces.
|
||||
str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](unsigned char ch) {
|
||||
return std::isspace(ch) == 0;
|
||||
}));
|
||||
// Remove trailing spaces.
|
||||
str.erase(std::find_if(
|
||||
str.rbegin(), str.rend(), [](unsigned char ch) { return std::isspace(ch) == 0; })
|
||||
.base(),
|
||||
str.end());
|
||||
}
|
||||
|
||||
// replace unsuported specail chars with space
|
||||
static void
|
||||
handle_special_chars(std::string& str)
|
||||
{
|
||||
std::set<char> specialChars = {'!', '@', '#', '$', '%', '&', '(', ')', ',',
|
||||
'*', '+', '-', '.', '/', ';', '<', '=', '>',
|
||||
'?', '@', '{', '}', '^', '`', '~', '|', ':'};
|
||||
|
||||
// Iterate over the string and replace any special characters with a space.
|
||||
for(char& i : str)
|
||||
{
|
||||
if(specialChars.find(i) != specialChars.end())
|
||||
{
|
||||
i = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validate input coutners and correct format if needed
|
||||
void
|
||||
validate_counters_format(std::vector<std::string>& counters, std::string line)
|
||||
{
|
||||
// trim line for any white spaces
|
||||
trim(line);
|
||||
|
||||
if(!(line[0] == '#' || line.find("pmc") == std::string::npos))
|
||||
{
|
||||
handle_special_chars(line);
|
||||
|
||||
std::stringstream input_line(line);
|
||||
std::string counter;
|
||||
while(getline(input_line, counter, ' '))
|
||||
{
|
||||
if(counter.substr(0, 3) != "pmc" && has_counter_format(counter))
|
||||
{
|
||||
counters.push_back(counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// raise exception with correct usage if user still managed to corrupt input
|
||||
for(const auto& itr : counters)
|
||||
{
|
||||
if(!has_counter_format(itr))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[rocprofiler] Bad input metric. usage --> pmc: <counter1> <counter2>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,68 @@
|
||||
/* Copyright (c) 2022 Advanced Micro Devices, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cxxabi.h>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
[[nodiscard]] std::string
|
||||
cxa_demangle(std::string_view _mangled_name, int* _status) __attribute__((nonnull(2)));
|
||||
|
||||
/* The function extracts the kernel name from
|
||||
input string. By using the iterators it finds the
|
||||
window in the string which contains only the kernel name.
|
||||
For example 'Foo<int, float>::foo(a[], int (int))' -> 'foo'*/
|
||||
std::string
|
||||
truncate_name(std::string_view name);
|
||||
|
||||
// C++ symbol demangle
|
||||
std::string
|
||||
cxx_demangle(std::string_view symbol);
|
||||
|
||||
// check if string has special char
|
||||
bool
|
||||
has_special_char(std::string_view str);
|
||||
|
||||
// check if string has correct counter format
|
||||
bool
|
||||
has_counter_format(std::string_view str);
|
||||
|
||||
// trims the begining of the line for spaces
|
||||
std::string
|
||||
left_trim(std::string_view s);
|
||||
|
||||
// validates pmc user input format
|
||||
void
|
||||
validate_counters_format(std::vector<std::string>& counters, std::string line);
|
||||
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,183 @@
|
||||
// Copyright (c) 2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <initializer_list>
|
||||
#include <ios>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#if !defined(ROCPROFILER_FOLD_EXPRESSION)
|
||||
# define ROCPROFILER_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
|
||||
#endif
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <typename Tp>
|
||||
struct is_string_impl : std::false_type
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct is_string_impl<std::string> : std::true_type
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct is_string_impl<std::string_view> : std::true_type
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct is_string_impl<const char*> : std::true_type
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct is_string_impl<char*> : std::true_type
|
||||
{};
|
||||
|
||||
template <typename Tp>
|
||||
struct is_string : is_string_impl<std::remove_cv_t<std::decay_t<Tp>>>
|
||||
{};
|
||||
|
||||
template <typename ArgT>
|
||||
auto
|
||||
as_string(ArgT&& _v, std::enable_if_t<is_string<ArgT>::value, int> = 0)
|
||||
{
|
||||
if constexpr(std::is_pointer<std::decay_t<ArgT>>::value)
|
||||
{
|
||||
return (_v == nullptr) ? std::string{"\"\""} : (std::string{"\""} + _v + std::string{"\""});
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::string{"\""} + _v + std::string{"\""};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ArgT>
|
||||
auto
|
||||
as_string(ArgT&& _v, std::enable_if_t<!is_string<ArgT>::value, long> = 0)
|
||||
{
|
||||
return _v;
|
||||
}
|
||||
|
||||
template <typename DelimT, typename... Args>
|
||||
auto
|
||||
join(DelimT&& _delim, Args&&... _args)
|
||||
{
|
||||
using delim_type = std::remove_cv_t<std::remove_reference_t<DelimT>>;
|
||||
|
||||
std::stringstream _ss{};
|
||||
_ss << std::boolalpha;
|
||||
|
||||
if constexpr(std::is_same<delim_type, char>::value)
|
||||
{
|
||||
const char _delim_c[2] = {_delim, '\0'};
|
||||
ROCPROFILER_FOLD_EXPRESSION(_ss << _delim_c << _args);
|
||||
auto _ret = _ss.str();
|
||||
return (_ret.length() > 1) ? _ret.substr(1) : std::string{};
|
||||
}
|
||||
else
|
||||
{
|
||||
ROCPROFILER_FOLD_EXPRESSION(_ss << _delim << _args);
|
||||
auto _ret = _ss.str();
|
||||
auto&& _len = std::string{_delim}.length();
|
||||
return (_ret.length() > _len) ? _ret.substr(_len) : std::string{};
|
||||
}
|
||||
}
|
||||
|
||||
struct QuoteStrings
|
||||
{};
|
||||
|
||||
template <typename DelimT, typename... Args>
|
||||
auto
|
||||
join(QuoteStrings&&, DelimT&& _delim, Args&&... _args)
|
||||
{
|
||||
using delim_type = std::remove_cv_t<std::remove_reference_t<DelimT>>;
|
||||
|
||||
std::stringstream _ss{};
|
||||
_ss << std::boolalpha;
|
||||
|
||||
if constexpr(std::is_same<delim_type, char>::value)
|
||||
{
|
||||
const char _delim_c[2] = {_delim, '\0'};
|
||||
ROCPROFILER_FOLD_EXPRESSION(_ss << _delim_c << as_string(_args));
|
||||
auto _ret = _ss.str();
|
||||
return (_ret.length() > 1) ? _ret.substr(1) : std::string{};
|
||||
}
|
||||
else
|
||||
{
|
||||
ROCPROFILER_FOLD_EXPRESSION(_ss << _delim << as_string(_args));
|
||||
auto _ret = _ss.str();
|
||||
auto&& _len = std::string{_delim}.length();
|
||||
return (_ret.length() > _len) ? _ret.substr(_len) : std::string{};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto
|
||||
join(std::array<std::string_view, 3>&& _delim, Args&&... _args)
|
||||
{
|
||||
return join("",
|
||||
std::get<0>(_delim),
|
||||
join(std::get<1>(_delim), std::forward<Args>(_args)...),
|
||||
std::get<2>(_delim));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto
|
||||
join(QuoteStrings&&, std::array<std::string_view, 3>&& _delim, Args&&... _args)
|
||||
{
|
||||
return join(QuoteStrings{},
|
||||
"",
|
||||
std::get<0>(_delim),
|
||||
join(std::get<1>(_delim), std::forward<Args>(_args)...),
|
||||
std::get<2>(_delim));
|
||||
}
|
||||
|
||||
template <typename DelimB, typename DelimT, typename DelimE, typename... Args>
|
||||
auto
|
||||
join(std::tuple<DelimB, DelimT, DelimE>&& _delim, Args&&... _args)
|
||||
{
|
||||
return join("",
|
||||
std::get<0>(_delim),
|
||||
join(std::get<1>(_delim), std::forward<Args>(_args)...),
|
||||
std::get<2>(_delim));
|
||||
}
|
||||
|
||||
template <typename DelimB, typename DelimT, typename DelimE, typename... Args>
|
||||
auto
|
||||
join(QuoteStrings&&, std::tuple<DelimB, DelimT, DelimE>&& _delim, Args&&... _args)
|
||||
{
|
||||
return join(QuoteStrings{},
|
||||
"",
|
||||
std::get<0>(_delim),
|
||||
join(std::get<1>(_delim), std::forward<Args>(_args)...),
|
||||
std::get<2>(_delim));
|
||||
}
|
||||
} // namespace
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,140 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR rhs
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR rhsWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR rhs DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ROCPROFILER_LOG_COLORS_AVAILABLE
|
||||
# define ROCPROFILER_LOG_COLORS_AVAILABLE 1
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace log
|
||||
{
|
||||
bool&
|
||||
monochrome();
|
||||
|
||||
inline bool&
|
||||
monochrome()
|
||||
{
|
||||
static bool _v = []() {
|
||||
auto _val = false;
|
||||
const char* _env_cstr = nullptr;
|
||||
#if defined(ROCPROFILER_LOG_COLORS_ENV)
|
||||
_env_cstr = std::getenv(ROCPROFILER_LOG_COLORS_ENV);
|
||||
#elif defined(ROCPROFILER_PROJECT_NAME)
|
||||
auto _env_name = std::string{ROCPROFILER_PROJECT_NAME} + "_MONOCHROME";
|
||||
for(auto& itr : _env_name)
|
||||
itr = toupper(itr);
|
||||
_env_cstr = std::getenv(_env_name.c_str());
|
||||
#else
|
||||
_env_cstr = std::getenv("ROCPROFILER_MONOCHROME");
|
||||
#endif
|
||||
|
||||
if(!_env_cstr) _env_cstr = std::getenv("MONOCHROME");
|
||||
|
||||
if(_env_cstr)
|
||||
{
|
||||
auto _env = std::string{_env_cstr};
|
||||
|
||||
// check if numeric
|
||||
if(_env.find_first_not_of("0123456789") == std::string::npos)
|
||||
{
|
||||
return _env.length() > 1 || _env[0] != '0';
|
||||
}
|
||||
|
||||
for(auto& itr : _env)
|
||||
itr = tolower(itr);
|
||||
|
||||
// check for matches to acceptable forms of false
|
||||
for(const auto& itr : {"off", "false", "no", "n", "f"})
|
||||
{
|
||||
if(_env == itr) return false;
|
||||
}
|
||||
|
||||
// check for matches to acceptable forms of true
|
||||
for(const auto& itr : {"on", "true", "yes", "y", "t"})
|
||||
{
|
||||
if(_env == itr) return true;
|
||||
}
|
||||
}
|
||||
return _val;
|
||||
}();
|
||||
return _v;
|
||||
}
|
||||
|
||||
namespace color
|
||||
{
|
||||
static constexpr auto info_value = "\033[01;34m";
|
||||
static constexpr auto warning_value = "\033[01;33m";
|
||||
static constexpr auto fatal_value = "\033[01;31m";
|
||||
static constexpr auto source_value = "\033[01;32m";
|
||||
static constexpr auto dmesg_value = "\033[01;37m";
|
||||
static constexpr auto end_value = "\033[0m";
|
||||
|
||||
inline const char*
|
||||
info()
|
||||
{
|
||||
return (log::monochrome()) ? "" : info_value;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
warning()
|
||||
{
|
||||
return (log::monochrome()) ? "" : warning_value;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
fatal()
|
||||
{
|
||||
return (log::monochrome()) ? "" : fatal_value;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
source()
|
||||
{
|
||||
return (log::monochrome()) ? "" : source_value;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
dmesg()
|
||||
{
|
||||
return (log::monochrome()) ? "" : dmesg_value;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
end()
|
||||
{
|
||||
return (log::monochrome()) ? "" : end_value;
|
||||
}
|
||||
} // namespace color
|
||||
} // namespace log
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,376 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lib/common/environment.hpp"
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <unordered_set>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace units
|
||||
{
|
||||
static constexpr int64_t nsec = 1;
|
||||
static constexpr int64_t usec = 1000 * nsec;
|
||||
static constexpr int64_t msec = 1000 * usec;
|
||||
static constexpr int64_t csec = 10 * msec;
|
||||
static constexpr int64_t dsec = 10 * csec;
|
||||
static constexpr int64_t sec = 10 * dsec;
|
||||
static constexpr int64_t minute = 60 * sec;
|
||||
static constexpr int64_t hour = 60 * minute;
|
||||
|
||||
static constexpr int64_t byte = 1;
|
||||
static constexpr int64_t kilobyte = 1000 * byte;
|
||||
static constexpr int64_t megabyte = 1000 * kilobyte;
|
||||
static constexpr int64_t gigabyte = 1000 * megabyte;
|
||||
static constexpr int64_t terabyte = 1000 * gigabyte;
|
||||
static constexpr int64_t petabyte = 1000 * terabyte;
|
||||
|
||||
static constexpr int64_t kibibyte = 1024 * byte;
|
||||
static constexpr int64_t mebibyte = 1024 * kibibyte;
|
||||
static constexpr int64_t gibibyte = 1024 * mebibyte;
|
||||
static constexpr int64_t tebibyte = 1024 * gibibyte;
|
||||
static constexpr int64_t pebibyte = 1024 * tebibyte;
|
||||
|
||||
static constexpr int64_t B = 1;
|
||||
static constexpr int64_t KB = 1000 * B;
|
||||
static constexpr int64_t MB = 1000 * KB;
|
||||
static constexpr int64_t GB = 1000 * MB;
|
||||
static constexpr int64_t TB = 1000 * GB;
|
||||
static constexpr int64_t PB = 1000 * TB;
|
||||
|
||||
static constexpr int64_t Bi = 1;
|
||||
static constexpr int64_t KiB = 1024 * Bi;
|
||||
static constexpr int64_t MiB = 1024 * KiB;
|
||||
static constexpr int64_t GiB = 1024 * MiB;
|
||||
static constexpr int64_t TiB = 1024 * GiB;
|
||||
static constexpr int64_t PiB = 1024 * TiB;
|
||||
|
||||
static constexpr int64_t nanowatt = 1;
|
||||
static constexpr int64_t microwatt = 1000 * nanowatt;
|
||||
static constexpr int64_t milliwatt = 1000 * microwatt;
|
||||
static constexpr int64_t watt = 1000 * milliwatt;
|
||||
static constexpr int64_t kilowatt = 1000 * watt;
|
||||
static constexpr int64_t megawatt = 1000 * kilowatt;
|
||||
static constexpr int64_t gigawatt = 1000 * megawatt;
|
||||
|
||||
static constexpr int64_t hertz = 1;
|
||||
static constexpr int64_t kilohertz = 1000 * hertz;
|
||||
static constexpr int64_t megahertz = 1000 * kilohertz;
|
||||
static constexpr int64_t gigahertz = 1000 * megahertz;
|
||||
|
||||
static constexpr int64_t Hz = 1;
|
||||
static constexpr int64_t KHz = 1000 * Hz;
|
||||
static constexpr int64_t MHz = 1000 * KHz;
|
||||
static constexpr int64_t GHz = 1000 * MHz;
|
||||
|
||||
inline int64_t
|
||||
get_page_size()
|
||||
{
|
||||
static auto _pagesz = sysconf(_SC_PAGESIZE);
|
||||
return _pagesz;
|
||||
}
|
||||
|
||||
const int64_t clocks_per_sec = sysconf(_SC_CLK_TCK);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline std::string
|
||||
time_repr(int64_t _unit)
|
||||
{
|
||||
switch(_unit)
|
||||
{
|
||||
case nsec: return "nsec"; break;
|
||||
case usec: return "usec"; break;
|
||||
case msec: return "msec"; break;
|
||||
case csec: return "csec"; break;
|
||||
case dsec: return "dsec"; break;
|
||||
case sec: return "sec"; break;
|
||||
default: return "UNK"; break;
|
||||
}
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline std::string
|
||||
mem_repr(int64_t _unit)
|
||||
{
|
||||
switch(_unit)
|
||||
{
|
||||
case byte: return "B"; break;
|
||||
case kilobyte: return "KB"; break;
|
||||
case megabyte: return "MB"; break;
|
||||
case gigabyte: return "GB"; break;
|
||||
case terabyte: return "TB"; break;
|
||||
case petabyte: return "PB"; break;
|
||||
case kibibyte: return "KiB"; break;
|
||||
case mebibyte: return "MiB"; break;
|
||||
case gibibyte: return "GiB"; break;
|
||||
case tebibyte: return "TiB"; break;
|
||||
case pebibyte: return "PiB"; break;
|
||||
default: return "UNK"; break;
|
||||
}
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline std::string
|
||||
freq_repr(int64_t _unit)
|
||||
{
|
||||
switch(_unit)
|
||||
{
|
||||
case hertz: return "Hz"; break;
|
||||
case kilohertz: return "KHz"; break;
|
||||
case megahertz: return "MHz"; break;
|
||||
case gigahertz: return "GHz"; break;
|
||||
default: return "UNK"; break;
|
||||
}
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline std::string
|
||||
power_repr(int64_t _unit)
|
||||
{
|
||||
switch(_unit)
|
||||
{
|
||||
case nanowatt: return "nanowatts"; break;
|
||||
case microwatt: return "microwatts"; break;
|
||||
case milliwatt: return "milliwatts"; break;
|
||||
case watt: return "watts"; break;
|
||||
case kilowatt: return "kilowatts"; break;
|
||||
case megawatt: return "megawatts"; break;
|
||||
case gigawatt: return "gigawatts"; break;
|
||||
default: return "UNK"; break;
|
||||
}
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline std::tuple<std::string, int64_t>
|
||||
get_memory_unit(std::string _unit)
|
||||
{
|
||||
using string_t = std::string;
|
||||
using return_type = std::tuple<string_t, int64_t>;
|
||||
using inner_t = std::tuple<string_t, string_t, int64_t>;
|
||||
|
||||
if(_unit.length() == 0) return return_type{"MB", units::megabyte};
|
||||
|
||||
for(auto& itr : _unit)
|
||||
itr = tolower(itr);
|
||||
|
||||
for(const auto& itr : {inner_t{"byte", "b", units::byte},
|
||||
inner_t{"kilobyte", "kb", units::kilobyte},
|
||||
inner_t{"megabyte", "mb", units::megabyte},
|
||||
inner_t{"gigabyte", "gb", units::gigabyte},
|
||||
inner_t{"terabyte", "tb", units::terabyte},
|
||||
inner_t{"petabyte", "pb", units::petabyte},
|
||||
inner_t{"kibibyte", "kib", units::KiB},
|
||||
inner_t{"mebibyte", "mib", units::MiB},
|
||||
inner_t{"gibibyte", "gib", units::GiB},
|
||||
inner_t{"tebibyte", "tib", units::TiB},
|
||||
inner_t{"pebibyte", "pib", units::PiB}})
|
||||
{
|
||||
if(_unit == std::get<0>(itr) || _unit == std::get<1>(itr))
|
||||
{
|
||||
if(std::get<2>(itr) == units::byte)
|
||||
return return_type{std::get<0>(itr), std::get<2>(itr)};
|
||||
return return_type{mem_repr(std::get<2>(itr)), std::get<2>(itr)};
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "Warning!! No memory unit matching \"" << _unit << "\". Using default..."
|
||||
<< std::endl;
|
||||
|
||||
return return_type{"MB", units::megabyte};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline std::tuple<std::string, int64_t>
|
||||
get_timing_unit(std::string _unit)
|
||||
{
|
||||
using string_t = std::string;
|
||||
using strset_t = std::unordered_set<string_t>;
|
||||
using return_type = std::tuple<string_t, int64_t>;
|
||||
using inner_t = std::tuple<string_t, strset_t, int64_t>;
|
||||
|
||||
if(_unit.length() == 0) return return_type{"sec", units::sec};
|
||||
|
||||
for(auto& itr : _unit)
|
||||
itr = tolower(itr);
|
||||
|
||||
for(const auto& itr :
|
||||
{inner_t{"nsec", strset_t{"ns", "nanosecond", "nanoseconds"}, units::nsec},
|
||||
inner_t{"usec", strset_t{"us", "microsecond", "microseconds"}, units::usec},
|
||||
inner_t{"msec", strset_t{"ms", "millisecond", "milliseconds"}, units::msec},
|
||||
inner_t{"csec", strset_t{"cs", "centisecond", "centiseconds"}, units::csec},
|
||||
inner_t{"dsec", strset_t{"ds", "decisecond", "deciseconds"}, units::dsec},
|
||||
inner_t{"sec", strset_t{"s", "second", "seconds"}, units::sec},
|
||||
inner_t{"min", strset_t{"minute", "minutes"}, units::minute},
|
||||
inner_t{"hr", strset_t{"hr", "hour", "hours"}, units::hour}})
|
||||
{
|
||||
if(_unit == std::get<0>(itr) || std::get<1>(itr).find(_unit) != std::get<1>(itr).end())
|
||||
{
|
||||
return return_type{time_repr(std::get<2>(itr)), std::get<2>(itr)};
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "Warning!! No timing unit matching \"" << _unit << "\". Using default..."
|
||||
<< std::endl;
|
||||
|
||||
return return_type{"sec", units::sec};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline std::tuple<std::string, int64_t>
|
||||
get_frequncy_unit(std::string _unit)
|
||||
{
|
||||
using string_t = std::string;
|
||||
using return_type = std::tuple<string_t, int64_t>;
|
||||
using inner_t = std::tuple<string_t, string_t, int64_t>;
|
||||
|
||||
if(_unit.length() == 0) return return_type{"MHz", units::megahertz};
|
||||
|
||||
for(auto& itr : _unit)
|
||||
itr = tolower(itr);
|
||||
|
||||
for(const auto& itr : {inner_t{"hertz", "hz", units::hertz},
|
||||
inner_t{"kilohertz", "khz", units::kilohertz},
|
||||
inner_t{"megahertz", "mhz", units::megahertz},
|
||||
inner_t{"gigahertz", "ghz", units::gigahertz}})
|
||||
{
|
||||
if(_unit == std::get<0>(itr) || _unit == std::get<1>(itr))
|
||||
{
|
||||
return return_type{freq_repr(std::get<2>(itr)), std::get<2>(itr)};
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "Warning!! No frequency unit matching \"" << _unit << "\". Using default..."
|
||||
<< std::endl;
|
||||
|
||||
return return_type{"MHz", units::megahertz};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline std::tuple<std::string, int64_t>
|
||||
get_power_unit(const std::string& _unit)
|
||||
{
|
||||
using string_t = std::string;
|
||||
using return_type = std::tuple<string_t, int64_t>;
|
||||
using inner_t = std::tuple<string_t, string_t, int64_t>;
|
||||
|
||||
if(_unit.length() == 0) return return_type{"watts", units::watt};
|
||||
|
||||
auto _lunit = _unit;
|
||||
for(auto& itr : _lunit)
|
||||
itr = tolower(itr);
|
||||
|
||||
for(const auto& itr : {inner_t{"nanowatt", "nW", units::nanowatt},
|
||||
inner_t{"microwatt", "uW", units::microwatt},
|
||||
inner_t{"milliwatt", "mW", units::milliwatt},
|
||||
inner_t{"watt", "W", units::watt},
|
||||
inner_t{"kilowatt", "KW", units::kilowatt},
|
||||
inner_t{"megawatt", "MW", units::megawatt},
|
||||
inner_t{"gigawatt", "GW", units::gigawatt}})
|
||||
{
|
||||
if(_lunit == std::get<0>(itr) || _lunit + "s" == std::get<0>(itr) ||
|
||||
_unit == std::get<1>(itr))
|
||||
{
|
||||
return return_type{power_repr(std::get<2>(itr)), std::get<2>(itr)};
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "Warning!! No power unit matching \"" << _unit << "\". Using default..."
|
||||
<< std::endl;
|
||||
|
||||
return return_type{"watts", units::watt};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
namespace temperature
|
||||
{
|
||||
enum unit_system : int8_t
|
||||
{
|
||||
Celsius = 0,
|
||||
Fahrenheit,
|
||||
Kelvin
|
||||
};
|
||||
|
||||
template <typename Tp>
|
||||
Tp
|
||||
convert(Tp _v, unit_system _from, unit_system _to)
|
||||
{
|
||||
switch(_from)
|
||||
{
|
||||
case Celsius:
|
||||
{
|
||||
switch(_to)
|
||||
{
|
||||
case Celsius: return _v;
|
||||
case Fahrenheit: return static_cast<Tp>((_v * 1.8) + 32);
|
||||
case Kelvin: return (_v - 273);
|
||||
}
|
||||
}
|
||||
case Fahrenheit:
|
||||
{
|
||||
switch(_to)
|
||||
{
|
||||
case Celsius: return static_cast<Tp>((_v - 32) / 1.8);
|
||||
case Fahrenheit: return _v;
|
||||
case Kelvin: return (_v - 273);
|
||||
}
|
||||
}
|
||||
case Kelvin:
|
||||
{
|
||||
switch(_to)
|
||||
{
|
||||
case Celsius: return (_v + 273);
|
||||
case Fahrenheit: return static_cast<Tp>(((_v + 273) * 1.8) + 32);
|
||||
case Kelvin: return _v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace temperature
|
||||
} // namespace units
|
||||
} // namespace common
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
set(ROCPROFILER_LIB_HEADERS config_helpers.hpp config_internal.hpp tracer.hpp)
|
||||
set(ROCPROFILER_LIB_SOURCES config_internal.cpp rocprofiler_config.cpp)
|
||||
|
||||
add_library(rocprofiler-library SHARED)
|
||||
add_library(rocprofiler::rocprofiler-library ALIAS rocprofiler-library)
|
||||
|
||||
target_sources(rocprofiler-library PRIVATE ${ROCPROFILER_LIB_SOURCES}
|
||||
${ROCPROFILER_LIB_HEADERS})
|
||||
|
||||
add_subdirectory(hsa)
|
||||
|
||||
target_link_libraries(
|
||||
rocprofiler-library
|
||||
PUBLIC rocprofiler::rocprofiler-headers
|
||||
PRIVATE rocprofiler::rocprofiler-build-flags
|
||||
rocprofiler::rocprofiler-memcheck
|
||||
rocprofiler::rocprofiler-common-library
|
||||
rocprofiler::rocprofiler-stdcxxfs
|
||||
rocprofiler::rocprofiler-dl
|
||||
rocprofiler::rocprofiler-hip
|
||||
rocprofiler::rocprofiler-amd-comgr
|
||||
rocprofiler::rocprofiler-hsa-runtime)
|
||||
target_compile_definitions(
|
||||
rocprofiler-library PRIVATE AMD_INTERNAL_BUILD=1 PROF_API_IMPL=1
|
||||
HIP_PROF_HIP_API_STRING=1 __HIP_PLATFORM_AMD__=1)
|
||||
set_target_properties(
|
||||
rocprofiler-library
|
||||
PROPERTIES OUTPUT_NAME rocprofiler64
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
VERSION ${PROJECT_VERSION})
|
||||
@@ -0,0 +1,107 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rocprofiler/rocprofiler.h>
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
namespace
|
||||
{
|
||||
inline size_t // NOLINTNEXTLINE
|
||||
get_domain_max_op(rocprofiler_tracer_activity_domain_t _domain)
|
||||
{
|
||||
switch(_domain)
|
||||
{
|
||||
case ACTIVITY_DOMAIN_NONE: return -1;
|
||||
case ACTIVITY_DOMAIN_HSA_API: return 0;
|
||||
case ACTIVITY_DOMAIN_HSA_OPS: return 0;
|
||||
case ACTIVITY_DOMAIN_HIP_OPS: return 0;
|
||||
case ACTIVITY_DOMAIN_HIP_API: return 0;
|
||||
case ACTIVITY_DOMAIN_KFD_API: return -1;
|
||||
case ACTIVITY_DOMAIN_EXT_API: return -1;
|
||||
case ACTIVITY_DOMAIN_ROCTX: return 0;
|
||||
case ACTIVITY_DOMAIN_HSA_EVT: return 0;
|
||||
case ACTIVITY_DOMAIN_NUMBER: return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <typename Tp, size_t N = 8>
|
||||
struct allocator
|
||||
{
|
||||
void construct(Tp* const _p, const Tp& _v) const { ::new((void*) _p) Tp{_v}; }
|
||||
void construct(Tp* const _p, Tp&& _v) const { ::new((void*) _p) Tp{std::move(_v)}; }
|
||||
|
||||
void destroy(Tp* const _p) const { _p->~Tp(); }
|
||||
|
||||
static constexpr auto size = sizeof(Tp);
|
||||
using buffer_value_t = char[size];
|
||||
|
||||
struct buffer_entry
|
||||
{
|
||||
std::atomic_flag flag = ATOMIC_FLAG_INIT;
|
||||
buffer_value_t value = {};
|
||||
|
||||
void* get()
|
||||
{
|
||||
if(flag.test_and_set())
|
||||
{
|
||||
return &value[0];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool reset(void* p)
|
||||
{
|
||||
if(static_cast<void*>(&value[0]) == p)
|
||||
{
|
||||
flag.clear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static auto& get_buffer()
|
||||
{
|
||||
static auto _v = std::array<buffer_entry, N>{};
|
||||
return _v;
|
||||
}
|
||||
|
||||
Tp* allocate(const size_t n) const
|
||||
{
|
||||
if(n == 0) return nullptr;
|
||||
|
||||
if(n == 1)
|
||||
{
|
||||
// try an find in buffer for data locality
|
||||
for(auto& itr : get_buffer())
|
||||
{
|
||||
auto* _p = itr.get();
|
||||
if(_p) return static_cast<Tp*>(_p);
|
||||
}
|
||||
}
|
||||
|
||||
auto* _p = new char[n * size];
|
||||
return reinterpret_cast<Tp*>(_p);
|
||||
}
|
||||
|
||||
void deallocate(Tp* const ptr, const size_t /*unused*/) const
|
||||
{
|
||||
for(auto& itr : get_buffer())
|
||||
{
|
||||
if(itr.reset(ptr)) return;
|
||||
}
|
||||
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
Tp* allocate(const size_t n, const void* const /* hint */) const { return allocate(n); }
|
||||
|
||||
void reserve(const size_t) {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
#include "config_internal.hpp"
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
uint64_t
|
||||
correlation_config::get_unique_record_id()
|
||||
{
|
||||
static auto _v = std::atomic<uint64_t>{};
|
||||
return _v++;
|
||||
}
|
||||
|
||||
bool
|
||||
domain_config::operator()(rocprofiler_tracer_activity_domain_t _domain) const
|
||||
{
|
||||
return ((1 << _domain) & domains) == (1 << _domain);
|
||||
}
|
||||
|
||||
bool
|
||||
domain_config::operator()(rocprofiler_tracer_activity_domain_t _domain, uint32_t _op) const
|
||||
{
|
||||
auto _offset = (_domain * rocprofiler::internal::domain_ops_offset);
|
||||
return (*this)(_domain) && (opcodes.none() || opcodes.test(_offset + _op));
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,74 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rocprofiler/config.h>
|
||||
#include <rocprofiler/rocprofiler.h>
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <bitset>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
// number of bits to reserve all op codes
|
||||
constexpr size_t domain_ops_offset = ROCPROFILER_DOMAIN_OPS_MAX;
|
||||
constexpr size_t reserved_domain_size = ROCPROFILER_DOMAIN_OPS_RESERVED * 8;
|
||||
constexpr size_t max_configs_count = 8;
|
||||
|
||||
struct correlation_config
|
||||
{
|
||||
uint64_t id = 0;
|
||||
uint64_t external_id = 0;
|
||||
::rocprofiler_external_cid_cb_t external_id_callback = nullptr;
|
||||
|
||||
static uint64_t get_unique_record_id();
|
||||
};
|
||||
|
||||
struct domain_config
|
||||
{
|
||||
::rocprofiler_sync_callback_t user_sync_callback = nullptr;
|
||||
int64_t domains = 0;
|
||||
std::bitset<reserved_domain_size> opcodes = {};
|
||||
|
||||
/// check if domain is enabled
|
||||
bool operator()(::rocprofiler_tracer_activity_domain_t) const;
|
||||
|
||||
/// check if op in a domain is enabled
|
||||
bool operator()(::rocprofiler_tracer_activity_domain_t, uint32_t) const;
|
||||
};
|
||||
|
||||
struct buffer_config
|
||||
{
|
||||
::rocprofiler_buffer_callback_t callback = nullptr;
|
||||
uint64_t buffer_size;
|
||||
// Memory::GenericBuffer* buffer = nullptr;
|
||||
uint64_t buffer_idx = 0;
|
||||
};
|
||||
|
||||
using filter_config = ::rocprofiler_filter_config;
|
||||
|
||||
struct config
|
||||
{
|
||||
// size is used to ensure that we never read past the end of the version
|
||||
size_t size = 0; // = sizeof(rocprofiler_config)
|
||||
uint32_t compat_version = 0; // set by user
|
||||
uint32_t api_version = 0; // set by rocprofiler
|
||||
uint64_t session_idx = 0; // session id index
|
||||
void* user_data = nullptr; // user data passed to callbacks
|
||||
correlation_config* correlation_id = nullptr; // &my_cid_config (optional)
|
||||
buffer_config* buffer = nullptr; // = &my_buffer_config (required)
|
||||
domain_config* domain = nullptr; // = &my_domain_config (required)
|
||||
filter_config* filter = nullptr; // = &my_filter_config (optional)
|
||||
};
|
||||
|
||||
std::array<rocprofiler::internal::config*, max_configs_count>&
|
||||
get_registered_configs();
|
||||
|
||||
std::array<std::atomic<rocprofiler::internal::config*>, max_configs_count>&
|
||||
get_active_configs();
|
||||
} // namespace internal
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,10 @@
|
||||
set(ROCPROFILER_LIB_HSA_SOURCES hsa.cpp)
|
||||
set(ROCPROFILER_LIB_HSA_HEADERS hsa.hpp hsa-defines.hpp hsa-types.h hsa-utils.hpp)
|
||||
target_sources(rocprofiler-library PRIVATE ${ROCPROFILER_LIB_HSA_SOURCES}
|
||||
${ROCPROFILER_LIB_HSA_HEADERS})
|
||||
|
||||
# add_executable(rocr-example hsa.cpp rocr.hpp) target_link_libraries(rocr-example PRIVATE
|
||||
# rocprofiler-v2) target_include_directories( rocr-example PRIVATE ${PROJECT_SOURCE_DIR}
|
||||
# ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/src ${PROJECT_BINARY_DIR}/src)
|
||||
# target_compile_definitions( rocr-example PRIVATE AMD_INTERNAL_BUILD PROF_API_IMPL
|
||||
# HIP_PROF_HIP_API_STRING=1 __HIP_PLATFORM_AMD__=1)
|
||||
@@ -0,0 +1,266 @@
|
||||
// Copyright (c) 2018-2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define IMPL_DETAIL_EXPAND(X) X
|
||||
#define IMPL_DETAIL_FOR_EACH_NARG(...) \
|
||||
IMPL_DETAIL_FOR_EACH_NARG_(__VA_ARGS__, IMPL_DETAIL_FOR_EACH_RSEQ_N())
|
||||
#define IMPL_DETAIL_FOR_EACH_NARG_(...) IMPL_DETAIL_EXPAND(IMPL_DETAIL_FOR_EACH_ARG_N(__VA_ARGS__))
|
||||
#define IMPL_DETAIL_FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) N
|
||||
#define IMPL_DETAIL_FOR_EACH_RSEQ_N() 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
#define IMPL_DETAIL_CONCATENATE(X, Y) X##Y
|
||||
#define IMPL_DETAIL_FOR_EACH_(N, MACRO, PREFIX, ...) \
|
||||
IMPL_DETAIL_EXPAND(IMPL_DETAIL_CONCATENATE(MACRO, N)(PREFIX, __VA_ARGS__))
|
||||
#define IMPL_DETAIL_FOR_EACH(MACRO, PREFIX, ...) \
|
||||
IMPL_DETAIL_FOR_EACH_(IMPL_DETAIL_FOR_EACH_NARG(__VA_ARGS__), MACRO, PREFIX, __VA_ARGS__)
|
||||
|
||||
#define MEMBER_0(...)
|
||||
#define MEMBER_1(PREFIX, FIELD) PREFIX.FIELD
|
||||
#define MEMBER_2(PREFIX, A, B) MEMBER_1(PREFIX, A), MEMBER_1(PREFIX, B)
|
||||
#define MEMBER_3(PREFIX, A, B, C) MEMBER_2(PREFIX, A, B), MEMBER_1(PREFIX, C)
|
||||
#define MEMBER_4(PREFIX, A, B, C, D) MEMBER_3(PREFIX, A, B, C), MEMBER_1(PREFIX, D)
|
||||
#define MEMBER_5(PREFIX, A, B, C, D, E) MEMBER_4(PREFIX, A, B, C, D), MEMBER_1(PREFIX, E)
|
||||
#define MEMBER_6(PREFIX, A, B, C, D, E, F) MEMBER_5(PREFIX, A, B, C, D, E), MEMBER_1(PREFIX, F)
|
||||
#define MEMBER_7(PREFIX, A, B, C, D, E, F, G) \
|
||||
MEMBER_6(PREFIX, A, B, C, D, E, F), MEMBER_1(PREFIX, G)
|
||||
|
||||
#define MEMBER_8(PREFIX, A, B, C, D, E, F, G, H) \
|
||||
MEMBER_7(PREFIX, A, B, C, D, E, F, G), MEMBER_1(PREFIX, H)
|
||||
|
||||
#define MEMBER_9(PREFIX, A, B, C, D, E, F, G, H, I) \
|
||||
MEMBER_8(PREFIX, A, B, C, D, E, F, G, H), MEMBER_1(PREFIX, I)
|
||||
|
||||
#define MEMBER_10(PREFIX, A, B, C, D, E, F, G, H, I, J) \
|
||||
MEMBER_9(PREFIX, A, B, C, D, E, F, G, H, I), MEMBER_1(PREFIX, J)
|
||||
|
||||
#define MEMBER_11(PREFIX, A, B, C, D, E, F, G, H, I, J, K) \
|
||||
MEMBER_10(PREFIX, A, B, C, D, E, F, G, H, I, J), MEMBER_1(PREFIX, K)
|
||||
|
||||
#define MEMBER_12(PREFIX, A, B, C, D, E, F, G, H, I, J, K, L) \
|
||||
MEMBER_11(PREFIX, A, B, C, D, E, F, G, H, I, J, K), MEMBER_1(PREFIX, L)
|
||||
|
||||
#define NAMED_MEMBER_0(...)
|
||||
#define NAMED_MEMBER_1(PREFIX, FIELD) std::make_pair(#FIELD, PREFIX.FIELD)
|
||||
#define NAMED_MEMBER_2(PREFIX, A, B) NAMED_MEMBER_1(PREFIX, A), NAMED_MEMBER_1(PREFIX, B)
|
||||
#define NAMED_MEMBER_3(PREFIX, A, B, C) NAMED_MEMBER_2(PREFIX, A, B), NAMED_MEMBER_1(PREFIX, C)
|
||||
#define NAMED_MEMBER_4(PREFIX, A, B, C, D) \
|
||||
NAMED_MEMBER_3(PREFIX, A, B, C), NAMED_MEMBER_1(PREFIX, D)
|
||||
#define NAMED_MEMBER_5(PREFIX, A, B, C, D, E) \
|
||||
NAMED_MEMBER_4(PREFIX, A, B, C, D), NAMED_MEMBER_1(PREFIX, E)
|
||||
#define NAMED_MEMBER_6(PREFIX, A, B, C, D, E, F) \
|
||||
NAMED_MEMBER_5(PREFIX, A, B, C, D, E), NAMED_MEMBER_1(PREFIX, F)
|
||||
#define NAMED_MEMBER_7(PREFIX, A, B, C, D, E, F, G) \
|
||||
NAMED_MEMBER_6(PREFIX, A, B, C, D, E, F), NAMED_MEMBER_1(PREFIX, G)
|
||||
#define NAMED_MEMBER_8(PREFIX, A, B, C, D, E, F, G, H) \
|
||||
NAMED_MEMBER_7(PREFIX, A, B, C, D, E, F, G), NAMED_MEMBER_1(PREFIX, H)
|
||||
#define NAMED_MEMBER_9(PREFIX, A, B, C, D, E, F, G, H, I) \
|
||||
NAMED_MEMBER_8(PREFIX, A, B, C, D, E, F, G, H), NAMED_MEMBER_1(PREFIX, I)
|
||||
#define NAMED_MEMBER_10(PREFIX, A, B, C, D, E, F, G, H, I, J) \
|
||||
NAMED_MEMBER_9(PREFIX, A, B, C, D, E, F, G, H, I), NAMED_MEMBER_1(PREFIX, J)
|
||||
#define NAMED_MEMBER_11(PREFIX, A, B, C, D, E, F, G, H, I, J, K) \
|
||||
NAMED_MEMBER_10(PREFIX, A, B, C, D, E, F, G, H, I, J), NAMED_MEMBER_1(PREFIX, K)
|
||||
#define NAMED_MEMBER_12(PREFIX, A, B, C, D, E, F, G, H, I, J, K, L) \
|
||||
NAMED_MEMBER_11(PREFIX, A, B, C, D, E, F, G, H, I, J, K), NAMED_MEMBER_1(PREFIX, L)
|
||||
|
||||
/// @def GET_MEMBER_FIELDS
|
||||
/// @param VAR some struct instance
|
||||
/// @param ... The member fields of the struct
|
||||
///
|
||||
/// @brief this macro is used to expand one variable (VAR) + one or more member fields (FIELDS)
|
||||
/// into a sequence of something like: `(VAR.FIELD, ...)`
|
||||
/// For example, `GET_MEMBER_FIELDS(foo, a, b, c)` would transform into `foo.a, foo.b, foo.c`:
|
||||
///
|
||||
/// @code{.cpp}
|
||||
///
|
||||
/// struct Foo
|
||||
/// {
|
||||
/// int a;
|
||||
/// float b;
|
||||
/// double c;
|
||||
/// };
|
||||
///
|
||||
/// // some function taking int, float, and double
|
||||
/// void some_function(int, float, double);
|
||||
///
|
||||
/// // overload to some_function accepting Foo instance and using
|
||||
/// // the args to invoke "real" function
|
||||
/// void some_function(Foo _foo_v)
|
||||
/// {
|
||||
/// some_function(GET_MEMBER_FIELDS(_foo_v, a, b, c));
|
||||
/// }
|
||||
///
|
||||
/// int main()
|
||||
/// {
|
||||
/// Foo _foo_v = {-1, 0.5f, 2.0};
|
||||
/// invoke_some_function(_foo_v);
|
||||
/// }
|
||||
///
|
||||
/// @code
|
||||
#define GET_MEMBER_FIELDS(VAR, ...) IMPL_DETAIL_FOR_EACH(MEMBER_, VAR, __VA_ARGS__)
|
||||
#define GET_NAMED_MEMBER_FIELDS(VAR, ...) IMPL_DETAIL_FOR_EACH(NAMED_MEMBER_, VAR, __VA_ARGS__)
|
||||
|
||||
#define HSA_API_INFO_DEFINITION_0(HSA_DOMAIN, HSA_TABLE, HSA_API_ID, HSA_FUNC, HSA_FUNC_PTR) \
|
||||
namespace rocprofiler \
|
||||
{ \
|
||||
namespace hsa \
|
||||
{ \
|
||||
template <> \
|
||||
struct hsa_api_info<HSA_API_ID> \
|
||||
{ \
|
||||
static constexpr auto domain_idx = HSA_DOMAIN; \
|
||||
static constexpr auto table_idx = HSA_TABLE; \
|
||||
static constexpr auto operation_idx = HSA_API_ID; \
|
||||
static constexpr auto name = #HSA_FUNC; \
|
||||
\
|
||||
using this_type = hsa_api_info<operation_idx>; \
|
||||
using base_type = hsa_api_impl<operation_idx>; \
|
||||
\
|
||||
static auto& get_table() { return hsa_table_lookup<table_idx>{}(); } \
|
||||
\
|
||||
template <typename TableT> \
|
||||
static auto& get_table(TableT& _v) \
|
||||
{ \
|
||||
return hsa_table_lookup<table_idx>{}(_v); \
|
||||
} \
|
||||
\
|
||||
template <typename TableT> \
|
||||
static auto& get_table_func(TableT& _table) \
|
||||
{ \
|
||||
if constexpr(std::is_pointer<TableT>::value) \
|
||||
{ \
|
||||
assert(_table != nullptr && "nullptr to HSA table for " #HSA_FUNC " function"); \
|
||||
return _table->HSA_FUNC_PTR; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
return _table.HSA_FUNC_PTR; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
static auto& get_table_func() { return get_table_func(get_table()); } \
|
||||
\
|
||||
template <typename DataT> \
|
||||
static auto& get_api_data_args(DataT& _data) \
|
||||
{ \
|
||||
return _data.api_data.args.HSA_FUNC; \
|
||||
} \
|
||||
\
|
||||
template <typename RetT, typename... Args> \
|
||||
static auto get_functor(RetT (*)(Args...)) \
|
||||
{ \
|
||||
if constexpr(std::is_void<RetT>::value) \
|
||||
return [](Args... args) -> RetT { base_type::functor(args...); }; \
|
||||
else \
|
||||
return [](Args... args) -> RetT { return base_type::functor(args...); }; \
|
||||
} \
|
||||
\
|
||||
static auto get_functor() { return get_functor(get_table_func()); } \
|
||||
\
|
||||
static std::string as_string(hsa_trace_data_t) { return std::string{name} + "()"; } \
|
||||
\
|
||||
static std::string as_named_string(hsa_trace_data_t) { return std::string{name} + "()"; } \
|
||||
\
|
||||
static std::vector<std::pair<std::string, std::string>> as_arg_list(hsa_trace_data_t) \
|
||||
{ \
|
||||
return {}; \
|
||||
} \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define HSA_API_INFO_DEFINITION_V(HSA_DOMAIN, HSA_TABLE, HSA_API_ID, HSA_FUNC, HSA_FUNC_PTR, ...) \
|
||||
namespace rocprofiler \
|
||||
{ \
|
||||
namespace hsa \
|
||||
{ \
|
||||
template <> \
|
||||
struct hsa_api_info<HSA_API_ID> \
|
||||
{ \
|
||||
static constexpr auto domain_idx = HSA_DOMAIN; \
|
||||
static constexpr auto table_idx = HSA_TABLE; \
|
||||
static constexpr auto operation_idx = HSA_API_ID; \
|
||||
static constexpr auto name = #HSA_FUNC; \
|
||||
\
|
||||
using this_type = hsa_api_info<operation_idx>; \
|
||||
using base_type = hsa_api_impl<operation_idx>; \
|
||||
\
|
||||
static auto& get_table() { return hsa_table_lookup<table_idx>{}(); } \
|
||||
\
|
||||
template <typename TableT> \
|
||||
static auto& get_table(TableT& _v) \
|
||||
{ \
|
||||
return hsa_table_lookup<table_idx>{}(_v); \
|
||||
} \
|
||||
\
|
||||
template <typename TableT> \
|
||||
static auto& get_table_func(TableT& _table) \
|
||||
{ \
|
||||
if constexpr(std::is_pointer<TableT>::value) \
|
||||
{ \
|
||||
assert(_table != nullptr && "nullptr to HSA table for " #HSA_FUNC " function"); \
|
||||
return _table->HSA_FUNC_PTR; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
return _table.HSA_FUNC_PTR; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
static auto& get_table_func() { return get_table_func(get_table()); } \
|
||||
\
|
||||
template <typename DataT> \
|
||||
static auto& get_api_data_args(DataT& _data) \
|
||||
{ \
|
||||
return _data.api_data.args.HSA_FUNC; \
|
||||
} \
|
||||
\
|
||||
template <typename RetT, typename... Args> \
|
||||
static auto get_functor(RetT (*)(Args...)) \
|
||||
{ \
|
||||
if constexpr(std::is_void<RetT>::value) \
|
||||
return [](Args... args) -> RetT { base_type::functor(args...); }; \
|
||||
else \
|
||||
return [](Args... args) -> RetT { return base_type::functor(args...); }; \
|
||||
} \
|
||||
\
|
||||
static auto get_functor() { return get_functor(get_table_func()); } \
|
||||
\
|
||||
static std::string as_string(hsa_trace_data_t trace_data) \
|
||||
{ \
|
||||
return utils::join(utils::join_args{std::string{name} + "(", ")", ", "}, \
|
||||
GET_MEMBER_FIELDS(get_api_data_args(trace_data), __VA_ARGS__)); \
|
||||
} \
|
||||
\
|
||||
static std::string as_named_string(hsa_trace_data_t trace_data) \
|
||||
{ \
|
||||
return utils::join( \
|
||||
utils::join_args{std::string{name} + "(", ")", ", "}, \
|
||||
GET_NAMED_MEMBER_FIELDS(get_api_data_args(trace_data), __VA_ARGS__)); \
|
||||
} \
|
||||
\
|
||||
static auto as_arg_list(hsa_trace_data_t trace_data) \
|
||||
{ \
|
||||
return utils::stringize( \
|
||||
GET_NAMED_MEMBER_FIELDS(get_api_data_args(trace_data), __VA_ARGS__)); \
|
||||
} \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2018-2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace hsa
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
struct join_args
|
||||
{
|
||||
std::string_view prefix = {};
|
||||
std::string_view suffix = {};
|
||||
std::string_view separator = {};
|
||||
};
|
||||
|
||||
template <typename Tp>
|
||||
auto
|
||||
join_impl(const Tp& _v)
|
||||
{
|
||||
return _v;
|
||||
}
|
||||
|
||||
template <typename LhsT, typename RhsT>
|
||||
auto
|
||||
join_impl(const std::pair<LhsT, RhsT>& _v)
|
||||
{
|
||||
auto _ss = std::stringstream{};
|
||||
_ss << _v.first << "=" << _v.second;
|
||||
return _ss.str();
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto
|
||||
join(join_args ja, Args... args)
|
||||
{
|
||||
auto _content = std::string{};
|
||||
{
|
||||
auto _ss = std::stringstream{};
|
||||
((_ss << ja.separator << join_impl(args)), ...);
|
||||
auto _v = _ss.str();
|
||||
if(_v.length() > ja.separator.length()) _content = _v.substr(2);
|
||||
}
|
||||
|
||||
return (std::stringstream{} << ja.prefix << _content << ja.suffix).str();
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
auto
|
||||
stringize_impl(const Tp& _v)
|
||||
{
|
||||
auto _ss = std::stringstream{};
|
||||
_ss << _v;
|
||||
return _ss.str();
|
||||
}
|
||||
|
||||
template <typename LhsT, typename RhsT>
|
||||
auto
|
||||
stringize_impl(const std::pair<LhsT, RhsT>& _v)
|
||||
{
|
||||
return std::make_pair(stringize_impl(_v.first), stringize_impl(_v.second));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto
|
||||
stringize(Args... args)
|
||||
{
|
||||
return std::vector<std::pair<std::string, std::string>>{stringize_impl(args)...};
|
||||
}
|
||||
} // namespace utils
|
||||
} // namespace hsa
|
||||
} // namespace rocprofiler
|
||||
@@ -0,0 +1,485 @@
|
||||
// Copyright (c) 2018-2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "hsa.hpp"
|
||||
#include "hsa-types.h"
|
||||
|
||||
#include <hsa/hsa_api_trace.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace hsa
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::atomic<activity_functor_t> report_activity = {};
|
||||
|
||||
auto&
|
||||
get_saved_table()
|
||||
{
|
||||
static auto _core = CoreApiTable{};
|
||||
static auto _amd_ext = AmdExtTable{};
|
||||
static auto _img_ext = ImageExtTable{};
|
||||
static auto _fini_ext = FinalizerExtTable{};
|
||||
static auto _v = []() {
|
||||
_core.version = {
|
||||
HSA_CORE_API_TABLE_MAJOR_VERSION, sizeof(_core), HSA_CORE_API_TABLE_STEP_VERSION, 0};
|
||||
_amd_ext.version = {HSA_AMD_EXT_API_TABLE_MAJOR_VERSION,
|
||||
sizeof(_amd_ext),
|
||||
HSA_AMD_EXT_API_TABLE_STEP_VERSION,
|
||||
0};
|
||||
_img_ext.version = {HSA_IMAGE_API_TABLE_MAJOR_VERSION,
|
||||
sizeof(_img_ext),
|
||||
HSA_IMAGE_API_TABLE_STEP_VERSION,
|
||||
0};
|
||||
_fini_ext.version = {HSA_FINALIZER_API_TABLE_MAJOR_VERSION,
|
||||
sizeof(_fini_ext),
|
||||
HSA_FINALIZER_API_TABLE_STEP_VERSION,
|
||||
0};
|
||||
auto _version = ApiTableVersion{
|
||||
HSA_API_TABLE_MAJOR_VERSION, sizeof(HsaApiTable), HSA_API_TABLE_STEP_VERSION, 0};
|
||||
auto _val = hsa_api_table_t{_version, &_core, &_amd_ext, &_fini_ext, &_img_ext};
|
||||
return _val;
|
||||
}();
|
||||
return _v;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
struct hsa_table_lookup<HSA_API_TABLE_ID_CoreApi>
|
||||
{
|
||||
auto& operator()(hsa_api_table_t& _v) const { return _v.core_; }
|
||||
auto& operator()(hsa_api_table_t* _v) const { return _v->core_; }
|
||||
auto& operator()() const { return (*this)(get_saved_table()); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hsa_table_lookup<HSA_API_TABLE_ID_AmdExt>
|
||||
{
|
||||
auto& operator()(hsa_api_table_t& _v) const { return _v.amd_ext_; }
|
||||
auto& operator()(hsa_api_table_t* _v) const { return _v->amd_ext_; }
|
||||
auto& operator()() const { return (*this)(get_saved_table()); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hsa_table_lookup<HSA_API_TABLE_ID_ImageExt>
|
||||
{
|
||||
auto& operator()(hsa_api_table_t& _v) const { return _v.image_ext_; }
|
||||
auto& operator()(hsa_api_table_t* _v) const { return _v->image_ext_; }
|
||||
auto& operator()() const { return (*this)(get_saved_table()); }
|
||||
};
|
||||
|
||||
template <typename DataT, typename Tp>
|
||||
void
|
||||
set_data_retval(DataT& _data, Tp _val)
|
||||
{
|
||||
if constexpr(std::is_same<Tp, hsa_signal_value_t>::value)
|
||||
{
|
||||
_data.hsa_signal_value_t_retval = _val;
|
||||
}
|
||||
else if constexpr(std::is_same<Tp, uint64_t>::value)
|
||||
{
|
||||
_data.uint64_t_retval = _val;
|
||||
}
|
||||
else if constexpr(std::is_same<Tp, uint32_t>::value)
|
||||
{
|
||||
_data.uint32_t_retval = _val;
|
||||
}
|
||||
else if constexpr(std::is_same<Tp, hsa_status_t>::value)
|
||||
{
|
||||
_data.hsa_status_t_retval = _val;
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::is_void<Tp>::value, "Error! unsupported return type");
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t Idx>
|
||||
template <typename DataT, typename DataArgsT, typename... Args>
|
||||
auto
|
||||
hsa_api_impl<Idx>::phase_enter(DataT& _data, DataArgsT& _data_args, Args... args)
|
||||
{
|
||||
using info_type = hsa_api_info<Idx>;
|
||||
|
||||
activity_functor_t _func = report_activity.load(std::memory_order_relaxed);
|
||||
if(_func)
|
||||
{
|
||||
if constexpr(Idx == HSA_API_ID_hsa_amd_memory_async_copy_rect)
|
||||
{
|
||||
auto _tuple = std::make_tuple(args...);
|
||||
_data.api_data.args.hsa_amd_memory_async_copy_rect.dst = std::get<0>(_tuple);
|
||||
_data.api_data.args.hsa_amd_memory_async_copy_rect.dst_offset = std::get<1>(_tuple);
|
||||
_data.api_data.args.hsa_amd_memory_async_copy_rect.src = std::get<2>(_tuple);
|
||||
_data.api_data.args.hsa_amd_memory_async_copy_rect.src_offset = std::get<3>(_tuple);
|
||||
_data.api_data.args.hsa_amd_memory_async_copy_rect.range = std::get<4>(_tuple);
|
||||
_data.api_data.args.hsa_amd_memory_async_copy_rect.range__val = *(std::get<4>(_tuple));
|
||||
_data.api_data.args.hsa_amd_memory_async_copy_rect.copy_agent = std::get<5>(_tuple);
|
||||
_data.api_data.args.hsa_amd_memory_async_copy_rect.dir = std::get<6>(_tuple);
|
||||
_data.api_data.args.hsa_amd_memory_async_copy_rect.num_dep_signals =
|
||||
std::get<7>(_tuple);
|
||||
_data.api_data.args.hsa_amd_memory_async_copy_rect.dep_signals = std::get<8>(_tuple);
|
||||
_data.api_data.args.hsa_amd_memory_async_copy_rect.completion_signal =
|
||||
std::get<9>(_tuple);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data_args = DataArgsT{args...};
|
||||
}
|
||||
if(_func(info_type::domain_idx, info_type::operation_idx, &_data) == 0)
|
||||
{
|
||||
if(_data.phase_enter != nullptr) _data.phase_enter(info_type::operation_idx, &_data);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <size_t Idx>
|
||||
template <typename DataT, typename... Args>
|
||||
auto
|
||||
hsa_api_impl<Idx>::phase_exit(DataT& _data)
|
||||
{
|
||||
using info_type = hsa_api_info<Idx>;
|
||||
|
||||
if(_data.phase_exit != nullptr)
|
||||
{
|
||||
_data.phase_exit(info_type::operation_idx, &_data);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct null_type
|
||||
{};
|
||||
|
||||
template <size_t Idx>
|
||||
template <typename DataT, typename FuncT, typename... Args>
|
||||
auto
|
||||
hsa_api_impl<Idx>::exec(DataT& _data, FuncT&& _func, Args&&... args)
|
||||
{
|
||||
using return_type = std::decay_t<std::invoke_result_t<FuncT, Args...>>;
|
||||
|
||||
if(_func)
|
||||
{
|
||||
static_assert(std::is_void<return_type>::value || std::is_enum<return_type>::value ||
|
||||
std::is_integral<return_type>::value,
|
||||
"Error! unsupported return type");
|
||||
|
||||
if constexpr(std::is_void<return_type>::value)
|
||||
{
|
||||
_func(std::forward<Args>(args)...);
|
||||
return null_type{};
|
||||
}
|
||||
else
|
||||
{
|
||||
auto _ret = _func(std::forward<Args>(args)...);
|
||||
set_data_retval(_data.api_data, _ret);
|
||||
return _ret;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr(std::is_void<return_type>::value)
|
||||
return null_type{};
|
||||
else
|
||||
return return_type{HSA_STATUS_ERROR};
|
||||
}
|
||||
|
||||
template <size_t Idx>
|
||||
template <typename... Args>
|
||||
auto
|
||||
hsa_api_impl<Idx>::functor(Args&&... args)
|
||||
{
|
||||
using info_type = hsa_api_info<Idx>;
|
||||
|
||||
auto trace_data = hsa_trace_data_t{};
|
||||
|
||||
auto _enabled = phase_enter(
|
||||
trace_data, info_type::get_api_data_args(trace_data), std::forward<Args>(args)...);
|
||||
|
||||
auto _ret = exec(trace_data, info_type::get_table_func(), std::forward<Args>(args)...);
|
||||
|
||||
if(_enabled) phase_exit(trace_data);
|
||||
|
||||
if constexpr(!std::is_same<decltype(_ret), null_type>::value)
|
||||
return _ret;
|
||||
else
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
} // namespace hsa
|
||||
} // namespace rocprofiler
|
||||
|
||||
#include "hsa.gen.cpp"
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace hsa
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <size_t Idx, size_t... IdxTail>
|
||||
const char*
|
||||
hsa_api_name(const uint32_t id, std::index_sequence<Idx, IdxTail...>)
|
||||
{
|
||||
if(Idx == id) return hsa_api_info<Idx>::name;
|
||||
if constexpr(sizeof...(IdxTail) > 0)
|
||||
return hsa_api_name(id, std::index_sequence<IdxTail...>{});
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <size_t Idx, size_t... IdxTail>
|
||||
uint32_t
|
||||
hsa_api_id_by_name(const char* name, std::index_sequence<Idx, IdxTail...>)
|
||||
{
|
||||
if(std::string_view{hsa_api_info<Idx>::name} == std::string_view{name})
|
||||
return hsa_api_info<Idx>::operation_idx;
|
||||
if constexpr(sizeof...(IdxTail) > 0)
|
||||
return hsa_api_id_by_name(name, std::index_sequence<IdxTail...>{});
|
||||
else
|
||||
return HSA_API_ID_NONE;
|
||||
}
|
||||
|
||||
template <size_t Idx, size_t... IdxTail>
|
||||
std::string
|
||||
hsa_api_data_string(const uint32_t id,
|
||||
const hsa_trace_data_t& _data,
|
||||
std::index_sequence<Idx, IdxTail...>)
|
||||
{
|
||||
if(Idx == id) return hsa_api_info<Idx>::as_string(_data);
|
||||
if constexpr(sizeof...(IdxTail) > 0)
|
||||
return hsa_api_data_string(id, _data, std::index_sequence<IdxTail...>{});
|
||||
else
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
template <size_t Idx, size_t... IdxTail>
|
||||
std::string
|
||||
hsa_api_named_data_string(const uint32_t id,
|
||||
const hsa_trace_data_t& _data,
|
||||
std::index_sequence<Idx, IdxTail...>)
|
||||
{
|
||||
if(Idx == id) return hsa_api_info<Idx>::as_named_string(_data);
|
||||
if constexpr(sizeof...(IdxTail) > 0)
|
||||
return hsa_api_named_data_string(id, _data, std::index_sequence<IdxTail...>{});
|
||||
else
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
template <size_t Idx, size_t... IdxTail>
|
||||
void
|
||||
hsa_api_iterate_args(const uint32_t id,
|
||||
const hsa_trace_data_t& _data,
|
||||
int (*_func)(const char*, const char*),
|
||||
std::index_sequence<Idx, IdxTail...>)
|
||||
{
|
||||
if(Idx == id)
|
||||
{
|
||||
for(auto&& itr : hsa_api_info<Idx>::as_arg_list(_data))
|
||||
{
|
||||
_func(itr.first.c_str(), itr.second.c_str());
|
||||
}
|
||||
}
|
||||
if constexpr(sizeof...(IdxTail) > 0)
|
||||
hsa_api_iterate_args(id, _data, _func, std::index_sequence<IdxTail...>{});
|
||||
}
|
||||
|
||||
template <size_t... Idx>
|
||||
void
|
||||
hsa_api_get_ids(std::vector<uint32_t>& _id_list, std::index_sequence<Idx...>)
|
||||
{
|
||||
auto _emplace = [](auto& _vec, uint32_t _v) {
|
||||
if(_v < HSA_API_ID_DISPATCH) _vec.emplace_back(_v);
|
||||
};
|
||||
|
||||
(_emplace(_id_list, hsa_api_info<Idx>::operation_idx), ...);
|
||||
}
|
||||
|
||||
template <size_t... Idx>
|
||||
void
|
||||
hsa_api_get_names(std::vector<const char*>& _name_list, std::index_sequence<Idx...>)
|
||||
{
|
||||
auto _emplace = [](auto& _vec, const char* _v) {
|
||||
if(_v != nullptr && strnlen(_v, 1) > 0) _vec.emplace_back(_v);
|
||||
};
|
||||
|
||||
(_emplace(_name_list, hsa_api_info<Idx>::name), ...);
|
||||
}
|
||||
|
||||
template <size_t... Idx>
|
||||
void
|
||||
hsa_api_update_table(hsa_api_table_t* _orig, std::index_sequence<Idx...>)
|
||||
{
|
||||
auto _update = [](hsa_api_table_t* _orig_v, auto _info) {
|
||||
// 1. get the sub-table containing the function pointer
|
||||
// 2. get reference to function pointer in sub-table
|
||||
// 3. update function pointer with functor
|
||||
auto& _table = _info.get_table(_orig_v);
|
||||
auto& _func = _info.get_table_func(_table);
|
||||
_func = _info.get_functor(_func);
|
||||
};
|
||||
|
||||
(_update(_orig, hsa_api_info<Idx>{}), ...);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// check out the assembly here... this compiles to a switch statement
|
||||
const char*
|
||||
hsa_api_name(uint32_t id)
|
||||
{
|
||||
return hsa_api_name(id, std::make_index_sequence<HSA_API_ID_DISPATCH>{});
|
||||
}
|
||||
|
||||
uint32_t
|
||||
hsa_api_id_by_name(const char* name)
|
||||
{
|
||||
return hsa_api_id_by_name(name, std::make_index_sequence<HSA_API_ID_DISPATCH>{});
|
||||
}
|
||||
|
||||
std::string
|
||||
hsa_api_data_string(uint32_t id, const hsa_trace_data_t& _data)
|
||||
{
|
||||
return hsa_api_data_string(id, _data, std::make_index_sequence<HSA_API_ID_DISPATCH>{});
|
||||
}
|
||||
|
||||
std::string
|
||||
hsa_api_named_data_string(uint32_t id, const hsa_trace_data_t& _data)
|
||||
{
|
||||
return hsa_api_named_data_string(id, _data, std::make_index_sequence<HSA_API_ID_DISPATCH>{});
|
||||
}
|
||||
|
||||
void
|
||||
hsa_api_iterate_args(uint32_t id,
|
||||
const hsa_trace_data_t& _data,
|
||||
int (*_func)(const char*, const char*))
|
||||
{
|
||||
if(_func)
|
||||
hsa_api_iterate_args(id, _data, _func, std::make_index_sequence<HSA_API_ID_DISPATCH>{});
|
||||
}
|
||||
|
||||
std::vector<uint32_t>
|
||||
hsa_api_get_ids()
|
||||
{
|
||||
auto _data = std::vector<uint32_t>{};
|
||||
_data.reserve(HSA_API_ID_DISPATCH);
|
||||
hsa_api_get_ids(_data, std::make_index_sequence<HSA_API_ID_DISPATCH>{});
|
||||
return _data;
|
||||
}
|
||||
|
||||
std::vector<const char*>
|
||||
hsa_api_get_names()
|
||||
{
|
||||
auto _data = std::vector<const char*>{};
|
||||
_data.reserve(HSA_API_ID_DISPATCH);
|
||||
hsa_api_get_names(_data, std::make_index_sequence<HSA_API_ID_DISPATCH>{});
|
||||
return _data;
|
||||
}
|
||||
|
||||
void
|
||||
hsa_api_set_callback(activity_functor_t _func)
|
||||
{
|
||||
auto&& _v = report_activity.load();
|
||||
report_activity.compare_exchange_strong(_v, _func);
|
||||
}
|
||||
|
||||
void
|
||||
hsa_api_update_table(hsa_api_table_t* _orig)
|
||||
{
|
||||
if(_orig) hsa_api_update_table(_orig, std::make_index_sequence<HSA_API_ID_DISPATCH>{});
|
||||
}
|
||||
} // namespace hsa
|
||||
} // namespace rocprofiler
|
||||
|
||||
extern "C" {
|
||||
bool
|
||||
OnLoad(HsaApiTable* table,
|
||||
uint64_t runtime_version,
|
||||
uint64_t failed_tool_count,
|
||||
const char* const* failed_tool_names)
|
||||
{
|
||||
(void) runtime_version;
|
||||
(void) failed_tool_count;
|
||||
(void) failed_tool_names;
|
||||
|
||||
auto& _saved = rocprofiler::hsa::get_saved_table();
|
||||
copyTables(table, &_saved);
|
||||
|
||||
rocprofiler::hsa::hsa_api_update_table(table);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#include <iomanip>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
rocprofiler::hsa::activity_functor_t _cb =
|
||||
[](rocprofiler_tracer_activity_domain_t domain, uint32_t operation_id, void* data) {
|
||||
const auto* _name = rocprofiler::hsa::hsa_api_name(operation_id);
|
||||
auto _name_id = rocprofiler::hsa::hsa_api_id_by_name(_name);
|
||||
auto& _data = *static_cast<rocprofiler::hsa::hsa_trace_data_t*>(data);
|
||||
std::cout << "[cb] domain=" << domain << ", op_id=" << operation_id << ", data=" << data
|
||||
<< ", name=" << _name << ", name_id=" << _name_id << ", named_string='"
|
||||
<< rocprofiler::hsa::hsa_api_named_data_string(operation_id, _data) << "'"
|
||||
<< "\n";
|
||||
auto _func = [](const char* name, const char* value) {
|
||||
std::cout << " " << std::setw(20) << name << " = " << value << "\n";
|
||||
return 0;
|
||||
};
|
||||
rocprofiler::hsa::hsa_api_iterate_args(operation_id, _data, _func);
|
||||
return 0;
|
||||
};
|
||||
|
||||
rocprofiler::hsa::report_activity.store(_cb);
|
||||
|
||||
{
|
||||
double val = 40;
|
||||
hsa_code_object_t code_object = {};
|
||||
hsa_code_object_info_t attribute = HSA_CODE_OBJECT_INFO_TYPE;
|
||||
void* value = &val;
|
||||
|
||||
auto _func =
|
||||
rocprofiler::hsa::hsa_api_info<HSA_API_ID_hsa_code_object_get_info>::get_functor();
|
||||
_func(code_object, attribute, value);
|
||||
}
|
||||
|
||||
{
|
||||
bool result = false;
|
||||
uint16_t ext = 1;
|
||||
uint16_t major = 4;
|
||||
uint16_t minor = 2;
|
||||
|
||||
auto _func = rocprofiler::hsa::hsa_api_info<
|
||||
HSA_API_ID_hsa_system_extension_supported>::get_functor();
|
||||
_func(ext, major, minor, &result);
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,217 @@
|
||||
// Copyright (c) 2018-2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "hsa.hpp"
|
||||
|
||||
// clang-format off
|
||||
HSA_API_INFO_DEFINITION_0(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_init, hsa_init, hsa_init_fn)
|
||||
HSA_API_INFO_DEFINITION_0(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_shut_down, hsa_shut_down, hsa_shut_down_fn)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_system_get_info, hsa_system_get_info, hsa_system_get_info_fn, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_system_extension_supported, hsa_system_extension_supported, hsa_system_extension_supported_fn, extension, version_major, version_minor, result)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_system_get_extension_table, hsa_system_get_extension_table, hsa_system_get_extension_table_fn, extension, version_major, version_minor, table)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_iterate_agents, hsa_iterate_agents, hsa_iterate_agents_fn, callback, data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_get_info, hsa_agent_get_info, hsa_agent_get_info_fn, agent, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_create, hsa_queue_create, hsa_queue_create_fn, agent, size, type, callback, data, private_segment_size, group_segment_size, queue)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_soft_queue_create, hsa_soft_queue_create, hsa_soft_queue_create_fn, region, size, type, features, doorbell_signal, queue)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_destroy, hsa_queue_destroy, hsa_queue_destroy_fn, queue)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_inactivate, hsa_queue_inactivate, hsa_queue_inactivate_fn, queue)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_load_read_index_scacquire, hsa_queue_load_read_index_scacquire, hsa_queue_load_read_index_scacquire_fn, queue)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_load_read_index_relaxed, hsa_queue_load_read_index_relaxed, hsa_queue_load_read_index_relaxed_fn, queue)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_load_write_index_scacquire, hsa_queue_load_write_index_scacquire, hsa_queue_load_write_index_scacquire_fn, queue)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_load_write_index_relaxed, hsa_queue_load_write_index_relaxed, hsa_queue_load_write_index_relaxed_fn, queue)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_store_write_index_relaxed, hsa_queue_store_write_index_relaxed, hsa_queue_store_write_index_relaxed_fn, queue, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_store_write_index_screlease, hsa_queue_store_write_index_screlease, hsa_queue_store_write_index_screlease_fn, queue, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_cas_write_index_scacq_screl, hsa_queue_cas_write_index_scacq_screl, hsa_queue_cas_write_index_scacq_screl_fn, queue, expected, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_cas_write_index_scacquire, hsa_queue_cas_write_index_scacquire, hsa_queue_cas_write_index_scacquire_fn, queue, expected, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_cas_write_index_relaxed, hsa_queue_cas_write_index_relaxed, hsa_queue_cas_write_index_relaxed_fn, queue, expected, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_cas_write_index_screlease, hsa_queue_cas_write_index_screlease, hsa_queue_cas_write_index_screlease_fn, queue, expected, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_add_write_index_scacq_screl, hsa_queue_add_write_index_scacq_screl, hsa_queue_add_write_index_scacq_screl_fn, queue, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_add_write_index_scacquire, hsa_queue_add_write_index_scacquire, hsa_queue_add_write_index_scacquire_fn, queue, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_add_write_index_relaxed, hsa_queue_add_write_index_relaxed, hsa_queue_add_write_index_relaxed_fn, queue, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_add_write_index_screlease, hsa_queue_add_write_index_screlease, hsa_queue_add_write_index_screlease_fn, queue, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_store_read_index_relaxed, hsa_queue_store_read_index_relaxed, hsa_queue_store_read_index_relaxed_fn, queue, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_store_read_index_screlease, hsa_queue_store_read_index_screlease, hsa_queue_store_read_index_screlease_fn, queue, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_iterate_regions, hsa_agent_iterate_regions, hsa_agent_iterate_regions_fn, agent, callback, data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_region_get_info, hsa_region_get_info, hsa_region_get_info_fn, region, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_get_exception_policies, hsa_agent_get_exception_policies, hsa_agent_get_exception_policies_fn, agent, profile, mask)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_extension_supported, hsa_agent_extension_supported, hsa_agent_extension_supported_fn, extension, agent, version_major, version_minor, result)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_register, hsa_memory_register, hsa_memory_register_fn, ptr, size)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_deregister, hsa_memory_deregister, hsa_memory_deregister_fn, ptr, size)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_allocate, hsa_memory_allocate, hsa_memory_allocate_fn, region, size, ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_free, hsa_memory_free, hsa_memory_free_fn, ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_copy, hsa_memory_copy, hsa_memory_copy_fn, dst, src, size)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_assign_agent, hsa_memory_assign_agent, hsa_memory_assign_agent_fn, ptr, agent, access)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_create, hsa_signal_create, hsa_signal_create_fn, initial_value, num_consumers, consumers, signal)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_destroy, hsa_signal_destroy, hsa_signal_destroy_fn, signal)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_load_relaxed, hsa_signal_load_relaxed, hsa_signal_load_relaxed_fn, signal)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_load_scacquire, hsa_signal_load_scacquire, hsa_signal_load_scacquire_fn, signal)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_store_relaxed, hsa_signal_store_relaxed, hsa_signal_store_relaxed_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_store_screlease, hsa_signal_store_screlease, hsa_signal_store_screlease_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_wait_relaxed, hsa_signal_wait_relaxed, hsa_signal_wait_relaxed_fn, signal, condition, compare_value, timeout_hint, wait_state_hint)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_wait_scacquire, hsa_signal_wait_scacquire, hsa_signal_wait_scacquire_fn, signal, condition, compare_value, timeout_hint, wait_state_hint)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_and_relaxed, hsa_signal_and_relaxed, hsa_signal_and_relaxed_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_and_scacquire, hsa_signal_and_scacquire, hsa_signal_and_scacquire_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_and_screlease, hsa_signal_and_screlease, hsa_signal_and_screlease_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_and_scacq_screl, hsa_signal_and_scacq_screl, hsa_signal_and_scacq_screl_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_or_relaxed, hsa_signal_or_relaxed, hsa_signal_or_relaxed_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_or_scacquire, hsa_signal_or_scacquire, hsa_signal_or_scacquire_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_or_screlease, hsa_signal_or_screlease, hsa_signal_or_screlease_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_or_scacq_screl, hsa_signal_or_scacq_screl, hsa_signal_or_scacq_screl_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_xor_relaxed, hsa_signal_xor_relaxed, hsa_signal_xor_relaxed_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_xor_scacquire, hsa_signal_xor_scacquire, hsa_signal_xor_scacquire_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_xor_screlease, hsa_signal_xor_screlease, hsa_signal_xor_screlease_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_xor_scacq_screl, hsa_signal_xor_scacq_screl, hsa_signal_xor_scacq_screl_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_exchange_relaxed, hsa_signal_exchange_relaxed, hsa_signal_exchange_relaxed_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_exchange_scacquire, hsa_signal_exchange_scacquire, hsa_signal_exchange_scacquire_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_exchange_screlease, hsa_signal_exchange_screlease, hsa_signal_exchange_screlease_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_exchange_scacq_screl, hsa_signal_exchange_scacq_screl, hsa_signal_exchange_scacq_screl_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_add_relaxed, hsa_signal_add_relaxed, hsa_signal_add_relaxed_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_add_scacquire, hsa_signal_add_scacquire, hsa_signal_add_scacquire_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_add_screlease, hsa_signal_add_screlease, hsa_signal_add_screlease_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_add_scacq_screl, hsa_signal_add_scacq_screl, hsa_signal_add_scacq_screl_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_subtract_relaxed, hsa_signal_subtract_relaxed, hsa_signal_subtract_relaxed_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_subtract_scacquire, hsa_signal_subtract_scacquire, hsa_signal_subtract_scacquire_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_subtract_screlease, hsa_signal_subtract_screlease, hsa_signal_subtract_screlease_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_subtract_scacq_screl, hsa_signal_subtract_scacq_screl, hsa_signal_subtract_scacq_screl_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_cas_relaxed, hsa_signal_cas_relaxed, hsa_signal_cas_relaxed_fn, signal, expected, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_cas_scacquire, hsa_signal_cas_scacquire, hsa_signal_cas_scacquire_fn, signal, expected, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_cas_screlease, hsa_signal_cas_screlease, hsa_signal_cas_screlease_fn, signal, expected, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_cas_scacq_screl, hsa_signal_cas_scacq_screl, hsa_signal_cas_scacq_screl_fn, signal, expected, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_from_name, hsa_isa_from_name, hsa_isa_from_name_fn, name, isa)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_get_info, hsa_isa_get_info, hsa_isa_get_info_fn, isa, attribute, index, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_compatible, hsa_isa_compatible, hsa_isa_compatible_fn, code_object_isa, agent_isa, result)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_serialize, hsa_code_object_serialize, hsa_code_object_serialize_fn, code_object, alloc_callback, callback_data, options, serialized_code_object, serialized_code_object_size)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_deserialize, hsa_code_object_deserialize, hsa_code_object_deserialize_fn, serialized_code_object, serialized_code_object_size, options, code_object)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_destroy, hsa_code_object_destroy, hsa_code_object_destroy_fn, code_object)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_get_info, hsa_code_object_get_info, hsa_code_object_get_info_fn, code_object, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_get_symbol, hsa_code_object_get_symbol, hsa_code_object_get_symbol_fn, code_object, symbol_name, symbol)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_symbol_get_info, hsa_code_symbol_get_info, hsa_code_symbol_get_info_fn, code_symbol, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_iterate_symbols, hsa_code_object_iterate_symbols, hsa_code_object_iterate_symbols_fn, code_object, callback, data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_create, hsa_executable_create, hsa_executable_create_fn, profile, executable_state, options, executable)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_destroy, hsa_executable_destroy, hsa_executable_destroy_fn, executable)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_load_code_object, hsa_executable_load_code_object, hsa_executable_load_code_object_fn, executable, agent, code_object, options)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_freeze, hsa_executable_freeze, hsa_executable_freeze_fn, executable, options)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_get_info, hsa_executable_get_info, hsa_executable_get_info_fn, executable, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_global_variable_define, hsa_executable_global_variable_define, hsa_executable_global_variable_define_fn, executable, variable_name, address)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_agent_global_variable_define, hsa_executable_agent_global_variable_define, hsa_executable_agent_global_variable_define_fn, executable, agent, variable_name, address)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_readonly_variable_define, hsa_executable_readonly_variable_define, hsa_executable_readonly_variable_define_fn, executable, agent, variable_name, address)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_validate, hsa_executable_validate, hsa_executable_validate_fn, executable, result)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_get_symbol, hsa_executable_get_symbol, hsa_executable_get_symbol_fn, executable, module_name, symbol_name, agent, call_convention, symbol)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_symbol_get_info, hsa_executable_symbol_get_info, hsa_executable_symbol_get_info_fn, executable_symbol, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_iterate_symbols, hsa_executable_iterate_symbols, hsa_executable_iterate_symbols_fn, executable, callback, data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_status_string, hsa_status_string, hsa_status_string_fn, status, status_string)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_extension_get_name, hsa_extension_get_name, hsa_extension_get_name_fn, extension, name)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_system_major_extension_supported, hsa_system_major_extension_supported, hsa_system_major_extension_supported_fn, extension, version_major, version_minor, result)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_system_get_major_extension_table, hsa_system_get_major_extension_table, hsa_system_get_major_extension_table_fn, extension, version_major, table_length, table)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_major_extension_supported, hsa_agent_major_extension_supported, hsa_agent_major_extension_supported_fn, extension, agent, version_major, version_minor, result)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_cache_get_info, hsa_cache_get_info, hsa_cache_get_info_fn, cache, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_iterate_caches, hsa_agent_iterate_caches, hsa_agent_iterate_caches_fn, agent, callback, data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_silent_store_relaxed, hsa_signal_silent_store_relaxed, hsa_signal_silent_store_relaxed_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_silent_store_screlease, hsa_signal_silent_store_screlease, hsa_signal_silent_store_screlease_fn, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_group_create, hsa_signal_group_create, hsa_signal_group_create_fn, num_signals, signals, num_consumers, consumers, signal_group)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_group_destroy, hsa_signal_group_destroy, hsa_signal_group_destroy_fn, signal_group)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_group_wait_any_scacquire, hsa_signal_group_wait_any_scacquire, hsa_signal_group_wait_any_scacquire_fn, signal_group, conditions, compare_values, wait_state_hint, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_group_wait_any_relaxed, hsa_signal_group_wait_any_relaxed, hsa_signal_group_wait_any_relaxed_fn, signal_group, conditions, compare_values, wait_state_hint, signal, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_iterate_isas, hsa_agent_iterate_isas, hsa_agent_iterate_isas_fn, agent, callback, data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_get_info_alt, hsa_isa_get_info_alt, hsa_isa_get_info_alt_fn, isa, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_get_exception_policies, hsa_isa_get_exception_policies, hsa_isa_get_exception_policies_fn, isa, profile, mask)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_get_round_method, hsa_isa_get_round_method, hsa_isa_get_round_method_fn, isa, fp_type, flush_mode, round_method)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_wavefront_get_info, hsa_wavefront_get_info, hsa_wavefront_get_info_fn, wavefront, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_iterate_wavefronts, hsa_isa_iterate_wavefronts, hsa_isa_iterate_wavefronts_fn, isa, callback, data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_get_symbol_from_name, hsa_code_object_get_symbol_from_name, hsa_code_object_get_symbol_from_name_fn, code_object, module_name, symbol_name, symbol)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_reader_create_from_file, hsa_code_object_reader_create_from_file, hsa_code_object_reader_create_from_file_fn, file, code_object_reader)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_reader_create_from_memory, hsa_code_object_reader_create_from_memory, hsa_code_object_reader_create_from_memory_fn, code_object, size, code_object_reader)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_reader_destroy, hsa_code_object_reader_destroy, hsa_code_object_reader_destroy_fn, code_object_reader)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_create_alt, hsa_executable_create_alt, hsa_executable_create_alt_fn, profile, default_float_rounding_mode, options, executable)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_load_program_code_object, hsa_executable_load_program_code_object, hsa_executable_load_program_code_object_fn, executable, code_object_reader, options, loaded_code_object)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_load_agent_code_object, hsa_executable_load_agent_code_object, hsa_executable_load_agent_code_object_fn, executable, agent, code_object_reader, options, loaded_code_object)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_validate_alt, hsa_executable_validate_alt, hsa_executable_validate_alt_fn, executable, options, result)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_get_symbol_by_name, hsa_executable_get_symbol_by_name, hsa_executable_get_symbol_by_name_fn, executable, symbol_name, agent, symbol)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_iterate_agent_symbols, hsa_executable_iterate_agent_symbols, hsa_executable_iterate_agent_symbols_fn, executable, agent, callback, data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_iterate_program_symbols, hsa_executable_iterate_program_symbols, hsa_executable_iterate_program_symbols_fn, executable, callback, data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_coherency_get_type, hsa_amd_coherency_get_type, hsa_amd_coherency_get_type_fn, agent, type)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_coherency_set_type, hsa_amd_coherency_set_type, hsa_amd_coherency_set_type_fn, agent, type)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_profiling_set_profiler_enabled, hsa_amd_profiling_set_profiler_enabled, hsa_amd_profiling_set_profiler_enabled_fn, queue, enable)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_profiling_async_copy_enable, hsa_amd_profiling_async_copy_enable, hsa_amd_profiling_async_copy_enable_fn, enable)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_profiling_get_dispatch_time, hsa_amd_profiling_get_dispatch_time, hsa_amd_profiling_get_dispatch_time_fn, agent, signal, time)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_profiling_get_async_copy_time, hsa_amd_profiling_get_async_copy_time, hsa_amd_profiling_get_async_copy_time_fn, signal, time)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_profiling_convert_tick_to_system_domain, hsa_amd_profiling_convert_tick_to_system_domain, hsa_amd_profiling_convert_tick_to_system_domain_fn, agent, agent_tick, system_tick)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_signal_async_handler, hsa_amd_signal_async_handler, hsa_amd_signal_async_handler_fn, signal, cond, value, handler, arg)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_async_function, hsa_amd_async_function, hsa_amd_async_function_fn, callback, arg)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_signal_wait_any, hsa_amd_signal_wait_any, hsa_amd_signal_wait_any_fn, signal_count, signals, conds, values, timeout_hint, wait_hint, satisfying_value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_queue_cu_set_mask, hsa_amd_queue_cu_set_mask, hsa_amd_queue_cu_set_mask_fn, queue, num_cu_mask_count, cu_mask)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_pool_get_info, hsa_amd_memory_pool_get_info, hsa_amd_memory_pool_get_info_fn, memory_pool, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_agent_iterate_memory_pools, hsa_amd_agent_iterate_memory_pools, hsa_amd_agent_iterate_memory_pools_fn, agent, callback, data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_pool_allocate, hsa_amd_memory_pool_allocate, hsa_amd_memory_pool_allocate_fn, memory_pool, size, flags, ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_pool_free, hsa_amd_memory_pool_free, hsa_amd_memory_pool_free_fn, ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_async_copy, hsa_amd_memory_async_copy, hsa_amd_memory_async_copy_fn, dst, dst_agent, src, src_agent, size, num_dep_signals, dep_signals, completion_signal)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_async_copy_on_engine, hsa_amd_memory_async_copy_on_engine, hsa_amd_memory_async_copy_on_engine_fn, dst, dst_agent, src, src_agent, size, num_dep_signals, dep_signals, completion_signal, engine_id, force_copy_on_sdma)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_copy_engine_status, hsa_amd_memory_copy_engine_status, hsa_amd_memory_copy_engine_status_fn, dst_agent, src_agent, engine_ids_mask)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_agent_memory_pool_get_info, hsa_amd_agent_memory_pool_get_info, hsa_amd_agent_memory_pool_get_info_fn, agent, memory_pool, attribute, value)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_agents_allow_access, hsa_amd_agents_allow_access, hsa_amd_agents_allow_access_fn, num_agents, agents, flags, ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_pool_can_migrate, hsa_amd_memory_pool_can_migrate, hsa_amd_memory_pool_can_migrate_fn, src_memory_pool, dst_memory_pool, result)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_migrate, hsa_amd_memory_migrate, hsa_amd_memory_migrate_fn, ptr, memory_pool, flags)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_lock, hsa_amd_memory_lock, hsa_amd_memory_lock_fn, host_ptr, size, agents, num_agent, agent_ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_unlock, hsa_amd_memory_unlock, hsa_amd_memory_unlock_fn, host_ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_fill, hsa_amd_memory_fill, hsa_amd_memory_fill_fn, ptr, value, count)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_interop_map_buffer, hsa_amd_interop_map_buffer, hsa_amd_interop_map_buffer_fn, num_agents, agents, interop_handle, flags, size, ptr, metadata_size, metadata)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_interop_unmap_buffer, hsa_amd_interop_unmap_buffer, hsa_amd_interop_unmap_buffer_fn, ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_image_create, hsa_amd_image_create, hsa_amd_image_create_fn, agent, image_descriptor, image_layout, image_data, access_permission, image)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_pointer_info, hsa_amd_pointer_info, hsa_amd_pointer_info_fn, ptr, info, alloc, num_agents_accessible, accessible)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_pointer_info_set_userdata, hsa_amd_pointer_info_set_userdata, hsa_amd_pointer_info_set_userdata_fn, ptr, userdata)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_ipc_memory_create, hsa_amd_ipc_memory_create, hsa_amd_ipc_memory_create_fn, ptr, len, handle)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_ipc_memory_attach, hsa_amd_ipc_memory_attach, hsa_amd_ipc_memory_attach_fn, handle, len, num_agents, mapping_agents, mapped_ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_ipc_memory_detach, hsa_amd_ipc_memory_detach, hsa_amd_ipc_memory_detach_fn, mapped_ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_signal_create, hsa_amd_signal_create, hsa_amd_signal_create_fn, initial_value, num_consumers, consumers, attributes, signal)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_ipc_signal_create, hsa_amd_ipc_signal_create, hsa_amd_ipc_signal_create_fn, signal, handle)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_ipc_signal_attach, hsa_amd_ipc_signal_attach, hsa_amd_ipc_signal_attach_fn, handle, signal)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_register_system_event_handler, hsa_amd_register_system_event_handler, hsa_amd_register_system_event_handler_fn, callback, data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_queue_set_priority, hsa_amd_queue_set_priority, hsa_amd_queue_set_priority_fn, queue, priority)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_async_copy_rect, hsa_amd_memory_async_copy_rect, hsa_amd_memory_async_copy_rect_fn, dst, dst_offset, src, src_offset, range, copy_agent, dir, num_dep_signals, dep_signals, completion_signal)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_lock_to_pool, hsa_amd_memory_lock_to_pool, hsa_amd_memory_lock_to_pool_fn, host_ptr, size, agents, num_agent, pool, flags, agent_ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_register_deallocation_callback, hsa_amd_register_deallocation_callback, hsa_amd_register_deallocation_callback_fn, ptr, callback, user_data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_deregister_deallocation_callback, hsa_amd_deregister_deallocation_callback, hsa_amd_deregister_deallocation_callback_fn, ptr, callback)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_signal_value_pointer, hsa_amd_signal_value_pointer, hsa_amd_signal_value_pointer_fn, signal, value_ptr)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_svm_attributes_set, hsa_amd_svm_attributes_set, hsa_amd_svm_attributes_set_fn, ptr, size, attribute_list, attribute_count)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_svm_attributes_get, hsa_amd_svm_attributes_get, hsa_amd_svm_attributes_get_fn, ptr, size, attribute_list, attribute_count)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_svm_prefetch_async, hsa_amd_svm_prefetch_async, hsa_amd_svm_prefetch_async_fn, ptr, size, agent, num_dep_signals, dep_signals, completion_signal)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_spm_acquire, hsa_amd_spm_acquire, hsa_amd_spm_acquire_fn, preferred_agent)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_spm_release, hsa_amd_spm_release, hsa_amd_spm_release_fn, preferred_agent)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_spm_set_dest_buffer, hsa_amd_spm_set_dest_buffer, hsa_amd_spm_set_dest_buffer_fn, preferred_agent, size_in_bytes, timeout, size_copied, dest, is_data_loss)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_queue_cu_get_mask, hsa_amd_queue_cu_get_mask, hsa_amd_queue_cu_get_mask_fn, queue, num_cu_mask_count, cu_mask)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_portable_export_dmabuf, hsa_amd_portable_export_dmabuf, hsa_amd_portable_export_dmabuf_fn, ptr, size, dmabuf, offset)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_portable_close_dmabuf, hsa_amd_portable_close_dmabuf, hsa_amd_portable_close_dmabuf_fn, dmabuf)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_get_capability, hsa_ext_image_get_capability, hsa_ext_image_get_capability_fn, agent, geometry, image_format, capability_mask)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_data_get_info, hsa_ext_image_data_get_info, hsa_ext_image_data_get_info_fn, agent, image_descriptor, access_permission, image_data_info)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_create, hsa_ext_image_create, hsa_ext_image_create_fn, agent, image_descriptor, image_data, access_permission, image)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_import, hsa_ext_image_import, hsa_ext_image_import_fn, agent, src_memory, src_row_pitch, src_slice_pitch, dst_image, image_region)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_export, hsa_ext_image_export, hsa_ext_image_export_fn, agent, src_image, dst_memory, dst_row_pitch, dst_slice_pitch, image_region)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_copy, hsa_ext_image_copy, hsa_ext_image_copy_fn, agent, src_image, src_offset, dst_image, dst_offset, range)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_clear, hsa_ext_image_clear, hsa_ext_image_clear_fn, agent, image, data, image_region)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_destroy, hsa_ext_image_destroy, hsa_ext_image_destroy_fn, agent, image)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_sampler_create, hsa_ext_sampler_create, hsa_ext_sampler_create_fn, agent, sampler_descriptor, sampler)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_sampler_destroy, hsa_ext_sampler_destroy, hsa_ext_sampler_destroy_fn, agent, sampler)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_get_capability_with_layout, hsa_ext_image_get_capability_with_layout, hsa_ext_image_get_capability_with_layout_fn, agent, geometry, image_format, image_data_layout, capability_mask)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_data_get_info_with_layout, hsa_ext_image_data_get_info_with_layout, hsa_ext_image_data_get_info_with_layout_fn, agent, image_descriptor, access_permission, image_data_layout, image_data_row_pitch, image_data_slice_pitch, image_data_info)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_create_with_layout, hsa_ext_image_create_with_layout, hsa_ext_image_create_with_layout_fn, agent, image_descriptor, image_data, access_permission, image_data_layout, image_data_row_pitch, image_data_slice_pitch, image)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_queue_intercept_create, hsa_amd_queue_intercept_create, hsa_amd_queue_intercept_create_fn, agent_handle, size, type, callback, data, private_segment_size, group_segment_size, queue)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_queue_intercept_register, hsa_amd_queue_intercept_register, hsa_amd_queue_intercept_register_fn, queue, callback, user_data)
|
||||
HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_runtime_queue_create_register, hsa_amd_runtime_queue_create_register, hsa_amd_runtime_queue_create_register_fn, callback, user_data)
|
||||
// clang-format on
|
||||
@@ -0,0 +1,124 @@
|
||||
// Copyright (c) 2018-2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lib/common/defines.hpp"
|
||||
#include "lib/rocprofiler/hsa/hsa-defines.hpp"
|
||||
#include "lib/rocprofiler/hsa/hsa-ostream.hpp"
|
||||
#include "lib/rocprofiler/hsa/hsa-types.h"
|
||||
#include "lib/rocprofiler/hsa/hsa-utils.hpp"
|
||||
|
||||
#include <hsa/hsa_api_trace.h>
|
||||
#include <rocprofiler/rocprofiler.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace hsa
|
||||
{
|
||||
using activity_functor_t = int (*)(rocprofiler_tracer_activity_domain_t domain,
|
||||
uint32_t operation_id,
|
||||
void* data);
|
||||
|
||||
using hsa_api_table_t = HsaApiTable;
|
||||
|
||||
struct hsa_trace_data_t
|
||||
{
|
||||
hsa_api_data_t api_data;
|
||||
uint64_t phase_enter_timestamp;
|
||||
uint64_t phase_data;
|
||||
|
||||
void (*phase_enter)(hsa_api_id_t operation_id, hsa_trace_data_t* data);
|
||||
void (*phase_exit)(hsa_api_id_t operation_id, hsa_trace_data_t* data);
|
||||
};
|
||||
|
||||
enum hsa_table_api_id_t
|
||||
{
|
||||
HSA_API_TABLE_ID_CoreApi,
|
||||
HSA_API_TABLE_ID_AmdExt,
|
||||
HSA_API_TABLE_ID_ImageExt,
|
||||
HSA_API_TABLE_ID_NUMBER,
|
||||
};
|
||||
|
||||
template <typename DataT, typename Tp>
|
||||
void
|
||||
set_data_retval(DataT&, Tp);
|
||||
|
||||
template <size_t Idx>
|
||||
struct hsa_table_lookup;
|
||||
|
||||
template <size_t Idx>
|
||||
struct hsa_api_impl
|
||||
{
|
||||
template <typename DataT, typename DataArgsT, typename... Args>
|
||||
static auto phase_enter(DataT& _data, DataArgsT&, Args... args);
|
||||
|
||||
template <typename DataT, typename... Args>
|
||||
static auto phase_exit(DataT& _data);
|
||||
|
||||
template <typename DataT, typename FuncT, typename... Args>
|
||||
static auto exec(DataT& _data, FuncT&&, Args&&... args);
|
||||
|
||||
template <typename... Args>
|
||||
static auto functor(Args&&... args);
|
||||
};
|
||||
|
||||
template <size_t Idx>
|
||||
struct hsa_api_info;
|
||||
|
||||
const char*
|
||||
hsa_api_name(uint32_t id);
|
||||
|
||||
uint32_t
|
||||
hsa_api_id_by_name(const char* name);
|
||||
|
||||
std::string
|
||||
hsa_api_data_string(uint32_t id, const hsa_trace_data_t& _data);
|
||||
|
||||
std::string
|
||||
hsa_api_named_data_string(uint32_t id, const hsa_trace_data_t& _data);
|
||||
|
||||
void
|
||||
hsa_api_iterate_args(uint32_t id,
|
||||
const hsa_trace_data_t& _data,
|
||||
int (*_func)(const char*, const char*));
|
||||
|
||||
std::vector<const char*>
|
||||
hsa_api_get_names();
|
||||
|
||||
std::vector<uint32_t>
|
||||
hsa_api_get_ids();
|
||||
|
||||
void
|
||||
hsa_api_set_callback(activity_functor_t _func);
|
||||
} // namespace hsa
|
||||
} // namespace rocprofiler
|
||||
|
||||
extern "C" {
|
||||
using on_load_t = bool (*)(HsaApiTable*, uint64_t, uint64_t, const char* const*);
|
||||
|
||||
bool
|
||||
OnLoad(HsaApiTable* table,
|
||||
uint64_t runtime_version,
|
||||
uint64_t failed_tool_count,
|
||||
const char* const* failed_tool_names) ROCPROFILER_PUBLIC_API;
|
||||
}
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -0,0 +1,515 @@
|
||||
/* Copyright (c) 2018-2022 Advanced Micro Devices, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <hsa/hsa.h>
|
||||
#include <hsa/hsa_ext_amd.h>
|
||||
#include <rocprofiler/rocprofiler.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rocprofiler_session_id_t session_id;
|
||||
rocprofiler_buffer_id_t buffer_id;
|
||||
} session_buffer_id_t;
|
||||
|
||||
typedef session_buffer_id_t roctracer_pool_t;
|
||||
|
||||
/* Correlation id */
|
||||
typedef uint64_t activity_correlation_id_t;
|
||||
|
||||
typedef uint32_t activity_kind_t;
|
||||
typedef uint32_t activity_op_t;
|
||||
|
||||
typedef uint64_t roctracer_timestamp_t;
|
||||
|
||||
typedef rocprofiler_tracer_activity_domain_t roctracer_domain_t;
|
||||
typedef rocprofiler_tracer_activity_domain_t activity_domain_t;
|
||||
|
||||
// Prof_Protocol
|
||||
/* Activity record type */
|
||||
typedef struct activity_record_s
|
||||
{
|
||||
uint32_t domain; /* activity domain id */
|
||||
activity_kind_t kind; /* activity kind */
|
||||
activity_op_t op; /* activity op */
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
activity_correlation_id_t correlation_id; /* activity ID */
|
||||
roctracer_timestamp_t begin_ns; /* host begin timestamp */
|
||||
roctracer_timestamp_t end_ns; /* host end timestamp */
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint32_t se; /* sampled SE */
|
||||
uint64_t cycle; /* sample cycle */
|
||||
uint64_t pc; /* sample PC */
|
||||
} pc_sample;
|
||||
};
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int device_id; /* device id */
|
||||
uint64_t queue_id; /* queue id */
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint32_t process_id; /* device id */
|
||||
uint32_t thread_id; /* thread id */
|
||||
};
|
||||
struct
|
||||
{
|
||||
activity_correlation_id_t external_id; /* external correlation id */
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
size_t bytes; /* data size bytes */
|
||||
const char* kernel_name; /* kernel name */
|
||||
const char* mark_message;
|
||||
};
|
||||
} activity_record_t;
|
||||
|
||||
typedef activity_record_t roctracer_record_t;
|
||||
|
||||
/* Activity sync callback type */
|
||||
typedef void (*activity_sync_callback_t)(activity_domain_t cid,
|
||||
activity_record_t* record,
|
||||
const void* data,
|
||||
void* arg);
|
||||
/* Activity async callback type */
|
||||
typedef void (*activity_async_callback_t)(activity_domain_t op, void* record, void* arg);
|
||||
|
||||
/* API callback type */
|
||||
typedef void (*activity_rtapi_callback_t)(activity_domain_t domain,
|
||||
uint32_t cid,
|
||||
const void* data,
|
||||
void* arg);
|
||||
typedef activity_rtapi_callback_t roctracer_rtapi_callback_t;
|
||||
|
||||
typedef roctracer_timestamp_t (*roctracer_get_timestamp_t)();
|
||||
typedef rocprofiler_timestamp_t (*rocprofiler_get_timestamp_t)();
|
||||
|
||||
typedef uint32_t activity_kind_t;
|
||||
typedef uint32_t activity_op_t;
|
||||
|
||||
/* API callback phase */
|
||||
typedef enum
|
||||
{
|
||||
ACTIVITY_API_PHASE_ENTER = 0,
|
||||
ACTIVITY_API_PHASE_EXIT = 1
|
||||
} activity_api_phase_t;
|
||||
|
||||
const char*
|
||||
roctracer_op_string(uint32_t domain, uint32_t op);
|
||||
|
||||
/* Trace record types */
|
||||
|
||||
/**
|
||||
* Memory pool allocator callback.
|
||||
*
|
||||
* If \p *ptr is NULL, then allocate memory of \p size bytes and save address
|
||||
* in \p *ptr.
|
||||
*
|
||||
* If \p *ptr is non-NULL and size is non-0, then reallocate the memory at \p
|
||||
* *ptr with size \p size and save the address in \p *ptr. The memory will have
|
||||
* been allocated by the same callback.
|
||||
*
|
||||
* If \p *ptr is non-NULL and size is 0, then deallocate the memory at \p *ptr.
|
||||
* The memory will have been allocated by the same callback.
|
||||
*
|
||||
* \p size is the size of the memory allocation or reallocation, or 0 if
|
||||
* deallocating.
|
||||
*
|
||||
* \p arg Argument provided
|
||||
*/
|
||||
typedef void (*roctracer_allocator_t)(char** ptr, size_t size, void* arg);
|
||||
|
||||
/**
|
||||
* Memory pool buffer callback.
|
||||
*
|
||||
* The callback that will be invoked when a memory pool buffer becomes full or
|
||||
* is flushed.
|
||||
*
|
||||
* \p begin pointer to first entry entry in the buffer.
|
||||
*
|
||||
* \p end pointer to one past the end entry in the buffer.
|
||||
*
|
||||
* \p arg the argument specified when the callback was defined.
|
||||
*/
|
||||
typedef void (*roctracer_buffer_callback_t)(const char* begin, const char* end, void* arg);
|
||||
|
||||
/**
|
||||
* Memory pool properties.
|
||||
*
|
||||
* Defines the properties when a tracer memory pool is created.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
* ROC Tracer mode.
|
||||
*/
|
||||
uint32_t mode;
|
||||
|
||||
/**
|
||||
* Size of buffer in bytes.
|
||||
*/
|
||||
size_t buffer_size;
|
||||
|
||||
/**
|
||||
* The allocator function to use to allocate and deallocate the buffer. If
|
||||
* NULL then \p malloc, \p realloc, and \p free are used.
|
||||
*/
|
||||
roctracer_allocator_t alloc_fun;
|
||||
|
||||
/**
|
||||
* The argument to pass when invoking the \p alloc_fun allocator.
|
||||
*/
|
||||
void* alloc_arg;
|
||||
|
||||
/**
|
||||
* The function to call when a buffer becomes full or is flushed.
|
||||
*/
|
||||
roctracer_buffer_callback_t buffer_callback_fun;
|
||||
|
||||
/**
|
||||
* The argument to pass when invoking the \p buffer_callback_fun callback.
|
||||
*/
|
||||
void* buffer_callback_arg;
|
||||
} roctracer_properties_t;
|
||||
|
||||
/**
|
||||
* ROC Tracer API status codes.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
* The function has executed successfully.
|
||||
*/
|
||||
ROCTRACER_STATUS_SUCCESS = 0,
|
||||
/**
|
||||
* A generic error has occurred.
|
||||
*/
|
||||
ROCTRACER_STATUS_ERROR = -1,
|
||||
/**
|
||||
* The domain ID is invalid.
|
||||
*/
|
||||
ROCTRACER_STATUS_ERROR_INVALID_DOMAIN_ID = -2,
|
||||
/**
|
||||
* An invalid argument was given to the function.
|
||||
*/
|
||||
ROCTRACER_STATUS_ERROR_INVALID_ARGUMENT = -3,
|
||||
/**
|
||||
* No default pool is defined.
|
||||
*/
|
||||
ROCTRACER_STATUS_ERROR_DEFAULT_POOL_UNDEFINED = -4,
|
||||
/**
|
||||
* The default pool is already defined.
|
||||
*/
|
||||
ROCTRACER_STATUS_ERROR_DEFAULT_POOL_ALREADY_DEFINED = -5,
|
||||
/**
|
||||
* Memory allocation error.
|
||||
*/
|
||||
ROCTRACER_STATUS_ERROR_MEMORY_ALLOCATION = -6,
|
||||
/**
|
||||
* External correlation ID pop mismatch.
|
||||
*/
|
||||
ROCTRACER_STATUS_ERROR_MISMATCHED_EXTERNAL_CORRELATION_ID = -7,
|
||||
/**
|
||||
* The operation is not currently implemented. This error may be reported by
|
||||
* any function. Check the \ref known_limitations section to determine the
|
||||
* status of the library implementation of the interface.
|
||||
*/
|
||||
ROCTRACER_STATUS_ERROR_NOT_IMPLEMENTED = -8,
|
||||
/**
|
||||
* Deprecated error code.
|
||||
*/
|
||||
ROCTRACER_STATUS_UNINIT = 2,
|
||||
/**
|
||||
* Deprecated error code.
|
||||
*/
|
||||
ROCTRACER_STATUS_BREAK = 3,
|
||||
/**
|
||||
* Deprecated error code.
|
||||
*/
|
||||
ROCTRACER_STATUS_BAD_DOMAIN = ROCTRACER_STATUS_ERROR_INVALID_DOMAIN_ID,
|
||||
/**
|
||||
* Deprecated error code.
|
||||
*/
|
||||
ROCTRACER_STATUS_BAD_PARAMETER = ROCTRACER_STATUS_ERROR_INVALID_ARGUMENT,
|
||||
/**
|
||||
* Deprecated error code.
|
||||
*/
|
||||
ROCTRACER_STATUS_HIP_API_ERR = 6,
|
||||
/**
|
||||
* Deprecated error code.
|
||||
*/
|
||||
ROCTRACER_STATUS_HIP_OPS_ERR = 7,
|
||||
/**
|
||||
* Deprecated error code.
|
||||
*/
|
||||
ROCTRACER_STATUS_HCC_OPS_ERR = ROCTRACER_STATUS_HIP_OPS_ERR,
|
||||
/**
|
||||
* Deprecated error code.
|
||||
*/
|
||||
ROCTRACER_STATUS_HSA_ERR = 7,
|
||||
/**
|
||||
* Deprecated error code.
|
||||
*/
|
||||
ROCTRACER_STATUS_ROCTX_ERR = 8,
|
||||
} roctracer_status_t;
|
||||
|
||||
/**
|
||||
* Query textual name of an operation of a domain.
|
||||
* @param[in] domain Domain being queried.
|
||||
* @param[in] op Operation within \p domain.
|
||||
* @param[in] kind \todo Define kind.
|
||||
* @return Returns the NUL terminated string for the operation name, or NULL if
|
||||
* the domain or operation are invalid. The string is owned by the ROC Tracer
|
||||
* library.
|
||||
*/
|
||||
const char*
|
||||
roctracer_op_string(uint32_t domain, uint32_t op, uint32_t kind);
|
||||
|
||||
/**
|
||||
* Query the operation code given a domain and the name of an operation.
|
||||
* @param[in] domain The domain being queried.
|
||||
* @param[in] str The NUL terminated name of the operation name being queried.
|
||||
* @param[out] op The operation code.
|
||||
* @param[out] kind If not NULL then the operation kind code.
|
||||
*/
|
||||
void
|
||||
roctracer_op_code(uint32_t domain, const char* str, uint32_t* op, uint32_t* kind);
|
||||
|
||||
/**
|
||||
* Set the properties of a domain.
|
||||
* @param[in] domain The domain.
|
||||
* @param[in] properties The properties. Each domain defines its own type for
|
||||
* the properties. Some domains require the properties to be set before they
|
||||
* can be enabled.
|
||||
*/
|
||||
void
|
||||
roctracer_set_properties(roctracer_domain_t domain, void* properties);
|
||||
|
||||
/**
|
||||
* Enable runtime API callback for a specific operation of a domain.
|
||||
* @param domain The domain.
|
||||
* @param op The operation ID in \p domain.
|
||||
* @param callback The callback to invoke each time the operation is performed
|
||||
* on entry and exit.
|
||||
* @param pool Value to pass as last argument of \p callback.
|
||||
*/
|
||||
void
|
||||
roctracer_enable_op_callback(roctracer_domain_t domain,
|
||||
uint32_t op,
|
||||
roctracer_rtapi_callback_t callback);
|
||||
|
||||
/**
|
||||
* Enable runtime API callback for all operations of a domain.
|
||||
* @param domain The domain
|
||||
* @param callback The callback to invoke each time the operation is performed
|
||||
* on entry and exit.
|
||||
* @param arg Value to pass as last argument of \p callback.
|
||||
*/
|
||||
void
|
||||
roctracer_enable_domain_callback(roctracer_domain_t domain,
|
||||
roctracer_rtapi_callback_t callback,
|
||||
void* user_data = nullptr);
|
||||
|
||||
/**
|
||||
* Disable runtime API callback for a specific operation of a domain.
|
||||
* @param domain The domain
|
||||
* @param op The operation in \p domain.
|
||||
*/
|
||||
void
|
||||
roctracer_disable_op_callback(roctracer_domain_t domain, uint32_t op);
|
||||
|
||||
/**
|
||||
* Disable runtime API callback for all operations of a domain.
|
||||
* @param domain The domain
|
||||
*/
|
||||
void
|
||||
roctracer_disable_domain_callback(roctracer_domain_t domain);
|
||||
|
||||
/**
|
||||
* Enable activity record logging for a specified operation of a domain using
|
||||
* the default memory pool.
|
||||
* @param[in] domain The domain.
|
||||
* @param[in] op The activity operation ID in \p domain.
|
||||
*/
|
||||
void
|
||||
roctracer_enable_op_activity(roctracer_domain_t domain, uint32_t op, roctracer_pool_t pool);
|
||||
|
||||
/**
|
||||
* Enable activity record logging for all operations of a domain using the
|
||||
* default memory pool.
|
||||
* @param[in] domain The domain.
|
||||
*/
|
||||
void
|
||||
roctracer_enable_domain_activity(roctracer_domain_t domain, roctracer_pool_t pool);
|
||||
|
||||
/**
|
||||
* Disable activity record logging for a specified operation of a domain.
|
||||
* @param[in] domain The domain.
|
||||
* @param[in] op The activity operation ID in \p domain.
|
||||
*/
|
||||
void
|
||||
roctracer_disable_op_activity(roctracer_domain_t domain, uint32_t op);
|
||||
|
||||
/**
|
||||
* Disable activity record logging for all operations of a domain.
|
||||
* @param[in] domain The domain.
|
||||
*/
|
||||
void
|
||||
roctracer_disable_domain_activity(roctracer_domain_t domain);
|
||||
|
||||
// HIP Support
|
||||
typedef enum
|
||||
{
|
||||
HIP_OP_ID_DISPATCH = 0,
|
||||
HIP_OP_ID_COPY = 1,
|
||||
HIP_OP_ID_BARRIER = 2,
|
||||
HIP_OP_ID_NUMBER = 3
|
||||
} hip_op_id_t;
|
||||
|
||||
// HSA Support
|
||||
// HSA OP ID enumeration
|
||||
enum hsa_op_id_t
|
||||
{
|
||||
HSA_OP_ID_DISPATCH = 0,
|
||||
HSA_OP_ID_COPY = 1,
|
||||
HSA_OP_ID_BARRIER = 2,
|
||||
HSA_OP_ID_RESERVED1 = 3,
|
||||
HSA_OP_ID_NUMBER
|
||||
};
|
||||
|
||||
// HSA EVT ID enumeration
|
||||
enum hsa_evt_id_t
|
||||
{
|
||||
HSA_EVT_ID_ALLOCATE = 0, // Memory allocate callback
|
||||
HSA_EVT_ID_DEVICE = 1, // Device assign callback
|
||||
HSA_EVT_ID_MEMCOPY = 2, // Memcopy callback
|
||||
HSA_EVT_ID_SUBMIT = 3, // Packet submission callback
|
||||
HSA_EVT_ID_KSYMBOL = 4, // Loading/unloading of kernel symbol
|
||||
HSA_EVT_ID_CODEOBJ = 5, // Loading/unloading of device code object
|
||||
HSA_EVT_ID_NUMBER
|
||||
};
|
||||
|
||||
struct hsa_ops_properties_t
|
||||
{
|
||||
void* reserved1[4];
|
||||
};
|
||||
|
||||
// ROCTx Support
|
||||
typedef uint64_t roctx_range_id_t;
|
||||
|
||||
/**
|
||||
* ROCTX API ID enumeration
|
||||
*/
|
||||
enum roctx_api_id_t
|
||||
{
|
||||
ROCTX_API_ID_roctxMarkA = 0,
|
||||
ROCTX_API_ID_roctxRangePushA = 1,
|
||||
ROCTX_API_ID_roctxRangePop = 2,
|
||||
ROCTX_API_ID_roctxRangeStartA = 3,
|
||||
ROCTX_API_ID_roctxRangeStop = 4,
|
||||
ROCTX_API_ID_NUMBER,
|
||||
};
|
||||
|
||||
/**
|
||||
* ROCTX callbacks data type
|
||||
*/
|
||||
typedef struct roctx_api_data_s
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
const char* message;
|
||||
roctx_range_id_t id;
|
||||
};
|
||||
struct
|
||||
{
|
||||
const char* message;
|
||||
} roctxMarkA;
|
||||
struct
|
||||
{
|
||||
const char* message;
|
||||
} roctxRangePushA;
|
||||
struct
|
||||
{
|
||||
const char* message;
|
||||
} roctxRangePop;
|
||||
struct
|
||||
{
|
||||
const char* message;
|
||||
roctx_range_id_t id;
|
||||
} roctxRangeStartA;
|
||||
struct
|
||||
{
|
||||
const char* message;
|
||||
roctx_range_id_t id;
|
||||
} roctxRangeStop;
|
||||
} args;
|
||||
} roctx_api_data_t;
|
||||
|
||||
// External Support
|
||||
/* Extension opcodes */
|
||||
typedef enum
|
||||
{
|
||||
ACTIVITY_EXT_OP_MARK = 0,
|
||||
ACTIVITY_EXT_OP_EXTERN_ID = 1
|
||||
} activity_ext_op_t;
|
||||
|
||||
typedef void (*roctracer_start_cb_t)();
|
||||
typedef void (*roctracer_stop_cb_t)();
|
||||
typedef struct
|
||||
{
|
||||
roctracer_start_cb_t start_cb;
|
||||
roctracer_stop_cb_t stop_cb;
|
||||
} roctracer_ext_properties_t;
|
||||
|
||||
// Tracing start
|
||||
void
|
||||
roctracer_start();
|
||||
|
||||
// Tracing stop
|
||||
void
|
||||
roctracer_stop();
|
||||
|
||||
// Notifies that the calling thread is entering an external region.
|
||||
// Push an external correlation id for the calling thread.
|
||||
void
|
||||
roctracer_activity_push_external_correlation_id(activity_correlation_id_t id);
|
||||
|
||||
// Notifies that the calling thread is leaving an external region.
|
||||
// Pop an external correlation id for the calling thread.
|
||||
// 'lastId' returns the last external correlation if not NULL
|
||||
void
|
||||
roctracer_activity_pop_external_correlation_id(activity_correlation_id_t* last_id);
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
مرجع در شماره جدید
Block a user