diff --git a/CHANGELOG.md b/CHANGELOG.md index dd6a7bb4..e4cb7345 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -147,7 +147,9 @@ Full documentation for ROCprofiler-SDK is available at [rocm.docs.amd.com/projec ### Added - Added support for select() operation in counter expression. -- Added reduce operation for counter expression wrt dimension. +- Added reduce operation for counter expression wrt dimension. +- `--collection-period` feature added in rocprofv3, to enable filtering using time. +- `--collection-period-unit` feature added in rocprofv3, to allow the user to control time units used in collection period option. ### Changed diff --git a/source/bin/rocprofv3.py b/source/bin/rocprofv3.py index e376d0d8..730654fa 100755 --- a/source/bin/rocprofv3.py +++ b/source/bin/rocprofv3.py @@ -374,6 +374,23 @@ def add_parser_bool_argument(gparser, *args, **kwargs): default=None, type=str, ) + filter_options.add_argument( + "-p", + "--collection-period", + help="The times are specified in seconds by default, but the unit can be changed using the `--collection-period-unit` or `-pu` option. Start Delay Time is the time in seconds before the collection begins, Collection Time is the duration in seconds for which data is collected, and Rate is the number of times the cycle is repeated. A repeat of 0 indicates that the cycle will repeat indefinitely. Users can specify multiple configurations, each defined by a triplet in the format `start_delay:collection_time:repeat`", + nargs="+", + default=None, + type=str, + metavar=("(START_DELAY_TIME):(COLLECTION_TIME):(REPEAT)"), + ) + filter_options.add_argument( + "--collection-period-unit", + help="To change the unit used in `--collection-period` or `-p`, you can specify the desired unit using the `--collection-period-unit` or `-pu` option. The available units are `hour` for hours, `min` for minutes, `sec` for seconds, `msec` for milliseconds, `usec` for microseconds, and `nsec` for nanoseconds", + nargs=1, + default="sec", + type=str, + choices=("hour", "min", "sec", "msec", "usec", "nsec"), + ) perfetto_options = parser.add_argument_group("Perfetto-specific options") @@ -494,7 +511,6 @@ def parse_json(json_file): def parse_text(text_file): - def process_line(line): if "pmc:" not in line: return "" @@ -561,7 +577,6 @@ def patch_args(data): def get_args(cmd_args, inp_args): - def ensure_type(name, var, type_id): if not isinstance(var, type_id): raise TypeError( @@ -850,6 +865,33 @@ def _write_env_value(): args.list_avail, overwrite_if_true=True, ) + if args.collection_period: + factors = { + "hour": 60 * 60 * 1e9, + "min": 60 * 1e9, + "sec": 1e9, + "msec": 1e6, + "usec": 1e3, + "nsec": 1, + } + + def to_nanosec(val): + return int(float(val) * factors[args.collection_period_unit[0]]) + + def convert_triplet(delay, duration, repeat): + return ":".join( + [ + f"{itr}" + for itr in [to_nanosec(delay), to_nanosec(duration), int(repeat)] + ] + ) + + periods = [convert_triplet(*itr.split(":")) for itr in args.collection_period] + update_env( + "ROCPROF_COLLECTION_PERIOD", + ";".join(periods), + overwrite_if_true=True, + ) if args.log_level and args.log_level not in ("env"): for itr in ("ROCPROF", "ROCPROFILER", "ROCTX"): diff --git a/source/docs/how-to/using-rocprofv3.rst b/source/docs/how-to/using-rocprofv3.rst index 82bfcb7b..5e0067f7 100644 --- a/source/docs/how-to/using-rocprofv3.rst +++ b/source/docs/how-to/using-rocprofv3.rst @@ -123,7 +123,7 @@ Here is the sample of commonly used ``rocprofv3`` command-line options. Some opt - Kernel Dispatch Counter Collection * - ``-L`` \| ``--list-avail`` - - List metrics for counter collection + - List metrics for counter collection - List supported PC sampling configurations. * - ``-E`` \| ``--extra_counters`` @@ -169,11 +169,19 @@ Here is the sample of commonly used ``rocprofv3`` command-line options. Some opt * - ``--pc-sampling-unit`` - The unit appropriate to the PC sampling type/method, currently only time unit is supported - PC Sampling Configurations - + * - ``--pc-sampling-interval`` - Frequency at which PC samples are generated - PC Sampling Configurations + * - ``--collection-period \| -p [(START_DELAY_TIME):(COLLECTION_TIME):(REPEAT), ...]`` + - The times are specified in seconds by default, but the unit can be changed using the `--collection-period-unit` or `-pu` option. Start Delay Time is the time in seconds before the collection begins, Collection Time is the duration in seconds for which data is collected, and Rate is the number of times the cycle is repeated. A repeat of 0 indicates that the cycle will repeat indefinitely. Users can specify multiple configurations, each defined by a triplet in the format `start_delay:collection_time:repeat`. For example, the command `-p 10:10:1 5:3:0` specifies two configurations: the first with a start delay of 10 seconds, a collection time of 10 seconds, and a repeat of 1 (the cycle will repeat once); the second with a start delay of 5 seconds, a collection time of 3 seconds, and a repeat of 0 (the cycle will repeat indefinitely). + - Filtering Options + + * - ``--collection-period-unit {hour,min,sec,msec,usec,nsec}`` + - To change the unit used in `--collection-period` or `-p`, you can specify the desired unit using the `--collection-period-unit` option. The available units are `hour` for hours, `min` for minutes, `sec` for seconds, `msec` for milliseconds, `usec` for microseconds, and `nsec` for nanoseconds. + - Filtering Options + To see exhaustive list of ``rocprofv3`` options, run: .. code-block:: bash @@ -633,23 +641,23 @@ For the description of the fields in the output file, see :ref:`output-file-fiel Output single summary of tracing data at the conclusion of the profiling session .. code-block:: shell - + rocprofv3 -S --hip-trace -- .. image:: /data/rocprofv3_summary.png - - + + 2.1 Summary per domain ++++++++++++++++++++++ -Outputs the summary of each tracing domain at the end of profiling session. +Outputs the summary of each tracing domain at the end of profiling session. .. code-block:: shell rocprofv3 -D --hsa-trace --hip-trace -- The above command generates a ``hip_trace.csv``, ``hsa_trace.csv`` file prefixed with the process ID along with the summary of each domain at the terminal. - + 2.2 Summary groups +++++++++++++++++++ @@ -666,7 +674,7 @@ To create a summary for ``MEMORY_COPY`` domains, use: To create a summary for ``MEMORY_COPY`` and ``HIP_API`` domains, use: .. code-block:: shell - + rocprofv3 --summary-groups 'MEMORY_COPY|HIP_API' --sys-trace -- .. image:: /data/rocprofv3_hip_memcpy_summary.png @@ -816,7 +824,7 @@ To supply the counters via ``command-line`` options, use: Extra-counters ++++++++++++++++ -Counters with custom definitions can be defined through an extra_counters.yaml +Counters with custom definitions can be defined through an extra_counters.yaml file using the ``command-line`` option. To supply the extra counters via ``command-line`` options, use: diff --git a/source/lib/rocprofiler-sdk-tool/config.cpp b/source/lib/rocprofiler-sdk-tool/config.cpp index d401cb21..4ba73cee 100644 --- a/source/lib/rocprofiler-sdk-tool/config.cpp +++ b/source/lib/rocprofiler-sdk-tool/config.cpp @@ -211,6 +211,18 @@ config::config() if(pc_sampling_method_value == ROCPROFILER_PC_SAMPLING_METHOD_HOST_TRAP) pc_sampling_host_trap = true; pc_sampling_unit_value = pc_sampling_unit_map.at(pc_sampling_unit); + + if(auto _collection_period = get_env("ROCPROF_COLLECTION_PERIOD", ""); + !_collection_period.empty()) + { + for(const auto& _config : sdk::parse::tokenize(_collection_period, ";")) + { + auto _config_params = sdk::parse::tokenize(_config, ":"); + collection_periods.emplace(CollectionPeriod{std::stoull(_config_params.at(0)), + std::stoull(_config_params.at(1)), + std::stoull(_config_params.at(2))}); + } + } } std::string diff --git a/source/lib/rocprofiler-sdk-tool/config.hpp b/source/lib/rocprofiler-sdk-tool/config.hpp index b7a2246c..60063439 100644 --- a/source/lib/rocprofiler-sdk-tool/config.hpp +++ b/source/lib/rocprofiler-sdk-tool/config.hpp @@ -67,6 +67,13 @@ struct config : output_config { using base_type = output_config; + struct CollectionPeriod + { + uint64_t delay = 0; + uint64_t duration = 0; + uint64_t repeat = 0; + }; + config(); ~config() = default; @@ -110,6 +117,8 @@ struct config : output_config std::unordered_set kernel_filter_range = {}; std::set counters = {}; + std::queue collection_periods = {}; + template void save(ArchiveT&) const; diff --git a/source/lib/rocprofiler-sdk-tool/tool.cpp b/source/lib/rocprofiler-sdk-tool/tool.cpp index 6435cd03..1746b718 100644 --- a/source/lib/rocprofiler-sdk-tool/tool.cpp +++ b/source/lib/rocprofiler-sdk-tool/tool.cpp @@ -60,16 +60,21 @@ #include +#include #include #include #include +#include #include #include #include +#include #include +#include #include #include #include +#include #include #include #include @@ -265,6 +270,77 @@ flush() ROCP_INFO << "Buffers flushed"; } +void +collection_period_cntrl(std::promise&& _promise, rocprofiler_context_id_t _ctx) +{ + bool testing_cp = tool::get_env("ROCPROF_COLLECTION_PERIOD_TESTING", false); + auto log_fname = get_output_filename(tool::get_config(), "collection_periods", "log"); + auto output_testing_file = std::ofstream{}; + + if(testing_cp) + { + ROCP_INFO << "collection period test logging enabled: " << log_fname; + output_testing_file.open(log_fname); + } + + auto log_period = [testing_cp, &output_testing_file]( + std::string_view label, auto _func, auto... _args) { + ROCP_INFO << "collection period: " << label; + + auto beg = rocprofiler_timestamp_t{}; + if(testing_cp) + { + rocprofiler_get_timestamp(&beg); + } + + _func(_args...); + + if(testing_cp) + { + auto end = rocprofiler_timestamp_t{}; + rocprofiler_get_timestamp(&end); + output_testing_file << label << ":" << beg << ":" << end << '\n' << std::flush; + } + }; + + auto sleep_for_nsec = [](auto _value) { + if(_value > 0) + { + std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::nanoseconds{_value}); + } + }; + + auto periods = tool::get_config().collection_periods; + _promise.set_value(); // allow the launching thread to proceed + while(!periods.empty()) + { + auto _period = periods.front(); + periods.pop(); + + auto execute_period = [&]() { + if(testing_cp) output_testing_file << "--" << '\n'; + + log_period("delay", sleep_for_nsec, _period.delay); + log_period("start", rocprofiler_start_context, _ctx); + log_period("duration", sleep_for_nsec, _period.duration); + log_period("stop", rocprofiler_stop_context, _ctx); + }; + + if(_period.repeat == 0) + { + execute_period(); + } + else + { + for(size_t i = 0; i < _period.repeat; ++i) + { + execute_period(); + } + } + } +} + int set_kernel_rename_correlation_id(rocprofiler_thread_id_t thr_id, rocprofiler_context_id_t ctx_id, @@ -553,8 +629,8 @@ code_object_tracing_callback(rocprofiler_callback_tracing_record_t record, // add the kernel to the kernel_targets if if(success) { - // if kernel name is provided by user then by default all kernels in the application - // are targeted + // if kernel name is provided by user then by default all kernels in the + // application are targeted const auto* kernel_info = CHECK_NOTNULL(tool_metadata)->get_kernel_symbol(sym_data->kernel_id); auto kernel_filter_include = tool::get_config().kernel_filter_include; @@ -711,12 +787,14 @@ get_device_counting_service(rocprofiler_agent_id_t agent_id) ROCP_FATAL_IF(dev_id_s.empty() || dev_id_s.find_first_not_of("0123456789") != std::string::npos) - << "invalid device qualifier format (':device=N) where N is the GPU id: " + << "invalid device qualifier format (':device=N) where N is the " + "GPU " + "id: " << itr; auto dev_id_v = std::stol(dev_id_s); - // skip this counter if the counter is for a specific device id (which doesn't - // this agent's device id) + // skip this counter if the counter is for a specific device id (which + // doesn't this agent's device id) if(dev_id_v != agent_v->gpu_index) { --expected_v; // is not expected @@ -1257,7 +1335,17 @@ tool_init(rocprofiler_client_finalize_t fini_func, void* tool_data) } } - ROCPROFILER_CALL(rocprofiler_start_context(get_client_ctx()), "start context failed"); + if(tool::get_config().collection_periods.empty()) + { + ROCPROFILER_CHECK(rocprofiler_start_context(get_client_ctx())); + } + else + { + auto _prom = std::promise{}; + auto _fut = _prom.get_future(); + std::thread{collection_period_cntrl, std::move(_prom), get_client_ctx()}.detach(); + _fut.wait_for(std::chrono::seconds{1}); // wait for a max of 1 second + } tool_metadata->process_id = getpid(); rocprofiler_get_timestamp(&(tool_metadata->process_start_ns)); diff --git a/source/lib/rocprofiler-sdk/context.cpp b/source/lib/rocprofiler-sdk/context.cpp index 735edb8f..5b279db1 100644 --- a/source/lib/rocprofiler-sdk/context.cpp +++ b/source/lib/rocprofiler-sdk/context.cpp @@ -79,6 +79,9 @@ rocprofiler_stop_context(rocprofiler_context_id_t context_id) !rocprofiler::context::get_registered_context(context_id)) return ROCPROFILER_STATUS_ERROR_CONTEXT_NOT_FOUND; + // if finalized, context is already stopped + if(rocprofiler::registration::get_fini_status() > 0) return ROCPROFILER_STATUS_SUCCESS; + return rocprofiler::context::stop_context(context_id); } diff --git a/source/lib/rocprofiler-sdk/context/context.cpp b/source/lib/rocprofiler-sdk/context/context.cpp index de310e88..47b66161 100644 --- a/source/lib/rocprofiler-sdk/context/context.cpp +++ b/source/lib/rocprofiler-sdk/context/context.cpp @@ -229,9 +229,13 @@ context* get_mutable_registered_context(rocprofiler_context_id_t id) { if(id.handle < get_contexts_offset()) return nullptr; + if(!get_registered_contexts_impl()) return nullptr; auto _idx = id.handle - get_contexts_offset(); - if(_idx >= get_registered_contexts_impl()->size()) return nullptr; - return &get_registered_contexts_impl()->at(_idx).value(); + if(_idx >= get_registered_contexts_impl()->size()) + return nullptr; + else if(get_registered_contexts_impl()->at(_idx).has_value()) + return &get_registered_contexts_impl()->at(_idx).value(); + return nullptr; } const context* diff --git a/tests/pytest-packages/pytest_utils/otf2_reader.py b/tests/pytest-packages/pytest_utils/otf2_reader.py index 740816fa..dc74bf08 100644 --- a/tests/pytest-packages/pytest_utils/otf2_reader.py +++ b/tests/pytest-packages/pytest_utils/otf2_reader.py @@ -78,7 +78,6 @@ def __init__(self, filename): self.filename = filename if isinstance(filename, (list, tuple)) else [filename] def read(self): - def _read_trace(trace_name): trace = otf2.reader.Reader(trace_name) # print(f"Read {len(trace.definitions.strings)} string definitions") diff --git a/tests/pytest-packages/tests/rocprofv3.py b/tests/pytest-packages/tests/rocprofv3.py index 3f809506..ed08eb7f 100644 --- a/tests/pytest-packages/tests/rocprofv3.py +++ b/tests/pytest-packages/tests/rocprofv3.py @@ -56,7 +56,6 @@ def test_perfetto_data( def test_otf2_data( otf2_data, json_data, categories=("hip", "hsa", "marker", "kernel", "memory_copy") ): - def get_operation_name(kind_id, op_id): return json_data["rocprofiler-sdk-tool"]["strings"]["buffer_records"][kind_id][ "operations" diff --git a/tests/rocprofv3/CMakeLists.txt b/tests/rocprofv3/CMakeLists.txt index 8ed9eb62..7d386d4f 100644 --- a/tests/rocprofv3/CMakeLists.txt +++ b/tests/rocprofv3/CMakeLists.txt @@ -35,3 +35,4 @@ add_subdirectory(summary) add_subdirectory(roctracer-roctx) add_subdirectory(scratch-memory) add_subdirectory(pc-sampling) +add_subdirectory(trace-period) diff --git a/tests/rocprofv3/trace-period/CMakeLists.txt b/tests/rocprofv3/trace-period/CMakeLists.txt new file mode 100644 index 00000000..435335db --- /dev/null +++ b/tests/rocprofv3/trace-period/CMakeLists.txt @@ -0,0 +1,67 @@ +# +# rocprofv3 tool tests for collection period +# +cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR) + +project( + rocprofiler-tests-rocprofv3-collection-period + LANGUAGES CXX + VERSION 0.0.0) + +find_package(rocprofiler-sdk REQUIRED) + +string(REPLACE "LD_PRELOAD=" "ROCPROF_PRELOAD=" PRELOAD_ENV + "${ROCPROFILER_MEMCHECK_PRELOAD_ENV}") + +set(collection-period-env "${PRELOAD_ENV}" ROCPROF_COLLECTION_PERIOD_TESTING=true) + +rocprofiler_configure_pytest_files(CONFIG pytest.ini COPY validate.py conftest.py) + +########################################################################################## +# +# Command line input +# +########################################################################################## + +add_test( + NAME rocprofv3-test-collection-period-execute + COMMAND + $ --runtime-trace --summary -d + ${CMAKE_CURRENT_BINARY_DIR}/collection-period -o out --output-format csv json + pftrace otf2 --log-level warning --collection-period 0:1:1 1:1:2 0.5:0.5:0 + --collection-period-unit sec -- $ 5000 4) + +set_tests_properties( + rocprofv3-test-collection-period-execute + PROPERTIES TIMEOUT 45 LABELS "integration-tests" ENVIRONMENT + "${collection-period-env}" FAIL_REGULAR_EXPRESSION + "${ROCPROFILER_DEFAULT_FAIL_REGEX}") + +add_test( + NAME rocprofv3-test-collection-period-validate + COMMAND + ${Python3_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/validate.py --json-input + ${CMAKE_CURRENT_BINARY_DIR}/collection-period/out_results.json --pftrace-input + ${CMAKE_CURRENT_BINARY_DIR}/collection-period/out_results.pftrace --otf2-input + ${CMAKE_CURRENT_BINARY_DIR}/collection-period/out_results.otf2 + --collection-period-input + ${CMAKE_CURRENT_BINARY_DIR}/collection-period/out_collection_periods.log) + +set(VALIDATION_FILES + ${CMAKE_CURRENT_BINARY_DIR}/collection-period/out_results.json + ${CMAKE_CURRENT_BINARY_DIR}/collection-period/out_collection_periods.log + ${CMAKE_CURRENT_BINARY_DIR}/collection-period/out_results.pftrace + ${CMAKE_CURRENT_BINARY_DIR}/collection-period/out_results.otf2) + +set_tests_properties( + rocprofv3-test-collection-period-validate + PROPERTIES TIMEOUT + 45 + LABELS + "integration-tests" + DEPENDS + "rocprofv3-test-collection-period-execute" + FAIL_REGULAR_EXPRESSION + "AssertionError" + ATTACHED_FILES_ON_FAIL + "${VALIDATION_FILES}") diff --git a/tests/rocprofv3/trace-period/conftest.py b/tests/rocprofv3/trace-period/conftest.py new file mode 100644 index 00000000..cf0f4746 --- /dev/null +++ b/tests/rocprofv3/trace-period/conftest.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 + +import pytest +import json +import os + +from rocprofiler_sdk.pytest_utils.dotdict import dotdict +from rocprofiler_sdk.pytest_utils import collapse_dict_list +from rocprofiler_sdk.pytest_utils.perfetto_reader import PerfettoReader +from rocprofiler_sdk.pytest_utils.otf2_reader import OTF2Reader + + +def pytest_addoption(parser): + parser.addoption( + "--json-input", + action="store", + help="Path to JSON file.", + ) + parser.addoption( + "--collection-period-input", + action="store", + help="Path to OUTPUT Timestamps file.", + ) + parser.addoption( + "--pftrace-input", + action="store", + help="Path to Perfetto trace file.", + ) + parser.addoption( + "--otf2-input", + action="store", + help="Path to OTF2 trace file.", + ) + + +@pytest.fixture +def json_data(request): + filename = request.config.getoption("--json-input") + with open(filename, "r") as inp: + return dotdict(collapse_dict_list(json.load(inp))) + + +@pytest.fixture +def collection_period_data(request): + filename = request.config.getoption("--collection-period-input") + with open(filename, "r") as inp: + data = inp.read() + + # Split the content by '--' + sections = [section.strip() for section in data.split("--") if section.strip()] + + result = [] + for section in sections: + section_data = {} + for line in section.splitlines(): + label, start, stop = [itr.strip() for itr in line.split(":")] + section_data[label] = {"start": int(start), "stop": int(stop)} + + if section_data: + result += [dotdict(section_data)] + + return result + + +@pytest.fixture +def pftrace_data(request): + filename = request.config.getoption("--pftrace-input") + return PerfettoReader(filename).read()[0] + + +@pytest.fixture +def otf2_data(request): + filename = request.config.getoption("--otf2-input") + if not os.path.exists(filename): + raise FileExistsError(f"{filename} does not exist") + return OTF2Reader(filename).read()[0] diff --git a/tests/rocprofv3/trace-period/pytest.ini b/tests/rocprofv3/trace-period/pytest.ini new file mode 100644 index 00000000..5e1e1c14 --- /dev/null +++ b/tests/rocprofv3/trace-period/pytest.ini @@ -0,0 +1,5 @@ + +[pytest] +addopts = --durations=20 -rA -s -vv +testpaths = validate.py +pythonpath = @ROCPROFILER_SDK_TESTS_BINARY_DIR@/pytest-packages diff --git a/tests/rocprofv3/trace-period/validate.py b/tests/rocprofv3/trace-period/validate.py new file mode 100644 index 00000000..9700753a --- /dev/null +++ b/tests/rocprofv3/trace-period/validate.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +import re +import sys +import pytest +import json + + +class TimeWindow(object): + + def __init__(self, beg, end): + self.offset = beg + self.duration = end - beg + + def in_region(self, val): + return val >= self.offset and val <= (self.offset + self.duration) + + def __repr__(self): + return f"[{self.offset}:{self.offset+self.duration}]" + + +def check_traces(data, valid_regions, invalid_regions, corrid_records=None): + for record in data: + corr_id = record.correlation_id.internal + rval = ( + corrid_records[corr_id] + if corrid_records is not None and corr_id in corrid_records + else record + ) + valid = [itr for itr in valid_regions if itr.in_region(rval.start_timestamp)] + assert ( + len(valid) == 1 + ), f"\nrval:\n\t{rval}\nrecord:\n\t{record}\nnot found in valid regions:\n{valid_regions}" + + invalid = [itr for itr in invalid_regions if itr.in_region(rval.start_timestamp)] + assert ( + len(invalid) == 0 + ), f"\nrval:\n\t{rval}\nrecord:\n\t{record}\nfound in invalid region(s):\n{invalid}" + + +def test_collection_period_trace(json_data, collection_period_data): + # Adding 20 us error margin to handle the time taken for the start/stop context to affect the collection + time_error_margin = 20 * 1e4 + valid_regions = [] + invalid_regions = [] + for period in collection_period_data: + _start = None + _stop = None + if "start" in period.keys(): + _start = period.start.start - time_error_margin + if "stop" in period.keys(): + _stop = period.stop.stop + time_error_margin + + if _start and _stop: + valid_regions.append(TimeWindow(_start, _stop)) + elif "duration" in period.keys(): + valid_regions.append(TimeWindow(period.duration.start, period.duration.stop)) + elif _start and not _stop: + valid_regions.append(TimeWindow(_start, _start + 10e9)) # add 10 seconds + + if "delay" in period.keys(): + invalid_regions.append(TimeWindow(period.delay.start, period.delay.stop)) + + data = json_data["rocprofiler-sdk-tool"] + corrid_records = {} + + for itr in ["hsa_api", "hip_api", "marker_api", "rccl_api"]: + grp = data.buffer_records[itr] + check_traces(grp, valid_regions, invalid_regions) + for record in grp: + corrid_records[record.correlation_id.external] = record + + +def test_perfetto_data(pftrace_data, json_data): + import rocprofiler_sdk.tests.rocprofv3 as rocprofv3 + + rocprofv3.test_perfetto_data( + pftrace_data, json_data, ("hip", "hsa", "marker", "kernel", "memory_copy") + ) + + +def test_otf2_data(otf2_data, json_data): + import rocprofiler_sdk.tests.rocprofv3 as rocprofv3 + + rocprofv3.test_otf2_data( + otf2_data, json_data, ("hip", "hsa", "marker", "kernel", "memory_copy") + ) + + +if __name__ == "__main__": + exit_code = pytest.main(["-x", __file__] + sys.argv[1:]) + sys.exit(exit_code)