From 8aff2862f1a0a028601767e86ed4fea1784829f4 Mon Sep 17 00:00:00 2001 From: Giovanni LB Date: Mon, 10 Jul 2023 15:16:26 -0300 Subject: [PATCH] SWDEV-403085: Added %rank to output path and metadata to CTF. Added tests for file/ctf/perfetto plugins. Change-Id: I3b85e8a413cb99e44b7d8d5303dcb9e3520c0f04 [ROCm/rocprofiler commit: 1166f3c121f9dfa4f15673f931594d63eb44acaa] --- projects/rocprofiler/bin/rocprofv2 | 16 +- projects/rocprofiler/plugin/ctf/plugin.cpp | 35 +++ .../featuretests/profiler/profiler_gtest.cpp | 251 ++++++++++-------- .../featuretests/profiler/profiler_gtest.h | 43 +-- 4 files changed, 213 insertions(+), 132 deletions(-) diff --git a/projects/rocprofiler/bin/rocprofv2 b/projects/rocprofiler/bin/rocprofv2 index aab0348c19..4ac2e4bcb7 100755 --- a/projects/rocprofiler/bin/rocprofv2 +++ b/projects/rocprofiler/bin/rocprofv2 @@ -80,9 +80,21 @@ while [ 1 ] ; do shift elif [[ "$1" = "-d" || "$1" = "--output-directory" ]] ; then if [ $2 ] ; then - mkdir -p $2 - export OUTPUT_PATH=$2 OUTPUT_PATH_INTERNAL=$2 + MPI_RANK_INTERNAL="" + if [ -n "$MPI_RANK" ]; then + MPI_RANK_INTERNAL=$MPI_RANK + elif [ -n "$OMPI_COMM_WORLD_RANK" ]; then + MPI_RANK_INTERNAL=$OMPI_COMM_WORLD_RANK + elif [ -n "$MV2_COMM_WORLD_RANK" ]; then + MPI_RANK_INTERNAL=$MV2_COMM_WORLD_RANK + fi + if [ -n "$MPI_RANK_INTERNAL" ]; then + OUTPUT_PATH_INTERNAL=${OUTPUT_PATH_INTERNAL//"%rank"/$MPI_RANK_INTERNAL} + fi + + mkdir -p $OUTPUT_PATH_INTERNAL + export OUTPUT_PATH=$OUTPUT_PATH_INTERNAL else usage exit 1 diff --git a/projects/rocprofiler/plugin/ctf/plugin.cpp b/projects/rocprofiler/plugin/ctf/plugin.cpp index eced9a565e..ba919154e3 100644 --- a/projects/rocprofiler/plugin/ctf/plugin.cpp +++ b/projects/rocprofiler/plugin/ctf/plugin.cpp @@ -757,6 +757,23 @@ std::uint64_t GetMetadataClkClsOffset() { } // namespace + +static const char* LOOP_MPI_RANK(const std::vector& mpivars) { + for (const char* env : mpivars) + if (const char* envvar = getenv(env)) + return envvar; + return nullptr; +} + +static void insert_meta_to_stream( + std::stringstream& stream, + const char* field, + const char* value +) { + if (!field || !value) return; + stream << "\n\t" << std::string(field) << " = " << std::string(value) << ';'; +} + void Plugin::CopyAdjustedMetadataStreamFile(const fs::path& metadata_stream_path, const fs::path& trace_dir) { // Load installed metadata stream file contents. @@ -772,6 +789,24 @@ void Plugin::CopyAdjustedMetadataStreamFile(const fs::path& metadata_stream_path metadata.replace(metadata.find(offset_term), std::strlen(offset_term), ss.str()); } + std::stringstream data_stream; + const char* rank = LOOP_MPI_RANK({"MPI_RANK", "OMPI_COMM_WORLD_RANK", "MV2_COMM_WORLD_RANK"}); + // Add MPI information to metadata + if (rank) { + insert_meta_to_stream(data_stream, "rank", rank); + insert_meta_to_stream(data_stream, "node_rank", getenv("OMPI_COMM_WORLD_NODE_RANK")); + + const char* local = LOOP_MPI_RANK({"OMPI_COMM_WORLD_LOCAL_RANK", "MV2_COMM_WORLD_LOCAL_RANK"}); + insert_meta_to_stream(data_stream, "local_rank", local); + + std::string data_ins = data_stream.str(); + size_t env_pos = metadata.find("env {"); + if (env_pos != std::string::npos) + metadata.insert(metadata.begin()+env_pos+5, data_ins.begin(), data_ins.end()); + else + std::cerr << "Failed to insert MPI metadata!" << std::endl; + } + // Write adjusted metadata stream to trace directory. { std::ofstream output{trace_dir / "metadata"}; diff --git a/projects/rocprofiler/tests-v2/featuretests/profiler/profiler_gtest.cpp b/projects/rocprofiler/tests-v2/featuretests/profiler/profiler_gtest.cpp index 90879323e9..da53932d5a 100644 --- a/projects/rocprofiler/tests-v2/featuretests/profiler/profiler_gtest.cpp +++ b/projects/rocprofiler/tests-v2/featuretests/profiler/profiler_gtest.cpp @@ -31,6 +31,7 @@ THE SOFTWARE. #include #include #include +#include #include "src/utils/helper.h" #include "utils/csv_parser.h" @@ -114,6 +115,10 @@ void ApplicationParser::SetApplicationEnv(const char* app_name) { os << app_path << test_app_path << app_name; ProcessApplication(os); + + /*unsetenv("LD_LIBRARY_PATH"); + unsetenv("LD_PRELOAD"); + unsetenv("COUNTERS_PATH");*/ } /** @@ -457,6 +462,12 @@ class MPITest : public ProfilerTest { // run mpirun script // ProcessMPIApplication("mpi_run.sh"); } + + /*virtual void TearDown() override { + unsetenv("HWLOC_COMPONENTS"); + unsetenv("LD_PRELOAD"); + ProfilerTest::TearDown(); + }*/ }; void MPITest::ProcessMPIApplication(const char* app_name) { @@ -1141,133 +1152,153 @@ TEST(ProfilerMPTest, WhenRunningMultiProcessTestItPasses) { ASSERT_TRUE(1); } } - /* - * ################################################### - * ############ File plugin tests ################ - * ################################################### - */ +* ################################################### +* ############ Plugin tests ################ +* ################################################### +*/ -/** - * Sets application output dir. - */ +void PluginTests::RunApplication(const char* app_name, const char* appParams) { + init_test_path(); -// void PluginTests::RunApplication(const char* app_name, const char* appParams) { -// if (is_installed_path()) return; // Only run these tests from build + unsetenv("LD_LIBRARY_PATH"); // Cleaning up envs from other tests + unsetenv("COUNTERS_PATH"); + unsetenv("LD_PRELOAD"); + unsetenv("HWLOC_COMPONENTS"); -// init_test_path(); -// unsetenv("OUTPUT_FOLDER"); + std::string app_path = is_installed_path() ? GetRunningPath(running_path) : ""; + std::stringstream os; + os << app_path << binary_path << appParams << " "; + os << app_path << test_app_path << app_name; + ProcessApplication(os); +} -// std::stringstream os; -// os << binary_path << appParams << " "; -// os << test_app_path << app_name; -// ProcessApplication(os); -// } +void PluginTests::ProcessApplication(std::stringstream& ss) { + FILE* handle = popen(ss.str().c_str(), "w"); + ASSERT_NE(handle, nullptr); + pclose(handle); +} -// void PluginTests::ProcessApplication(std::stringstream& ss) { -// FILE* handle = popen(ss.str().c_str(), "r"); -// ASSERT_NE(handle, nullptr); -// pclose(handle); -// } +bool FilePluginTest::hasFileInDir(const std::string& filename, const char* directory) { + for (const auto& entry : std::experimental::filesystem::directory_iterator(directory)) { + if (filename.size() == 0) return true; + if (std::string(entry.path().filename()).find(filename) != std::string::npos) return true; + } + return false; +} -// bool FilePluginTest::hasFileInDir(const std::string& filename, const char* directory) { -// if (is_installed_path()) return true; // Only run these tests from build +class VectorAddFolderOnlyTest : public FilePluginTest { + protected: + virtual void SetUp() { + RunApplication( "hip_vectoradd", + " --hsa-activity --hip-activity -d /tmp/tests-v2/file/"); + } + virtual void TearDown() { + std::experimental::filesystem::remove_all("/tmp/tests-v2/file/"); + } + bool hasFile(){ return hasFileInDir(".csv", "/tmp/tests-v2/file/"); } +}; -// for (const auto& entry : std::experimental::filesystem::directory_iterator(directory)) { -// if (filename.size() == 0) return true; -// if (std::string(entry.path().filename()).substr(0, filename.size()) == filename) return true; -// } -// return false; -// } +TEST_F(VectorAddFolderOnlyTest, WhenRunningProfilerWithFilePluginTest) { + EXPECT_EQ(hasFile(), true); +} -// class VectorAddFileOnlyTest : public FilePluginTest { -// protected: -// virtual void SetUp() { RunApplication("hip_vectoradd", " --hip-activity -o file_test_name "); } -// virtual void TearDown() { -// std::string filename = "file_test_name"; -// for (const auto& entry : std::experimental::filesystem::directory_iterator("./")) -// if (std::string(entry.path().filename()).substr(0, filename.size()) == filename) -// std::experimental::filesystem::remove(entry); -// } -// bool hasFile() { return hasFileInDir("file_test_name", "."); } -// }; +class VectorAddFileAndFolderTest : public FilePluginTest { + protected: + virtual void SetUp() { + RunApplication( "hip_vectoradd", + " --hip-activity -d /tmp/tests-v2/file/ -o file_test"); + } + virtual void TearDown() { + std::experimental::filesystem::remove_all("/tmp/tests-v2/file/"); + } + bool hasFile(){ return hasFileInDir("file_test.csv", "/tmp/tests-v2/file/"); } +}; -// TEST_F(VectorAddFileOnlyTest, WhenRunningProfilerWithFilePluginTest) { EXPECT_EQ(hasFile(), -// true); } +TEST_F(VectorAddFileAndFolderTest, WhenRunningProfilerWithFilePluginTest) { + EXPECT_EQ(hasFile(), true); +} -// class VectorAddFolderOnlyTest : public FilePluginTest { -// protected: -// virtual void SetUp() { -// RunApplication("hip_vectoradd", " --hsa-activity --hip-activity -d -// ./plugin_test_folder_path"); -// } -// virtual void TearDown() { -// std::experimental::filesystem::remove_all("./plugin_test_folder_path"); -// } bool hasFile(){ return hasFileInDir("", "./plugin_test_folder_path"); } -// }; +class VectorAddFilenameMPITest : public FilePluginTest { + protected: + virtual void SetUp() { + setenv("MPI_RANK", "7", true); + RunApplication("hip_vectoradd", + " --hip-activity -d /tmp/tests-v2/file/ -o test_%rank_"); + } + virtual void TearDown() { + std::experimental::filesystem::remove_all("/tmp/tests-v2/file/"); + unsetenv("MPI_RANK"); + } + bool hasFile() { return hasFileInDir("test_7_", "/tmp/tests-v2/file/"); } +}; -// TEST_F(VectorAddFolderOnlyTest, WhenRunningProfilerWithFilePluginTest) { -// EXPECT_EQ(hasFile(), true); -// } +TEST_F(VectorAddFilenameMPITest, WhenRunningProfilerWithFilePluginTest) { + EXPECT_EQ(hasFile(), true); +} -// class VectorAddFileAndFolderTest : public FilePluginTest { -// protected: -// virtual void SetUp() { -// RunApplication("hip_vectoradd", " --hip-activity -d ./plugin_test_folder_path -o -// file_test_name"); -// } -// virtual void TearDown() { -// std::experimental::filesystem::remove_all("./plugin_test_folder_path"); -// } bool hasFile(){ return hasFileInDir("file_test_name", "./plugin_test_folder_path"); } -// }; +bool PerfettoPluginTest::hasFileInDir(const std::string& filename, const char* directory) { + for (const auto& entry : std::experimental::filesystem::directory_iterator(directory)) { + std::string entrypath = std::string(entry.path().filename()); + if (entrypath.find(".pftrace") == std::string::npos) continue; + if (entrypath.substr(0, filename.size()) == filename) return true; + } + return false; +} -// TEST_F(VectorAddFileAndFolderTest, WhenRunningProfilerWithFilePluginTest) { -// EXPECT_EQ(hasFile(), true); -// } +class VectorAddPerfettoMPITest : public PerfettoPluginTest { + protected: + virtual void SetUp() { + setenv("MPI_RANK", "7", true); + RunApplication("hip_vectoradd", + " -d /tmp/tests-v2/perfetto/ -o test_%rank_ --plugin perfetto"); + } + virtual void TearDown() { + std::experimental::filesystem::remove_all("/tmp/tests-v2/perfetto/"); + unsetenv("MPI_RANK"); + } + bool hasFile(){ return hasFileInDir("test_7_", "/tmp/tests-v2/perfetto/"); } +}; -// class VectorAddFilenameMPITest : public FilePluginTest { -// protected: -// virtual void SetUp() { -// setenv("MPI_RANK", "7", true); -// RunApplication("hip_vectoradd", " --hip-activity -d ./plugin_test_folder_path -o -// test_%rank_"); -// } -// virtual void TearDown() { -// std::experimental::filesystem::remove_all("./plugin_test_folder_path"); -// unsetenv("MPI_RANK"); -// } -// bool hasFile() { return hasFileInDir("test_7_", "./plugin_test_folder_path"); } -// }; +TEST_F(VectorAddPerfettoMPITest, WhenRunningProfilerWithPerfettoTest) { + EXPECT_EQ(hasFile(), true); +} -// TEST_F(VectorAddFilenameMPITest, WhenRunningProfilerWithFilePluginTest) { -// EXPECT_EQ(hasFile(), true); -// } +bool CTFPluginTest::hasMetadataInDir(const char* directory) { + for (const auto& entry : std::experimental::filesystem::directory_iterator(directory)) + if (std::string(entry.path().filename()) == "metadata") return true; + return false; +} -// bool PerfettoPluginTest::hasFileInDir(const std::string& filename, const char* directory) { -// if (is_installed_path()) return true; // Only run these tests from build +class VectorAddCTFTest : public CTFPluginTest { + protected: + virtual void SetUp() { + RunApplication("hip_vectoradd", " -d /tmp/tests-v2/ctf --plugin ctf"); + } + virtual void TearDown() { + std::experimental::filesystem::remove_all("/tmp/tests-v2/"); + unsetenv("MPI_RANK"); + } + bool hasFile(){ return hasMetadataInDir("/tmp/tests-v2/ctf/trace/"); } +}; -// for (const auto& entry : std::experimental::filesystem::directory_iterator(directory)) { -// std::string entrypath = std::string(entry.path().filename()); -// if (entrypath.find(".pftrace") == std::string::npos) continue; -// if (entrypath.substr(0, filename.size()) == filename) return true; -// } -// return false; -// } +TEST_F(VectorAddCTFTest, WhenRunningProfilerWithCTFTest) { + EXPECT_EQ(hasFile(), true); +} -// class VectorAddPerfettoMPITest : public PerfettoPluginTest { -// protected: -// virtual void SetUp() { -// setenv("MPI_RANK", "7", true); -// RunApplication("hip_vectoradd", " -d ./plugin_test_folder_path -o test_%rank_ --plugin -// perfetto"); -// } -// virtual void TearDown() { -// std::experimental::filesystem::remove_all("./plugin_test_folder_path"); -// unsetenv("MPI_RANK"); -// } -// bool hasFile(){ return hasFileInDir("test_7_", "./plugin_test_folder_path"); } -// }; +class VectorAddCTFMPITest : public CTFPluginTest { + protected: + virtual void SetUp() { + setenv("MPI_RANK", "7", true); + RunApplication("hip_vectoradd", " -d /tmp/tests-v2/ctf_%rank --plugin ctf"); + } + virtual void TearDown() { + std::experimental::filesystem::remove_all("/tmp/tests-v2/"); + unsetenv("MPI_RANK"); + } + bool hasFile(){ return hasMetadataInDir("/tmp/tests-v2/ctf_7/trace/"); } +}; -// TEST_F(VectorAddPerfettoMPITest, WhenRunningProfilerWithPerfettoTest) { -// EXPECT_EQ(hasFile(), true); -// } \ No newline at end of file +TEST_F(VectorAddCTFMPITest, WhenRunningProfilerWithCTFTest) { + EXPECT_EQ(hasFile(), true); +} diff --git a/projects/rocprofiler/tests-v2/featuretests/profiler/profiler_gtest.h b/projects/rocprofiler/tests-v2/featuretests/profiler/profiler_gtest.h index 7161b5a2e5..359dd8e951 100644 --- a/projects/rocprofiler/tests-v2/featuretests/profiler/profiler_gtest.h +++ b/projects/rocprofiler/tests-v2/featuretests/profiler/profiler_gtest.h @@ -98,32 +98,35 @@ class ProfilerTest : public ApplicationParser { // /* --------------------------------------------------------------------------*/ // /** -// * @Synopsis Base class for file plugin tests. +// * @Synopsis Base class for plugin tests. // * The file test will check wether certain filenames are created. // * Currently, file plugin tests only from build as they need to create files. // */ // /* --------------------------------------------------------------------------*/ -// class PluginTests : public ::testing::Test { -// public: -// //!< Sets application environment by seting rocprofv2. -// void RunApplication(const char* app_name, const char* appParams); -// private: -// //!< Runs a given appllication with the hsa activity. -// void ProcessApplication(std::stringstream& ss); -// }; +class PluginTests : public ::testing::Test { + public: + //!< Sets application environment by seting rocprofv2. + void RunApplication(const char* app_name, const char* appParams); + private: + //!< Runs a given appllication with the hsa activity. + void ProcessApplication(std::stringstream& ss); +}; +class FilePluginTest : public PluginTests { + public: + //!< Checks wether a file beginning with "filename" exists in "directory" + static bool hasFileInDir(const std::string& filename, const char* directory); +}; -// class FilePluginTest : public PluginTests { -// public: -// //!< Checks wether a file beginning with "filename" exists in "directory" -// static bool hasFileInDir(const std::string& filename, const char* directory); -// }; - -// class PerfettoPluginTest : public PluginTests { -// public: -// //!< Checks wether a file beginning with "filename" and ending with "pftrace" exists in "directory" -// static bool hasFileInDir(const std::string& filename, const char* directory); -// }; +class PerfettoPluginTest : public PluginTests { + public: + //!< Checks wether a file beginning with "filename" and ending with "pftrace" exists in "directory" + static bool hasFileInDir(const std::string& filename, const char* directory); +}; +class CTFPluginTest : public FilePluginTest { +public: + static bool hasMetadataInDir(const char* directory); +}; #endif // TESTS_FEATURETESTS_PROFILER_GTESTS_APPS_PROFILER_GTEST_H_