From 14557e71d55e8d26d8c7f3e3912979b54e6e86ba Mon Sep 17 00:00:00 2001 From: Jim Flynn Date: Mon, 16 Dec 2019 11:50:29 +0000 Subject: IVGCVSW-4271 Add getSupportedOperations marker file * Also fix segfault in previous graph dump code Change-Id: I01915f47ae17d89ad3595430d073a17b1a1fda58 Signed-off-by: Jim Flynn --- 1.2/ArmnnDriver.hpp | 2 +- 1.2/ArmnnDriverImpl.cpp | 15 +++++++---- ArmnnDriverImpl.cpp | 38 +++++++++++++++++++++++--- Utils.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++------ Utils.hpp | 9 ++++--- test/UtilsTests.cpp | 55 +++++++++++++++++++------------------ 6 files changed, 142 insertions(+), 49 deletions(-) diff --git a/1.2/ArmnnDriver.hpp b/1.2/ArmnnDriver.hpp index 7460f396..10c73417 100644 --- a/1.2/ArmnnDriver.hpp +++ b/1.2/ArmnnDriver.hpp @@ -119,7 +119,7 @@ public: Return getVersionString(getVersionString_cb cb) { - ALOGV("hal_1_2::ArmnnDriver::getSupportedOperations()"); + ALOGV("hal_1_2::ArmnnDriver::getVersionString()"); cb(ErrorStatus::NONE, "ArmNN"); return Void(); diff --git a/1.2/ArmnnDriverImpl.cpp b/1.2/ArmnnDriverImpl.cpp index 951be815..93a8b8c4 100644 --- a/1.2/ArmnnDriverImpl.cpp +++ b/1.2/ArmnnDriverImpl.cpp @@ -148,6 +148,11 @@ Return ArmnnDriverImpl::prepareArmnnModel_1_2(const armnn::IRuntime return ErrorStatus::NONE; } + // Export the optimized network graph to a dot file if an output dump directory + // has been specified in the drivers' arguments. + std::string dotGraphFileName = ExportNetworkGraphToDotFile(*optNet, + options.GetRequestInputsAndOutputsDumpDir()); + // Load it into the runtime. armnn::NetworkId netId = 0; try @@ -165,11 +170,11 @@ Return ArmnnDriverImpl::prepareArmnnModel_1_2(const armnn::IRuntime return ErrorStatus::NONE; } - // Export the optimized network graph to a dot file if an output dump directory - // has been specified in the drivers' arguments. - ExportNetworkGraphToDotFile(*optNet, - options.GetRequestInputsAndOutputsDumpDir(), - netId); + // Now that we have a networkId for the graph rename the dump file to use it + // so that we can associate the graph file and the input/output tensor dump files + RenameGraphDotFile(dotGraphFileName, + options.GetRequestInputsAndOutputsDumpDir(), + netId); std::unique_ptr> preparedModel( new ArmnnPreparedModel_1_2( diff --git a/ArmnnDriverImpl.cpp b/ArmnnDriverImpl.cpp index df04ef9c..cbb2e642 100644 --- a/ArmnnDriverImpl.cpp +++ b/ArmnnDriverImpl.cpp @@ -129,6 +129,10 @@ Return ArmnnDriverImpl::prepareModel( return ErrorStatus::NONE; } + // Export the optimized network graph to a dot file if an output dump directory + // has been specified in the drivers' arguments. + std::string dotGraphFileName = ExportNetworkGraphToDotFile(*optNet, options.GetRequestInputsAndOutputsDumpDir()); + // Load it into the runtime. armnn::NetworkId netId = 0; try @@ -146,9 +150,11 @@ Return ArmnnDriverImpl::prepareModel( return ErrorStatus::NONE; } - // Export the optimized network graph to a dot file if an output dump directory - // has been specified in the drivers' arguments. - ExportNetworkGraphToDotFile(*optNet, options.GetRequestInputsAndOutputsDumpDir(), netId); + // Now that we have a networkId for the graph rename the dump file to use it + // so that we can associate the graph file and the input/output tensor dump files + RenameGraphDotFile(dotGraphFileName, + options.GetRequestInputsAndOutputsDumpDir(), + netId); unique_ptr> preparedModel( new ArmnnPreparedModel( @@ -191,7 +197,31 @@ Return ArmnnDriverImpl::getSupportedOperations(const armnn::IRu const HalModel& model, HalGetSupportedOperations_cb cb) { - ALOGV("ArmnnDriverImpl::getSupportedOperations()"); + std::stringstream ss; + ss << "ArmnnDriverImpl::getSupportedOperations()"; + std::string fileName; + std::string timestamp; + if (!options.GetRequestInputsAndOutputsDumpDir().empty()) + { + timestamp = GetFileTimestamp(); + fileName = boost::str(boost::format("%1%/%2%_getSupportedOperations.txt") + % options.GetRequestInputsAndOutputsDumpDir() + % timestamp); + ss << " : " << fileName; + } + ALOGV(ss.str().c_str()); + + if (!options.GetRequestInputsAndOutputsDumpDir().empty()) + { + //dump the marker file + std::ofstream fileStream; + fileStream.open(fileName, std::ofstream::out | std::ofstream::trunc); + if (fileStream.good()) + { + fileStream << timestamp << std::endl; + } + fileStream.close(); + } vector result; diff --git a/Utils.cpp b/Utils.cpp index 20a2f70f..314ac25d 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -11,7 +11,13 @@ #include #include +#include #include +#include +#include +#include + + using namespace android; using namespace android::hardware; @@ -343,20 +349,26 @@ void DumpJsonProfilingIfRequired(bool gpuProfilingEnabled, profiler->Print(fileStream); } -void ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimizedNetwork, - const std::string& dumpDir, - const armnn::NetworkId networkId) +std::string ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimizedNetwork, + const std::string& dumpDir) { + std::string fileName; // The dump directory must exist in advance. if (dumpDir.empty()) { - return; + return fileName; + } + + std::string timestamp = GetFileTimestamp(); + if (timestamp.empty()) + { + return fileName; } // Set the name of the output .dot file. - const std::string fileName = boost::str(boost::format("%1%/%2%_networkgraph.dot") - % dumpDir - % std::to_string(networkId)); + fileName = boost::str(boost::format("%1%/%2%_networkgraph.dot") + % dumpDir + % timestamp); ALOGV("Exporting the optimized network graph to file: %s", fileName.c_str()); @@ -367,13 +379,14 @@ void ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimizedNetwor if (!fileStream.good()) { ALOGW("Could not open file %s for writing", fileName.c_str()); - return; + return fileName; } if (optimizedNetwork.SerializeToDot(fileStream) != armnn::Status::Success) { ALOGW("An error occurred when writing to file %s", fileName.c_str()); } + return fileName; } bool IsDynamicTensor(const armnn::TensorInfo& outputInfo) @@ -382,4 +395,47 @@ bool IsDynamicTensor(const armnn::TensorInfo& outputInfo) return outputInfo.GetNumElements() == 0u; } +std::string GetFileTimestamp() +{ + // used to get a timestamp to name diagnostic files (the ArmNN serialized graph + // and getSupportedOperations.txt files) + timespec ts; + int iRet = clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + std::stringstream ss; + if (iRet == 0) + { + ss << std::to_string(ts.tv_sec) << "_" << std::to_string(ts.tv_nsec); + } + else + { + ALOGW("clock_gettime failed with errno %s : %s", std::to_string(errno).c_str(), std::strerror(errno)); + } + return ss.str(); +} + +void RenameGraphDotFile(const std::string& oldName, const std::string& dumpDir, const armnn::NetworkId networkId) +{ + if (dumpDir.empty()) + { + return; + } + if (oldName.empty()) + { + return; + } + const std::string newFileName = boost::str(boost::format("%1%/%2%_networkgraph.dot") + % dumpDir + % std::to_string(networkId)); + int iRet = rename(oldName.c_str(), newFileName.c_str()); + if (iRet != 0) + { + std::stringstream ss; + ss << "rename of [" << oldName << "] to [" << newFileName << "] failed with errno " << std::to_string(errno) + << " : " << std::strerror(errno); + ALOGW(ss.str().c_str()); + } +} + + + } // namespace armnn_driver diff --git a/Utils.hpp b/Utils.hpp index bfda6a66..c5a2e650 100644 --- a/Utils.hpp +++ b/Utils.hpp @@ -104,11 +104,14 @@ void DumpJsonProfilingIfRequired(bool gpuProfilingEnabled, armnn::NetworkId networkId, const armnn::IProfiler* profiler); -void ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimizedNetwork, - const std::string& dumpDir, - const armnn::NetworkId networkId); +std::string ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimizedNetwork, + const std::string& dumpDir); + +void RenameGraphDotFile(const std::string& oldName, const std::string& dumpDir, const armnn::NetworkId networkId); /// Checks if a tensor info represents a dynamic tensor bool IsDynamicTensor(const armnn::TensorInfo& outputInfo); +std::string GetFileTimestamp(); + } // namespace armnn_driver diff --git a/test/UtilsTests.cpp b/test/UtilsTests.cpp index 6ece4e26..5ab768a1 100644 --- a/test/UtilsTests.cpp +++ b/test/UtilsTests.cpp @@ -31,18 +31,20 @@ public: // Setup: set the output dump directory and an empty dummy model (as only its memory address is used). // Defaulting the output dump directory to "/data" because it should exist and be writable in all deployments. ExportNetworkGraphFixture() - : ExportNetworkGraphFixture("/data", 1) + : ExportNetworkGraphFixture("/data") {} - ExportNetworkGraphFixture(const std::string& requestInputsAndOutputsDumpDir, armnn::NetworkId networkId) + ExportNetworkGraphFixture(const std::string& requestInputsAndOutputsDumpDir) : m_RequestInputsAndOutputsDumpDir(requestInputsAndOutputsDumpDir) - , m_NetworkId(networkId) , m_FileName() , m_FileStream() { // Set the name of the output .dot file. + // NOTE: the export now uses a time stamp to name the file so we + // can't predict ahead of time what the file name will be. + std::string timestamp = "dummy"; m_FileName = boost::str(boost::format("%1%/%2%_networkgraph.dot") % m_RequestInputsAndOutputsDumpDir - % std::to_string(m_NetworkId)); + % timestamp); } // Teardown: delete the dump file regardless of the outcome of the tests. @@ -63,6 +65,11 @@ public: m_FileStream.close(); } + if (m_FileName.empty()) + { + return false; + } + // Open the file. m_FileStream.open(m_FileName, std::ifstream::in); @@ -90,10 +97,9 @@ public: } std::string m_RequestInputsAndOutputsDumpDir; - armnn::NetworkId m_NetworkId; + std::string m_FileName; private: - std::string m_FileName; std::ifstream m_FileStream; }; @@ -127,7 +133,7 @@ private: BOOST_AUTO_TEST_CASE(ExportToEmptyDirectory) { // Set the fixture for this test. - ExportNetworkGraphFixture fixture("", 0); + ExportNetworkGraphFixture fixture(""); // Set a mock content for the optimized network. std::string mockSerializedContent = "This is a mock serialized content."; @@ -136,9 +142,8 @@ BOOST_AUTO_TEST_CASE(ExportToEmptyDirectory) MockOptimizedNetwork mockOptimizedNetwork(mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture.m_RequestInputsAndOutputsDumpDir, - 0); + fixture.m_FileName = armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, + fixture.m_RequestInputsAndOutputsDumpDir); // Check that the output file does not exist. BOOST_TEST(!fixture.FileExists()); @@ -156,9 +161,8 @@ BOOST_AUTO_TEST_CASE(ExportNetwork) MockOptimizedNetwork mockOptimizedNetwork(mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture.m_RequestInputsAndOutputsDumpDir, - fixture.m_NetworkId); + fixture.m_FileName = armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, + fixture.m_RequestInputsAndOutputsDumpDir); // Check that the output file exists and that it has the correct name. BOOST_TEST(fixture.FileExists()); @@ -179,9 +183,8 @@ BOOST_AUTO_TEST_CASE(ExportNetworkOverwriteFile) MockOptimizedNetwork mockOptimizedNetwork(mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture.m_RequestInputsAndOutputsDumpDir, - fixture.m_NetworkId); + fixture.m_FileName = armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, + fixture.m_RequestInputsAndOutputsDumpDir); // Check that the output file exists and that it has the correct name. BOOST_TEST(fixture.FileExists()); @@ -194,9 +197,8 @@ BOOST_AUTO_TEST_CASE(ExportNetworkOverwriteFile) mockOptimizedNetwork.UpdateMockSerializedContent(mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture.m_RequestInputsAndOutputsDumpDir, - fixture.m_NetworkId); + fixture.m_FileName = armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, + fixture.m_RequestInputsAndOutputsDumpDir); // Check that the output file still exists and that it has the correct name. BOOST_TEST(fixture.FileExists()); @@ -219,9 +221,8 @@ BOOST_AUTO_TEST_CASE(ExportMultipleNetworks) MockOptimizedNetwork mockOptimizedNetwork(mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture1.m_RequestInputsAndOutputsDumpDir, - fixture1.m_NetworkId); + fixture1.m_FileName = armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, + fixture1.m_RequestInputsAndOutputsDumpDir); // Check that the output file exists and that it has the correct name. BOOST_TEST(fixture1.FileExists()); @@ -230,9 +231,8 @@ BOOST_AUTO_TEST_CASE(ExportMultipleNetworks) BOOST_TEST(fixture1.GetFileContent() == mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture2.m_RequestInputsAndOutputsDumpDir, - fixture2.m_NetworkId); + fixture2.m_FileName = armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, + fixture2.m_RequestInputsAndOutputsDumpDir); // Check that the output file exists and that it has the correct name. BOOST_TEST(fixture2.FileExists()); @@ -241,9 +241,8 @@ BOOST_AUTO_TEST_CASE(ExportMultipleNetworks) BOOST_TEST(fixture2.GetFileContent() == mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture3.m_RequestInputsAndOutputsDumpDir, - fixture3.m_NetworkId); + fixture3.m_FileName = armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, + fixture3.m_RequestInputsAndOutputsDumpDir); // Check that the output file exists and that it has the correct name. BOOST_TEST(fixture3.FileExists()); -- cgit v1.2.1