From 51a6df35d1fe01be478c2be987f2ec1e20212fcb Mon Sep 17 00:00:00 2001 From: gobhardw Date: Thu, 17 Aug 2023 21:27:00 +0530 Subject: [PATCH] rocporf binary update Change-Id: I2ba07a213acc7db403b804d8136edce28df9dd14 [ROCm/rocprofiler commit: 6ee20035ddf995e9e6bec7ea3b4bb05ce1ae9ca2] --- .../src/tools/rocprofv2/CMakeLists.txt | 25 +- .../src/tools/rocprofv2/rocprofv2.cpp | 629 +++++++++++++----- projects/rocprofiler/src/tools/tool.cpp | 31 +- 3 files changed, 506 insertions(+), 179 deletions(-) diff --git a/projects/rocprofiler/src/tools/rocprofv2/CMakeLists.txt b/projects/rocprofiler/src/tools/rocprofv2/CMakeLists.txt index 8693bf308a..8532b6ff62 100644 --- a/projects/rocprofiler/src/tools/rocprofv2/CMakeLists.txt +++ b/projects/rocprofiler/src/tools/rocprofv2/CMakeLists.txt @@ -1,5 +1,13 @@ # Setting Default Binary output directory -# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + +# fmt library for formatting +include(FetchContent) +fetchcontent_declare( + fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt.git + GIT_TAG master) +fetchcontent_makeavailable(fmt) # Getting HSA Include Directory get_property( @@ -18,17 +26,20 @@ endif() file(GLOB ROCPROFV2_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) -add_executable(rocprofv2 ${ROCPROFV2_SRC_FILES}) +add_executable(rocprofv2_bin ${ROCPROFV2_SRC_FILES}) target_compile_definitions( - rocprofv2 + rocprofv2_bin PUBLIC AMD_INTERNAL_BUILD PRIVATE PROF_API_IMPL) target_include_directories( - rocprofv2 + rocprofv2_bin PUBLIC ${HSA_RUNTIME_INCLUDE_DIRECTORIES} $ $ PRIVATE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/inc) -target_link_libraries(rocprofv2 PRIVATE ${AQLPROFILE_LIB} hsa-runtime64::hsa-runtime64 - stdc++fs Threads::Threads atomic -ldl) -# install(TARGETS rocprofv2 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime) +target_link_libraries( + rocprofv2_bin PRIVATE ${AQLPROFILE_LIB} hsa-runtime64::hsa-runtime64 stdc++fs + Threads::Threads atomic -ldl fmt::fmt) + +install(TARGETS rocprofv2_bin RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT runtime) diff --git a/projects/rocprofiler/src/tools/rocprofv2/rocprofv2.cpp b/projects/rocprofiler/src/tools/rocprofv2/rocprofv2.cpp index 8d09962070..ae4b584534 100644 --- a/projects/rocprofiler/src/tools/rocprofv2/rocprofv2.cpp +++ b/projects/rocprofiler/src/tools/rocprofv2/rocprofv2.cpp @@ -1,4 +1,5 @@ -/* Copyright (c) 2022 Advanced Micro Devices, Inc. +/****************************************************************************** +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 @@ -16,199 +17,505 @@ 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. */ + THE SOFTWARE. +*******************************************************************************/ #include #include -#include -#include -#include #include #include -#include +#include +#include +#include #include +#include #include +#include +#include +#include +#include +#include +#include +#include -namespace fs = std::experimental::filesystem; +// filesystem for path resolutions +namespace fs = std::filesystem; -// Usage message -void printUsage() { - std::cout << "ROCProfiler Run Binary Usage:" << std::endl; - std::cout << "\nTo run ./run.sh PARAMs, PARAMs can be the following:" << std::endl; - std::cout << "-h | --help For showing this message" << std::endl; - std::cout << "-t | --test For Running the tests" << std::endl; - std::cout << "-mt | --mem-test For Running the Memory Leak tests" << std::endl; - std::cout << "\nTo run ./run.sh PARAMs APP_EXEC, PARAMs can be the following:" << std::endl; - std::cout << "-i | --input For adding counters file path " - "(every line in the text file represents a counter)" - << std::endl; - std::cout << "-d | --output-directory For adding output path where the " - "output files will be saved" - << std::endl; - std::cout << "-fi | --flush-interval For adding a flush interval in " - "milliseconds, every \"flush interval\" the buffers will be flushed" - << std::endl; - std::cout << "-a | --asan For adding libasan.so.6 for memory leak " - "check run requires building using -act | --asan-clean-build option" - << std::endl; +namespace rocprofiler { +namespace src { +namespace tools { + +// supported plugin list +std::vector plugins{"ctf", "perfetto", "file", "att"}; + +// set rocm path and creates sym_link to /opt/rocm if not exists already +fs::path set_rocm_path() { + // check symlink + std::vector rocm_paths; + fs::path opt_path = "/opt"; + fs::path rocm_path = "/opt/rocm"; + + // iterate and save all dirs under /opt that matches rocm + for (const auto& entry : fs::directory_iterator(opt_path)) { + if (entry.is_directory()) { + std::string dirName = entry.path().filename().string(); + if (dirName.compare(0, 4, "rocm") == 0) { + rocm_paths.push_back(entry.path()); + } + } + } + + // check if symlink already exists + bool is_sym_link = false; + for (const auto& rocm_dir : rocm_paths) { + fs::path dir_path = opt_path / rocm_dir; + if (fs::is_symlink(dir_path)) { + is_sym_link = true; + } + } + + // create a symlink if not already exists + if (!is_sym_link) { + try { + fs::create_symlink(rocm_paths[rocm_paths.size() - 1], "/opt/rocm"); + std::cout << "symbolic link created successfully." << std::endl; + } catch (const fs::filesystem_error& e) { + std::cerr << "error creating symbolic link: " << e.what() << std::endl; + } + } + return rocm_path; } -void runMemCheck(fs::path bin_path) { - fs::path counter_path = bin_path; +// usage message +void print_usage(fs::path current_path) { + fmt::print("Usage: rocprofv2 [options] [target]\n"); + fmt::print("Options:\n"); + + // help message + fmt::print(fg(fmt::color::cyan), " -h | --help\t\t"); + fmt::print("For showing this message\n"); + + // list counters + fmt::print(fg(fmt::color::cyan), " --list-counters\t"); + fmt::print("For showing all available counters for the current GPUs\n"); + + // only show tests when running from build + if (current_path.string().find("build") != std::string::npos) { + fmt::print(fg(fmt::color::cyan), " -t | --test\t\t"); + fmt::print("For Running the tests\n"); + fmt::print(fg(fmt::color::cyan), " -mt | --mem-test \t"); + fmt::print("For Running the Memory Leak tests\n"); + } + + // HIP API traces + fmt::print(fg(fmt::color::cyan), " --hip-api\t\t"); + fmt::print("For Collecting HIP API Traces\n"); + + // HIP API and Activity traces + fmt::print(fg(fmt::color::cyan), " --hip-activity | --hip-trace\n\t\t\t"); + fmt::print("For Collecting HIP API Activities Traces\n"); + + // HSA API traces + fmt::print(fg(fmt::color::cyan), " --hsa-api\t\t"); + fmt::print("For Collecting HSA API Traces\n"); + + // HSA API and Activity traces + fmt::print(fg(fmt::color::cyan), " --hsa-activity | --hsa-trace\n\t\t\t"); + fmt::print("For Collecting HSA API Activities Traces\n"); + + // ROCtx traces + fmt::print(fg(fmt::color::cyan), " --roctx-trace\t\t"); + fmt::print("For Collecting ROCTx Traces\n"); + + // HSA API traces + fmt::print(fg(fmt::color::cyan), " --kernel-trace\t\t"); + fmt::print("For Collecting Kernel dispatch Traces\n"); + + // HSA API traces + fmt::print(fg(fmt::color::cyan), " --sys-trace\t\t"); + fmt::print( + "For Collecting HIP and HSA APIs and their Activities Traces along with ROCTX and Kernel " + "Dispatch traces\n\t\t\t"); + + fmt::print(fg(fmt::color::gray), + "usage e.g: rocprofv2 --[hip-trace|hsa-trace|roctx-trace|kernel-trace|sys-trace] " + "[target]\n"); + + // plugins + fmt::print(fg(fmt::color::cyan), " --plugin [PLUGIN_NAME]\n\t\t\t"); + fmt::print("For enabling a plugin (file/perfetto/att/ctf)\n\t\t\t"); + fmt::print(fg(fmt::color::gray), + "usage(file/perfetto/ctf) e.g: rocprofv2 -i pmc.txt --plugin [file/perfetto/ctf] -d " + "out-dir [target]\n\t\t\t"); + fmt::print(fg(fmt::color::gray), + "usage(att): rocprofv2 [rocprofv2_params] --plugin att [ISA_file] [att_parameters] " + "[target]\n\t\t\t"); + fmt::print(fg(fmt::color::gray), + "use rocprofv2 --plugin att --help for ATT-specific parameters help\n"); + + // input file + fmt::print(fg(fmt::color::cyan), " -i | --input\t\t"); + fmt::print( + "For adding counters file path (every line in the text file represents a counter)\n\t\t\t"); + fmt::print(fg(fmt::color::gray), "usage: rocprofv2 -i pmc.txt -d [target]\n"); + + // output file + fmt::print(fg(fmt::color::cyan), " -o | --output-file\t\t"); + fmt::print("For the output file name\n\t\t\t"); + fmt::print(fg(fmt::color::gray), + "usage e.g:(with current dir): rocprofv2 --hip-trace -o [target]\n\t\t\t"); + fmt::print( + fg(fmt::color::gray), + "usage e.g:(with custom dir): rocprofv2 --hip-trace -d -o [target]\n"); + + // output directory + fmt::print(fg(fmt::color::cyan), " -d | --output-directory\n\t\t\t"); + fmt::print("For adding output path where the output files will be saved\n\t\t\t"); + fmt::print(fg(fmt::color::gray), + "usage e.g:(with custom dir): rocprofv2 --hip-trace -d [target]\n"); + + // flush interval + fmt::print(fg(fmt::color::cyan), " -fi | --flush-interval\n\t\t\t"); + fmt::print( + "For adding a flush interval in milliseconds, every flush interval the buffers will be " + "flushed\n\t\t\t"); + fmt::print(fg(fmt::color::gray), "usage e.g : rocprofv2 --hip-trace - fi 1000 [target]\n"); + + // trace period + fmt::print(fg(fmt::color::cyan), " -tp | --trace-period\n\t\t\t"); + fmt::print( + "For specifing a trace period in milliseconds with -tp " + "::\n\t\t\t"); + fmt::print(fg(fmt::color::gray), + "usage e.g: rocprofv2 --hip-trace -tp 1000:2000:4000 [target]\n"); +} + +// runs memory check on hip_vectoradd +void run_mem_check(fs::path bin_path) { fs::path app_path = bin_path; fs::path log_path = bin_path; - fs::path suppr_path = bin_path; - fs::path pyscript_path = bin_path; + fs::path asan_script_path = bin_path; - std::string pathenv = bin_path.replace_filename("librocprofiler_tool.so"); - pyscript_path = pyscript_path.replace_filename("tests/memorytests/test_mem.py"); - counter_path = counter_path.replace_filename("tests/memorytests/input.txt"); - suppr_path = suppr_path.replace_filename("tests/memorytests/suppr.txt"); - app_path = app_path.replace_filename( - "tests/featuretests/profiler/gtests/apps/" - "hip_vectoradd"); - log_path = log_path.replace_filename("memleaks.log"); - - std::cout << "Running Memory Leaks Check...." << std::endl; - std::string run_command = "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.6:" + pathenv + - " ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=suppressions=" + suppr_path.string() + - " COUNTERS_PATH=" + counter_path.string() + " " + app_path.string() + - " > /tmp/rocprofv2-temp 2> " + log_path.string(); - int status = system(run_command.c_str()); - if (status < 0) std::cerr << "Invalid Command!" << std::endl; + asan_script_path = + asan_script_path.string() + std::string("/tests-v2/memorytests/run_asan_tests.sh"); + app_path = app_path.string() + std::string("/tests-v2/featuretests/profiler/apps/hip_vectoradd"); + log_path = log_path.string() + std::string("memleaks.log"); std::cout << "Log with all detected leaks is available at " << log_path.string() << std::endl; - std::string python_command = "python3 " + pyscript_path.string() + " " + log_path.string(); - status = system(python_command.c_str()); - if (status < 0) std::cerr << "Invalid Command!" << std::endl; -} - -// Passes Counter -static std::atomic pass_num{1}; - -// Getting the number of passes needed using the counters file path -uint32_t getNumberOfPasses(std::string counter_path) { - // TODO(aelwazir): Adding a way to get the number of passes; - return 1; -} - -// Function to run the app for the amount of passes needed -void runApp(const char* app_path, char* const envp[], char* const args[], - uint32_t number_of_passes = 1) { - while (pass_num.load(std::memory_order_relaxed) <= number_of_passes) { - // Forking to keep the original - int status = 0; - if (fork() > 0) { - status = execve(app_path, args, envp); - std::cout << "Error: can't launch(" << app_path << "):" << std::endl; - perror("errno"); - exit(EXIT_FAILURE); - } - if (status == 0) - std::cout << "Pass(" << pass_num.fetch_add(1, std::memory_order_release) - << ") of the application: " << fs::path(app_path).filename() - << " is executed successfully!" << std::endl; + int status = system((asan_script_path.string() + " " + app_path.string()).c_str()); + if (status < 0) { + std::cerr << "Invalid Command!" << std::endl; } } -uint32_t number_of_passes = 1; +// passes counter +static std::atomic pass_num{1}; + +// function to run the app for the amount of passes needed +void run_application(const char* app_path, char* const envp[], char* const args[]) { + std::vector envp_vector; + std::vector counter_passes; + + // each line of counter input file needs a single pass + for(int i = 0; envp[i] != nullptr; ++i) + { + std::string envpString = envp[i]; + if(envpString.find("ROCPROFILER_COUNTERS") != std::string::npos) + { + counter_passes.push_back(const_cast(envp[i])); + } + else + { + envp_vector.push_back(const_cast(envp[i])); + } + } + + // no counter collection. hence need only 1 pass + if(counter_passes.empty()) + { + envp_vector[envp_vector.size()] = nullptr; + + int status = 0; + if(fork() > 0) + { + status = execve(app_path, args, envp_vector.data()); + std::cout << "error: can't launch(" << app_path << "):" << std::endl; + perror("errno"); + exit(EXIT_FAILURE); + } + envp_vector.pop_back(); + if(status == 0) + std::cout << "pass(" << pass_num.fetch_add(1, std::memory_order_release) + << ") of the application: " << fs::path(app_path).filename() + << " is executed successfully!" << std::endl; + } + // counter collection. might need multipass, depends on input file pmc lines + else + { + for(const auto& pass : counter_passes) + { + int status = 0; + + envp_vector.push_back(pass); + envp_vector[envp_vector.size()] = nullptr; + + if(fork() > 0) + { + status = execve(app_path, args, envp_vector.data()); + std::cout << "error: can't launch(" << app_path << "):" << std::endl; + perror("errno"); + exit(EXIT_FAILURE); + } + envp_vector.pop_back(); + if(status == 0) + std::cout << "pass(" << pass_num.fetch_add(1, std::memory_order_release) + << ") of the application: " << fs::path(app_path).filename() + << " is executed successfully!" << std::endl; + } + } + envp_vector.clear(); +} + +} // namespace tools +} // namespace src +} // namespace rocprofiler + +// creating a shorter alias +namespace rocprofv2 = rocprofiler::src::tools; int main(int argc, char** argv) { - // Getting Current Path + // environment variables vector + std::vector pathenv; + + // reading arguments: one env var for the whole options!! + int app_argc_start = 0; + char* app_path = nullptr; + + // att params + std::string att_argv; + std::string att_pthon3_arg; + fs::path att_py_path; + std::string att_input_path; + + // getting current path char current_path[FILENAME_MAX]; if (!getcwd(current_path, sizeof(current_path))) { throw errno; } current_path[sizeof(current_path) - 1] = '\0'; - // Getting the rocprofv2 binary path to locate rocprofiler library path - fs::path bin_path; - if (Dl_info dl_info; dladdr((void*)runApp, &dl_info) != 0) { - bin_path = fs::path(dl_info.dli_fname); + // set rocm path (/opt/rocm) + fs::path rocm_path = rocprofv2::set_rocm_path(); + + // to show usage when no arguments are given + if (argc <= 1) { + rocprofv2::print_usage(current_path); + return (EXIT_SUCCESS); } - // Environment cariables vector - std::vector pathenv; + // providing LD_PRELOAD of rocprofiler library to run_application function + std::string tool_lib_path = rocm_path.string() + "/lib/rocprofiler/librocprofiler_tool.so"; + std::string current_ld_preload; + if (getenv("LD_PRELOAD")) current_ld_preload = getenv("LD_PRELOAD"); + if (!current_ld_preload.empty()) + tool_lib_path = "LD_PRELOAD=" + current_ld_preload + ":" + tool_lib_path; + else + tool_lib_path = "LD_PRELOAD=" + current_ld_preload + tool_lib_path; + pathenv.emplace_back(tool_lib_path); - // Reading Arguments - // One ENV Var for the whole options!! - int app_argc_start = 0; - char* app_path = nullptr; + // iterate through all options for (int i = 1; i < argc; i++) { - // Help Message - if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-h") == 0) { - printUsage(); - return 1; - // Normal ROCProfiler Tests - } else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--test") == 0) { - fs::path test_path = bin_path; - test_path = test_path.replace_filename("run_tests.sh"); + // help message + if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { + rocprofv2::print_usage(current_path); + return (EXIT_SUCCESS); + } + // list counters + if (strcmp(argv[i], "--list-counters") == 0) { + fs::path ctrl_path = rocm_path.string() + "/libexec/rocprofiler/ctrl"; + std::string iterate_counters = tool_lib_path + " " + ctrl_path.string(); + int status = system(iterate_counters.c_str()); + if (status < 0) { + std::cerr << "Invalid Command!" << std::endl; + return (EXIT_FAILURE); + } + return (EXIT_SUCCESS); + } + // rocprofiler tests + else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--test") == 0) { + fs::path test_path = current_path + std::string("/run_tests.sh"); int status = system(test_path.string().c_str()); - if (status < 0) std::cerr << "Invalid Command!" << std::endl; - return 1; - // Memory Check Test - } else if (strcmp(argv[i], "-mt") == 0 || strcmp(argv[i], "--mem-test") == 0) { - runMemCheck(bin_path); - return 1; - // Counters File - } else if (strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "--input") == 0) { + if (status < 0) { + std::cerr << "Invalid Command!" << std::endl; + return (EXIT_FAILURE); + } + return (EXIT_SUCCESS); + } + // memory check tests + else if (strcmp(argv[i], "-mt") == 0 || strcmp(argv[i], "--mem-test") == 0) { + rocprofv2::run_mem_check(current_path); + return (EXIT_SUCCESS); + } + // counters file + else if (strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "--input") == 0) { i++; if (argv[i]) { - std::string counters_path = std::string(current_path) + "/" + argv[2]; - std::cout << "Reading counters from: " << counters_path << std::endl; - number_of_passes = getNumberOfPasses(counters_path); + std::string counters_path; + if (!fs::path(argv[i]).is_absolute()) { + counters_path = std::string(current_path) + "/" + argv[i]; + } else { + counters_path = argv[i]; + } + std::cout << "reading counters from: " << counters_path << std::endl; pathenv.emplace_back("COUNTERS_PATH=" + counters_path); + + // setting att input path for later + att_input_path = counters_path; + + std::ifstream inputfile(counters_path); + std::string pmc_line; + while (std::getline(inputfile, pmc_line)) { + // std::cout << "ROCPROFILER_COUNTERS=" + pmc_line << std::endl; + pathenv.emplace_back("ROCPROFILER_COUNTERS=" + pmc_line); + } + + // close the file. + inputfile.close(); + + } else { std::cerr << "Error: Missing Counters File path!" << std::endl; - printUsage(); + rocprofv2::print_usage(current_path); exit(EXIT_FAILURE); } - // Output Directory + + } // HIP API trace + else if (strcmp(argv[i], "--hip-api") == 0) { + if (argv[i]) { + pathenv.emplace_back("ROCPROFILER_HIP_API_TRACE=1"); + } + // HIP trace + } else if (strcmp(argv[i], "--hip-trace") == 0 || strcmp(argv[i], "--hip-activity") == 0) { + if (argv[i]) { + pathenv.emplace_back("ROCPROFILER_HIP_API_TRACE=1"); + pathenv.emplace_back("ROCPROFILER_HIP_ACTIVITY_TRACE=1"); + } + // HSA API trace + } else if (strcmp(argv[i], "--hsa-api") == 0) { + if (argv[i]) { + pathenv.emplace_back("ROCPROFILER_HSA_API_TRACE=1"); + } + // HSA trace + } else if (strcmp(argv[i], "--hsa-trace") == 0 || strcmp(argv[i], "--hsa-activity") == 0) { + if (argv[i]) { + pathenv.emplace_back("ROCPROFILER_HSA_API_TRACE=1"); + pathenv.emplace_back("ROCPROFILER_HSA_ACTIVITY_TRACE=1"); + } + // ROCTx trace + } else if (strcmp(argv[i], "--roctx-trace") == 0) { + if (argv[i]) { + pathenv.emplace_back("ROCPROFILER_ROCTX_TRACE=1"); + } + // kernel trace + } else if (strcmp(argv[i], "--kernel-trace") == 0) { + if (argv[i]) { + pathenv.emplace_back("ROCPROFILER_KERNEL_TRACE=1"); + } + // sys trace + } else if (strcmp(argv[i], "--sys-trace") == 0) { + if (argv[i]) { + pathenv.emplace_back("ROCPROFILER_HIP_API_TRACE=1"); + pathenv.emplace_back("ROCPROFILER_HIP_ACTIVITY_TRACE=1"); + pathenv.emplace_back("ROCPROFILER_HSA_API_TRACE=1"); + pathenv.emplace_back("ROCPROFILER_HSA_ACTIVITY_TRACE=1"); + pathenv.emplace_back("ROCPROFILER_ROCTX_TRACE=1"); + pathenv.emplace_back("ROCPROFILER_KERNEL_TRACE=1"); + } + // plugins + } else if (strcmp(argv[i], "--plugin") == 0) { + i++; + auto it = + std::find(rocprofv2::plugins.begin(), rocprofv2::plugins.end(), std::string(argv[i])); + if (it == rocprofv2::plugins.end()) { + rocprofv2::print_usage(current_path); + exit(EXIT_FAILURE); + } + pathenv.emplace_back("ROCPROFILER_PLUGIN_LIB=lib" + std::string(argv[i]) + "_plugin.so"); + if (std::string(argv[i]) == "att") { + att_py_path = rocm_path.string() + std::string("/libexec/rocprofiler/att/att.py"); + pathenv.emplace_back("ROCPROFV2_ATT_LIB_PATH=" + rocm_path.string() + + "/lib/hsa-amd-aqlprofile/librocprofv2_att.so"); + i++; + att_argv = argv[3]; + att_pthon3_arg = "python3"; + i++; + att_argv = ""; + for (int i = 4; i < argc; i++) { + if (std::string(argv[i]) == "--trace-file") { + att_argv = att_argv + " " + argv[i] + " " + argv[i + 1]; + i = i + 1; + } else if (std::string(argv[i]) == "--mpi") { + att_pthon3_arg = "mpirun -np " + std::string(argv[i]) + " python3"; + i = i + 1; + } else if (std::string(argv[i]) == "--mode" || std::string(argv[i]) == "--ports" || + std::string(argv[i]) == "--genasm" || std::string(argv[i]) == "--att_kernel" || + std::string(argv[i]) == "--depth") { + att_argv = att_argv + " " + argv[i] + " " + argv[i + 1] + " " + argv[i - 1]; + i = i + 1; + } else { + continue; + } + } // for loop + } + // output directory } else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--output-directory") == 0) { i++; if (argv[i]) { - std::string output_path = std::string(current_path) + "/" + argv[2]; - fs::create_directory(output_path); - std::cout << "Output directory path: " << output_path << std::endl; - pathenv.emplace_back("OUTPUT_PATH=" + output_path); + pathenv.emplace_back("OUTPUT_PATH_INTERNAL=" + std::string(argv[i])); + pathenv.emplace_back("OUTPUT_PATH=" + std::string(argv[i])); } else { std::cerr << "Error: Missing output directory path!" << std::endl; - printUsage(); + rocprofv2::print_usage(current_path); exit(EXIT_FAILURE); } - // ASAN run - } else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--asan") == 0) { - std::string current_ld_preload{getenv("LD_PRELOAD")}; - std::string ld_preload = "/usr/lib/x86_64-linux-gnu/libasan.so.6"; - if (!current_ld_preload.empty()) ld_preload = current_ld_preload + ":" + ld_preload; - - std::cout << ld_preload << std::endl; - pathenv.emplace_back("LD_PRELOAD=" + ld_preload); - pathenv.emplace_back("ASAN_OPTIONS=detect_leaks=1"); - - fs::path suppr_path = bin_path; - std::string suppr = - "suppressions=" + suppr_path.replace_filename("tests/memorytests/suppr.txt").string(); - std::cout << suppr << std::endl; - pathenv.emplace_back("LSAN_OPTIONS=" + suppr); - // Flush Interval + } // output file name + else if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--output-file-name") == 0) { + i++; + if (argv[i]) { + pathenv.emplace_back("OUT_FILE_NAME=" + std::string(argv[i])); + } else { + std::cerr << "Error: Missing output file name!" << std::endl; + rocprofv2::print_usage(current_path); + exit(EXIT_FAILURE); + } + // flush interval } else if (strcmp(argv[i], "-fi") == 0 || strcmp(argv[i], "--flush-interval") == 0) { i++; if (argv[i]) { pathenv.emplace_back("ROCPROFILER_FLUSH_INTERVAL=" + std::string(argv[i])); } else { std::cerr << "Error: Missing flush interval value!" << std::endl; - printUsage(); + rocprofv2::print_usage(current_path); exit(EXIT_FAILURE); } - // Wrong argument given + // trace period + } else if (strcmp(argv[i], "-tp") == 0 || strcmp(argv[i], "--trace-period") == 0) { + i++; + if (argv[i]) { + pathenv.emplace_back("ROCPROFILER_TRACE_PERIOD=" + std::string(argv[i])); + } else { + std::cerr << "Error: Missing trace period value!" << std::endl; + rocprofv2::print_usage(current_path); + exit(EXIT_FAILURE); + } + // wrong argument given } else if (argv[i][0] == '-') { std::cerr << "Wrong option (" << argv[i] << "), Please use the following options:\n" << std::endl; - printUsage(); + rocprofv2::print_usage(current_path); exit(EXIT_FAILURE); - // Taking up the Application path with its arguments + // taking up the Application path with its arguments } else { app_path = argv[i]; app_argc_start = i; @@ -216,7 +523,7 @@ int main(int argc, char** argv) { } } - // Getting Original Application Arguments + // getting original application arguments char* app_args[argc - app_argc_start + 1]; int j = 0; for (int i = app_argc_start; i < argc; i++) { @@ -225,32 +532,40 @@ int main(int argc, char** argv) { } app_args[j] = NULL; - // Providing LD_PRELOAD of ROCProfiler Library to runApp function - std::string pathenv_str = "LD_PRELOAD=librocprofiler_tool.so"; - std::string current_ld_preload; - if (getenv("LD_PRELOAD")) current_ld_preload = getenv("LD_PRELOAD"); - if (strstr(bin_path.c_str(), "build") != nullptr) - pathenv_str = bin_path.replace_filename("librocprofiler_tool.so"); - else - pathenv_str = bin_path.remove_filename().replace_filename("lib/librocprofiler_tool.so"); - if (!current_ld_preload.empty()) - pathenv_str = "LD_PRELOAD=" + current_ld_preload + ":" + pathenv_str; - else - pathenv_str = "LD_PRELOAD=" + current_ld_preload + pathenv_str; - pathenv.emplace_back(pathenv_str); - - // Providing all Environment variables needed by the arguments + // providing all environment variables needed by the arguments char* envp_run[pathenv.size() + 1]; for (uint32_t i = 0; i < pathenv.size(); i++) envp_run[i] = const_cast(pathenv.at(i).c_str()); envp_run[pathenv.size()] = NULL; - // Getting Application Executable path to be provided to runApp function + // getting application executable path to be provided to run_application function std::string app_path_str; - if (app_path) app_path_str = std::string(current_path) + "/" + std::string(app_path); + if (!fs::path(app_path).is_absolute()) { + app_path_str = std::string(current_path) + "/" + std::string(app_path); + } else { + app_path_str = app_path; + } + + // providing metrics path + std::string metrics_path_str = + rocm_path.string() + "/libexec/rocprofiler/counters/derived_counters.xml"; + pathenv.emplace_back("ROCPROFILER_METRICS_PATH=" + metrics_path_str); + + // ATT: check if the att required environment variables are set. + if (!att_py_path.empty()) { + if (!att_argv.empty()) { + std::string command = att_pthon3_arg + " " + att_py_path.string() + " " + att_argv; + setenv("COUNTERS_PATH", att_input_path.c_str(), 1); + int status = system(command.c_str()); + if (status < 0) { + std::cerr << "Invalid Command!" << std::endl; + return (EXIT_FAILURE); + } + } + } + // calling run_application function to execute the application with environment variables and + // original arguments + rocprofv2::run_application(app_path_str.c_str(), envp_run, app_args); - // Calling runApp function to execute the application with Environment - // variables and original arguments - runApp(app_path_str.c_str(), envp_run, app_args, number_of_passes); return 1; -} \ No newline at end of file +} diff --git a/projects/rocprofiler/src/tools/tool.cpp b/projects/rocprofiler/src/tools/tool.cpp index c67f569382..7289b305a3 100644 --- a/projects/rocprofiler/src/tools/tool.cpp +++ b/projects/rocprofiler/src/tools/tool.cpp @@ -309,11 +309,10 @@ att_parsed_input_t GetATTParams() { // Default values used for token generation. std::unordered_map default_params = { - {"SE_MASK", 0x111111}, // One every 4 SEs, by default - {"SIMD_SELECT", 0x3}, // 0x3 works for both gfx9 and Navi - {"BUFFER_SIZE", 0x40000000}, // 2^30 == 1GB - {"ISA_CAPTURE_MODE", static_cast(ROCPROFILER_CAPTURE_SYMBOLS_ONLY)} - }; + {"SE_MASK", 0x111111}, // One every 4 SEs, by default + {"SIMD_SELECT", 0x3}, // 0x3 works for both gfx9 and Navi + {"BUFFER_SIZE", 0x40000000}, // 2^30 == 1GB + {"ISA_CAPTURE_MODE", static_cast(ROCPROFILER_CAPTURE_SYMBOLS_ONLY)}}; std::ifstream trace_file(path); if (!trace_file.is_open()) { @@ -338,14 +337,15 @@ att_parsed_input_t GetATTParams() { if (pos == std::string::npos) continue; param_name = line.substr(0, pos); - for (auto& c : param_name) c = (char)toupper(c); // So we don't have to worry about lowercase inputs - line = line.substr(pos+1); + for (auto& c : param_name) + c = (char)toupper(c); // So we don't have to worry about lowercase inputs + line = line.substr(pos + 1); } if (param_name.find("ATT") != std::string::npos && param_name.find("TARGET_CU") != std::string::npos) { - started_att_counters = true; // Means we'll do ATT - param_name = "TARGET_CU"; // To cover different variations + started_att_counters = true; // Means we'll do ATT + param_name = "TARGET_CU"; // To cover different variations } if (!started_att_counters) continue; @@ -364,7 +364,7 @@ att_parsed_input_t GetATTParams() { int rank = (comma < line.size() - 1) ? stoi(line.substr(comma + 1)) : 0; if (MPI_RANK < 0 || rank == MPI_RANK) // Only add ID if rank matches the one in input.txt - dispatch_ids.push_back(std::max(id-1,0)); // off by 1 in relation to kernel-trace + dispatch_ids.push_back(std::max(id - 1, 0)); // off by 1 in relation to kernel-trace continue; } // param_value is a number @@ -439,7 +439,7 @@ void finish() { static bool env_var_search(std::string& s) { std::smatch m; - std::regex e ("(.*)\\%\\q\\{([^}]+)\\}(.*)"); + std::regex e("(.*)\\%\\q\\{([^}]+)\\}(.*)"); std::regex_match(s, m, e); if (m.size() != 4) return false; @@ -447,7 +447,7 @@ static bool env_var_search(std::string& s) { while (m.size() == 4) { const char* envvar = getenv(m[2].str().c_str()); if (!envvar) envvar = ""; - s = m[1].str()+envvar+m[3].str(); + s = m[1].str() + envvar + m[3].str(); std::regex_match(s, m, e); }; @@ -482,12 +482,13 @@ void plugins_load(void* userdata) { if (out_path.size()) { try { std::experimental::filesystem::create_directories(out_path); - } catch (...) {} + } catch (...) { + } out_path = out_path + '/'; } if (out_path.size() && getenv("ROCPROFILER_COUNTERS")) { - std::ofstream(out_path+"pmc.txt", std::ios::app) - << std::string(getenv("ROCPROFILER_COUNTERS")) << '\n'; + std::ofstream(out_path + "pmc.txt", std::ios::app) + << std::string(getenv("ROCPROFILER_COUNTERS")) << '\n'; } PluginHeaderPacket header{