rocporf binary update
Change-Id: I2ba07a213acc7db403b804d8136edce28df9dd14
[ROCm/rocprofiler commit: 6ee20035dd]
Этот коммит содержится в:
коммит произвёл
Gopesh Bhardwaj
родитель
be079032bb
Коммит
51a6df35d1
@@ -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}
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/inc>
|
||||
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)
|
||||
|
||||
@@ -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 <dlfcn.h>
|
||||
#include <link.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <experimental/filesystem>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/color.h>
|
||||
|
||||
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<std::string> 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<std::string> 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 <file_name> [target]\n\t\t\t");
|
||||
fmt::print(
|
||||
fg(fmt::color::gray),
|
||||
"usage e.g:(with custom dir): rocprofv2 --hip-trace -d <out_dir> -o <file_name> [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 <out_dir> [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 "
|
||||
"<DELAY>:<ACTIVE_TIME>:<LOOP_RESET_TIME>\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<uint32_t> 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<uint32_t> 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<char*> envp_vector;
|
||||
std::vector<char*> 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<char*>(envp[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
envp_vector.push_back(const_cast<char*>(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<std::string> 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<std::string> 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<char*>(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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,11 +309,10 @@ att_parsed_input_t GetATTParams() {
|
||||
|
||||
// Default values used for token generation.
|
||||
std::unordered_map<std::string, uint32_t> 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<uint32_t>(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<uint32_t>(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{
|
||||
|
||||
Ссылка в новой задаче
Block a user