diff options
author | Jim Flynn <jim.flynn@arm.com> | 2019-12-16 11:50:29 +0000 |
---|---|---|
committer | Jim Flynn <jim.flynn@arm.com> | 2019-12-18 10:03:43 +0000 |
commit | d2697984e7d7989f5a8154c46a1bf37d98479415 (patch) | |
tree | b66502b18ef6e0723b5021ab86be55ffea75c15a | |
parent | dbbcc3948190d874d80f1f095fcbda65d693519d (diff) | |
download | android-nn-driver-d2697984e7d7989f5a8154c46a1bf37d98479415.tar.gz |
IVGCVSW-4271 Add getSupportedOperations marker file
* Also fix segfault in previous graph dump code
* Cherry picked from 19.08 (https://jira.arm.com/browse/IVGCVSW-4297)
Change-Id: Id4f2e89f5126b7962b4439370e6dd3edcee96f51
Signed-off-by: Jim Flynn <jim.flynn@arm.com>
-rw-r--r-- | 1.2/ArmnnDriver.hpp | 2 | ||||
-rw-r--r-- | 1.2/ArmnnDriverImpl.cpp | 10 | ||||
-rw-r--r-- | ArmnnDriverImpl.cpp | 38 | ||||
-rw-r--r-- | Utils.cpp | 92 | ||||
-rw-r--r-- | Utils.hpp | 43 | ||||
-rw-r--r-- | test/UtilsTests.cpp | 57 |
6 files changed, 165 insertions, 77 deletions
diff --git a/1.2/ArmnnDriver.hpp b/1.2/ArmnnDriver.hpp index 40116c8a..177cab63 100644 --- a/1.2/ArmnnDriver.hpp +++ b/1.2/ArmnnDriver.hpp @@ -119,7 +119,7 @@ public: Return<void> 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 dfb77c36..136228fd 100644 --- a/1.2/ArmnnDriverImpl.cpp +++ b/1.2/ArmnnDriverImpl.cpp @@ -161,8 +161,8 @@ Return<ErrorStatus> ArmnnDriverImpl::prepareArmnnModel_1_2(const armnn::IRuntime // Export the optimized network graph to a dot file if an output dump directory // has been specified in the drivers' arguments. - ExportNetworkGraphToDotFile<hal_1_2::HalPolicy::Model>(*optNet, options.GetRequestInputsAndOutputsDumpDir(), - model); + std::string dotGraphFileName = ExportNetworkGraphToDotFile(*optNet, + options.GetRequestInputsAndOutputsDumpDir()); // Load it into the runtime. armnn::NetworkId netId = 0; @@ -181,6 +181,12 @@ Return<ErrorStatus> ArmnnDriverImpl::prepareArmnnModel_1_2(const armnn::IRuntime return ErrorStatus::NONE; } + // 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<ArmnnPreparedModel_1_2<hal_1_2::HalPolicy>> preparedModel( new ArmnnPreparedModel_1_2<hal_1_2::HalPolicy>( netId, diff --git a/ArmnnDriverImpl.cpp b/ArmnnDriverImpl.cpp index 46c4e577..cbb2e642 100644 --- a/ArmnnDriverImpl.cpp +++ b/ArmnnDriverImpl.cpp @@ -131,7 +131,7 @@ Return<ErrorStatus> ArmnnDriverImpl<HalPolicy>::prepareModel( // Export the optimized network graph to a dot file if an output dump directory // has been specified in the drivers' arguments. - ExportNetworkGraphToDotFile<HalModel>(*optNet, options.GetRequestInputsAndOutputsDumpDir(), model); + std::string dotGraphFileName = ExportNetworkGraphToDotFile(*optNet, options.GetRequestInputsAndOutputsDumpDir()); // Load it into the runtime. armnn::NetworkId netId = 0; @@ -150,7 +150,13 @@ Return<ErrorStatus> ArmnnDriverImpl<HalPolicy>::prepareModel( return ErrorStatus::NONE; } - sp<ArmnnPreparedModel<HalPolicy>> preparedModel( + // 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<ArmnnPreparedModel<HalPolicy>> preparedModel( new ArmnnPreparedModel<HalPolicy>( netId, runtime.get(), @@ -180,7 +186,7 @@ Return<ErrorStatus> ArmnnDriverImpl<HalPolicy>::prepareModel( } } - NotifyCallbackAndCheck(cb, ErrorStatus::NONE, preparedModel); + NotifyCallbackAndCheck(cb, ErrorStatus::NONE, preparedModel.release()); return ErrorStatus::NONE; } @@ -191,7 +197,31 @@ Return<void> ArmnnDriverImpl<HalPolicy>::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<bool> result; @@ -11,7 +11,13 @@ #include <Permute.hpp> #include <cassert> +#include <cerrno> #include <cinttypes> +#include <sstream> +#include <cstdio> +#include <time.h> + + using namespace android; using namespace android::hardware; @@ -246,6 +252,11 @@ void DumpTensor(const std::string& dumpDir, dumpElementFunction = &DumpTensorElement<int32_t>; break; } + case armnn::DataType::Float16: + { + dumpElementFunction = &DumpTensorElement<armnn::Half>; + break; + } default: { dumpElementFunction = nullptr; @@ -358,10 +369,91 @@ void DumpJsonProfilingIfRequired(bool gpuProfilingEnabled, profiler->Print(fileStream); } +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 fileName; + } + + std::string timestamp = GetFileTimestamp(); + if (timestamp.empty()) + { + return fileName; + } + + // Set the name of the output .dot file. + fileName = boost::str(boost::format("%1%/%2%_networkgraph.dot") + % dumpDir + % timestamp); + + ALOGV("Exporting the optimized network graph to file: %s", fileName.c_str()); + + // Write the network graph to a dot file. + std::ofstream fileStream; + fileStream.open(fileName, std::ofstream::out | std::ofstream::trunc); + + if (!fileStream.good()) + { + ALOGW("Could not open file %s for writing", fileName.c_str()); + 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) { // Dynamic tensors have at least one 0-sized dimension 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 @@ -104,47 +104,14 @@ void DumpJsonProfilingIfRequired(bool gpuProfilingEnabled, armnn::NetworkId networkId, const armnn::IProfiler* profiler); -template <typename HalModel> -void ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimizedNetwork, - const std::string& dumpDir, - const HalModel& model) -{ - // The dump directory must exist in advance. - if (dumpDir.empty()) - { - return; - } - - // Get the memory address of the model and convert it to a hex string (of at least a '0' character). - size_t modelAddress = uintptr_t(&model); - std::stringstream ss; - ss << std::uppercase << std::hex << std::setfill('0') << std::setw(1) << modelAddress; - std::string modelAddressHexString = ss.str(); - - // Set the name of the output .dot file. - const std::string fileName = boost::str(boost::format("%1%/networkgraph_%2%.dot") - % dumpDir - % modelAddressHexString); - - ALOGV("Exporting the optimized network graph to file: %s", fileName.c_str()); +std::string ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimizedNetwork, + const std::string& dumpDir); - // Write the network graph to a dot file. - std::ofstream fileStream; - fileStream.open(fileName, std::ofstream::out | std::ofstream::trunc); - - if (!fileStream.good()) - { - ALOGW("Could not open file %s for writing", fileName.c_str()); - return; - } - - if (optimizedNetwork.SerializeToDot(fileStream) != armnn::Status::Success) - { - ALOGW("An error occurred when writing to file %s", fileName.c_str()); - } -} +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 f337db77..a11c8274 100644 --- a/test/UtilsTests.cpp +++ b/test/UtilsTests.cpp @@ -35,20 +35,16 @@ public: {} ExportNetworkGraphFixture(const std::string& requestInputsAndOutputsDumpDir) : m_RequestInputsAndOutputsDumpDir(requestInputsAndOutputsDumpDir) - , m_Model({}) , m_FileName() , m_FileStream() { - // Get the memory address of the model and convert it to a hex string (of at least a '0' character). - size_t modelAddress = uintptr_t(&m_Model); - std::stringstream ss; - ss << std::uppercase << std::hex << std::setfill('0') << std::setw(1) << modelAddress; - std::string modelAddressHexString = ss.str(); - // Set the name of the output .dot file. - m_FileName = boost::str(boost::format("%1%/networkgraph_%2%.dot") + // 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 - % modelAddressHexString); + % timestamp); } // Teardown: delete the dump file regardless of the outcome of the tests. @@ -69,6 +65,11 @@ public: m_FileStream.close(); } + if (m_FileName.empty()) + { + return false; + } + // Open the file. m_FileStream.open(m_FileName, std::ifstream::in); @@ -96,10 +97,9 @@ public: } std::string m_RequestInputsAndOutputsDumpDir; - V1_0::Model m_Model; + std::string m_FileName; private: - std::string m_FileName; std::ifstream m_FileStream; }; @@ -144,9 +144,8 @@ BOOST_AUTO_TEST_CASE(ExportToEmptyDirectory) MockOptimizedNetwork mockOptimizedNetwork(mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture.m_RequestInputsAndOutputsDumpDir, - fixture.m_Model); + fixture.m_FileName = armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, + fixture.m_RequestInputsAndOutputsDumpDir); // Check that the output file does not exist. BOOST_TEST(!fixture.FileExists()); @@ -164,9 +163,8 @@ BOOST_AUTO_TEST_CASE(ExportNetwork) MockOptimizedNetwork mockOptimizedNetwork(mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture.m_RequestInputsAndOutputsDumpDir, - fixture.m_Model); + 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()); @@ -187,9 +185,8 @@ BOOST_AUTO_TEST_CASE(ExportNetworkOverwriteFile) MockOptimizedNetwork mockOptimizedNetwork(mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture.m_RequestInputsAndOutputsDumpDir, - fixture.m_Model); + 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()); @@ -202,9 +199,8 @@ BOOST_AUTO_TEST_CASE(ExportNetworkOverwriteFile) mockOptimizedNetwork.UpdateMockSerializedContent(mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture.m_RequestInputsAndOutputsDumpDir, - fixture.m_Model); + 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()); @@ -227,9 +223,8 @@ BOOST_AUTO_TEST_CASE(ExportMultipleNetworks) MockOptimizedNetwork mockOptimizedNetwork(mockSerializedContent); // Export the mock optimized network. - armnn_driver::ExportNetworkGraphToDotFile(mockOptimizedNetwork, - fixture1.m_RequestInputsAndOutputsDumpDir, - fixture1.m_Model); + 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()); @@ -238,9 +233,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_Model); + 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()); @@ -249,9 +243,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_Model); + 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()); |