diff --git a/source/lib/rocprofiler-sdk-tool/config.cpp b/source/lib/rocprofiler-sdk-tool/config.cpp index 65f8fdec..e3744d7a 100644 --- a/source/lib/rocprofiler-sdk-tool/config.cpp +++ b/source/lib/rocprofiler-sdk-tool/config.cpp @@ -161,14 +161,14 @@ get_kernel_filter_range(const std::string& kernel_filter) { if(kernel_filter.empty()) return {}; - auto delim = rocprofiler::sdk::parse::tokenize(kernel_filter, ","); + auto delim = rocprofiler::sdk::parse::tokenize(kernel_filter, "[], "); auto range_set = std::unordered_set{}; for(const auto& itr : delim) { - if(itr.find('-') != std::string::npos && itr.find('[') != std::string::npos && - itr.find(']') != std::string::npos) + if(itr.find('-') != std::string::npos) { - auto drange = rocprofiler::sdk::parse::tokenize(itr, "[-] "); + auto drange = rocprofiler::sdk::parse::tokenize(itr, "- "); + ROCP_FATAL_IF(drange.size() != 2) << "bad range format for '" << itr << "'. Expected [A-B] where A and B are numbers"; @@ -179,14 +179,9 @@ get_kernel_filter_range(const std::string& kernel_filter) } else { - auto dval = rocprofiler::sdk::parse::tokenize(itr, " "); - ROCP_ERROR_IF(dval.empty()) << "kernel range value '" << itr << "' produced no numbers"; - for(const auto& ditr : dval) - { - ROCP_FATAL_IF(ditr.find_first_not_of("0123456789") != std::string::npos) - << "expected integer for " << itr << ". Non-integer value detected"; - range_set.emplace(std::stoul(ditr)); - } + ROCP_FATAL_IF(itr.find_first_not_of("0123456789") != std::string::npos) + << "expected integer for " << itr << ". Non-integer value detected"; + range_set.emplace(std::stoul(itr)); } } return range_set; diff --git a/tests/rocprofv3/counter-collection/CMakeLists.txt b/tests/rocprofv3/counter-collection/CMakeLists.txt index 1270ef5e..a320b7a9 100644 --- a/tests/rocprofv3/counter-collection/CMakeLists.txt +++ b/tests/rocprofv3/counter-collection/CMakeLists.txt @@ -7,3 +7,4 @@ add_subdirectory(input2) add_subdirectory(input3) add_subdirectory(list_metrics) add_subdirectory(kernel_filtering) +add_subdirectory(range_filtering) diff --git a/tests/rocprofv3/counter-collection/range_filtering/CMakeLists.txt b/tests/rocprofv3/counter-collection/range_filtering/CMakeLists.txt new file mode 100644 index 00000000..9fe274db --- /dev/null +++ b/tests/rocprofv3/counter-collection/range_filtering/CMakeLists.txt @@ -0,0 +1,49 @@ +# +# rocprofv3 tool test +# +cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR) + +project( + rocprofiler-tests-counter-collection + LANGUAGES CXX + VERSION 0.0.0) + +find_package(rocprofiler-sdk REQUIRED) + +rocprofiler_configure_pytest_files(CONFIG pytest.ini COPY validate.py conftest.py + input_range.json) + +add_test( + NAME rocprofv3-test-cc-kernel-filtering-range-filter-execute + COMMAND + $ -i + ${CMAKE_CURRENT_BINARY_DIR}/input_range.json -d + ${CMAKE_CURRENT_BINARY_DIR}/range_filter -- $ 1 15) + +string(REPLACE "LD_PRELOAD=" "ROCPROF_PRELOAD=" PRELOAD_ENV + "${ROCPROFILER_MEMCHECK_PRELOAD_ENV}") + +set(cc-env-kernel-filtering "${PRELOAD_ENV}") + +set_tests_properties( + rocprofv3-test-cc-kernel-filtering-range-filter-execute + PROPERTIES TIMEOUT 45 LABELS "integration-tests" ENVIRONMENT + "${cc-env-kernel-filtering}" FAIL_REGULAR_EXPRESSION + "${ROCPROFILER_DEFAULT_FAIL_REGEX}") + +add_test( + NAME rocprofv3-test-cc-kernel-filtering-range-filter-validate + COMMAND + ${Python3_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/validate.py --json-config + ${CMAKE_CURRENT_BINARY_DIR}/input_range.json --input-json-pass1 + ${CMAKE_CURRENT_BINARY_DIR}/range_filter/pass_1/out_results.json + --input-json-pass2 + ${CMAKE_CURRENT_BINARY_DIR}/range_filter/pass_2/out_results.json + --input-json-pass3 + ${CMAKE_CURRENT_BINARY_DIR}/range_filter/pass_3/out_results.json) + +set_tests_properties( + rocprofv3-test-cc-kernel-filtering-range-filter-validate + PROPERTIES TIMEOUT 45 LABELS "integration-tests" DEPENDS + "rocprofv3-test-cc-kernel-filtering-range-filter-execute" + FAIL_REGULAR_EXPRESSION "${ROCPROFILER_DEFAULT_FAIL_REGEX}") diff --git a/tests/rocprofv3/counter-collection/range_filtering/conftest.py b/tests/rocprofv3/counter-collection/range_filtering/conftest.py new file mode 100644 index 00000000..430e5eeb --- /dev/null +++ b/tests/rocprofv3/counter-collection/range_filtering/conftest.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 + +import json +import pytest +import pandas as pd +import re + +from rocprofiler_sdk.pytest_utils.dotdict import dotdict +from rocprofiler_sdk.pytest_utils import collapse_dict_list + + +def pytest_addoption(parser): + + parser.addoption( + "--input-json-pass1", + action="store", + help="Path to JSON file.", + ) + + parser.addoption( + "--input-json-pass2", + action="store", + help="Path to JSON file.", + ) + + parser.addoption( + "--input-json-pass3", + action="store", + help="Path to JSON file.", + ) + + parser.addoption( + "--json-config", + action="store", + help="Path to input JSON file.", + ) + + +def extract_iteration_list(jobs, pass_): + + kernel_iteration_range = jobs[pass_]["kernel_iteration_range"] + _range = re.split(r"\[|,|\],|\[|,|\]", kernel_iteration_range) + _range = list(filter(lambda itr: itr != "", _range)) + range_list = [] + for itr in _range: + if "-" in itr: + interval = re.split("-", itr) + range_list.append(list(range((int)(interval[0]), (int)(interval[1])))) + else: + + range_list.append(itr) + return range_list + + +def process_config(out_file, input_config, pass_): + + ret_dict = {} + + with open(out_file, "r") as inp: + ret_dict["json_data"] = dotdict(collapse_dict_list(json.load(inp))) + + with open(input_config, "r") as inp: + jobs = dotdict(collapse_dict_list(json.load(inp)))["jobs"] + ret_dict["iteration_range"] = extract_iteration_list(jobs, pass_) + + return ret_dict + + +@pytest.fixture +def input_json_pass1(request): + out_file = request.config.getoption("--input-json-pass1") + input_config = request.config.getoption("--json-config") + return process_config(out_file, input_config, 0) + + +@pytest.fixture +def input_json_pass2(request): + out_file = request.config.getoption("--input-json-pass2") + input_config = request.config.getoption("--json-config") + return process_config(out_file, input_config, 1) + + +@pytest.fixture +def input_json_pass3(request): + out_file = request.config.getoption("--input-json-pass3") + input_config = request.config.getoption("--json-config") + return process_config(out_file, input_config, 2) diff --git a/tests/rocprofv3/counter-collection/range_filtering/input_range.json b/tests/rocprofv3/counter-collection/range_filtering/input_range.json new file mode 100644 index 00000000..02e64102 --- /dev/null +++ b/tests/rocprofv3/counter-collection/range_filtering/input_range.json @@ -0,0 +1,37 @@ +{ + "jobs": [ + { + "pmc": [ + "SQ_WAVES" + ], + "kernel_iteration_range": "[1, 3, 5, [8-12]]", + "kernel_include_regex" : "transpose", + "output_file": "out", + "truncate_kernels": true, + "kernel_trace" : true, + "output_format" : ["json"] + }, + { + "pmc": [ + "SQ_WAVES" + ], + "kernel_iteration_range": "[11-14], [4-5]", + "output_file": "out", + "truncate_kernels": true, + "kernel_trace" : true, + "output_format" : ["json"] + }, + + { + "pmc": [ + "SQ_WAVES" + ], + "kernel_iteration_range": "[[3-6], 1, 13]", + "output_file": "out", + "truncate_kernels": true, + "kernel_trace" : true, + "output_format" : ["json"] + } + + ] +} diff --git a/tests/rocprofv3/counter-collection/range_filtering/pytest.ini b/tests/rocprofv3/counter-collection/range_filtering/pytest.ini new file mode 100644 index 00000000..5e1e1c14 --- /dev/null +++ b/tests/rocprofv3/counter-collection/range_filtering/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/counter-collection/range_filtering/validate.py b/tests/rocprofv3/counter-collection/range_filtering/validate.py new file mode 100644 index 00000000..3f875622 --- /dev/null +++ b/tests/rocprofv3/counter-collection/range_filtering/validate.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 + +import sys +import pytest +import numpy as np +import pandas as pd +import re + + +def unique(lst): + return list(set(lst)) + + +def validate_json(input_data): + json_data = input_data["json_data"] + iteration_list = input_data["iteration_range"] + + data = json_data["rocprofiler-sdk-tool"] + counter_collection_data = data["callback_records"]["counter_collection"] + kernel_dispatch_data = data["buffer_records"]["kernel_dispatch"] + dispatch_ids = {} + + def get_kernel_name(kernel_id): + return data["kernel_symbols"][kernel_id]["formatted_kernel_name"] + + iteration = 1 + for dispatch in kernel_dispatch_data: + dispatch_info = dispatch["dispatch_info"] + kernel_name = get_kernel_name(dispatch_info["kernel_id"]) + if kernel_name == "transpose": + if iteration in iteration_list: + dispatch_ids[dispatch_info[dispatch_id]] = dispatch_info + iteration = iteration + 1 + + for counter in counter_collection_data: + dispatch_data = counter["dispatch_data"]["dispatch_info"] + dispatch_id = dispatch_data["dispatch_id"] + if dispatch_id in dispatch_ids.keys(): + assert dispatch_data == dispatch_ids[dispatch_id] + + +def test_validate_counter_collection_pass1(input_json_pass1): + validate_json(input_json_pass1) + + +def test_validate_counter_collection_pass2(input_json_pass2): + validate_json(input_json_pass2) + + +def test_validate_counter_collection_pass3(input_json_pass3): + validate_json(input_json_pass3) + + +if __name__ == "__main__": + exit_code = pytest.main(["-x", __file__] + sys.argv[1:]) + sys.exit(exit_code)