From 44381518586476ce7aef78b00bc6a905ddf5730a Mon Sep 17 00:00:00 2001 From: Mike Kelly Date: Mon, 8 Jul 2019 17:37:35 +0100 Subject: IVGCVSW-3351 Run VTS tests * Added ArmnnBurstExecutorWithCache to fix test failures. * Added support for MeasureTiming to fix test failures. Signed-off-by: Mike Kelly Change-Id: I12b7c6228354bac1f1a9b61ee78066219c0923ad --- ArmnnPreparedModel_1_2.cpp | 153 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 143 insertions(+), 10 deletions(-) (limited to 'ArmnnPreparedModel_1_2.cpp') diff --git a/ArmnnPreparedModel_1_2.cpp b/ArmnnPreparedModel_1_2.cpp index f03d69d9..74da4734 100644 --- a/ArmnnPreparedModel_1_2.cpp +++ b/ArmnnPreparedModel_1_2.cpp @@ -20,11 +20,22 @@ using namespace android; using namespace android::hardware; -static const Timing g_NoTiming = {.timeOnDevice = UINT64_MAX, .timeInDriver = UINT64_MAX}; - namespace { +static const Timing g_NoTiming = {.timeOnDevice = UINT64_MAX, .timeInDriver = UINT64_MAX}; using namespace armnn_driver; +using TimePoint = std::chrono::steady_clock::time_point; + +TimePoint Now() +{ + return std::chrono::steady_clock::now(); +} + +unsigned long MicrosecondsDuration(TimePoint endPoint, TimePoint startPoint) +{ + return static_cast(std::chrono::duration_cast( + endPoint - startPoint).count()); +} void NotifyCallbackAndCheck(const ::android::sp& callback, ErrorStatus errorStatus, std::string callingFunction) @@ -167,8 +178,8 @@ Return ArmnnPreparedModel_1_2::execute_1_2(const Reque template Return ArmnnPreparedModel_1_2::executeSynchronously(const Request& request, - MeasureTiming, - V1_2::IPreparedModel::executeSynchronously_cb cb) + MeasureTiming measureTiming, + executeSynchronously_cb cb) { ALOGV("ArmnnPreparedModel_1_2::executeSynchronously(): %s", GetModelSummary(m_Model).c_str()); m_RequestCount++; @@ -179,8 +190,16 @@ Return ArmnnPreparedModel_1_2::executeSynchronously(const Requ return Void(); } + TimePoint driverStart, driverEnd, deviceStart, deviceEnd; + + if (measureTiming == MeasureTiming::YES) + { + driverStart = Now(); + } + if (!android::nn::validateRequest(request, m_Model)) { + ALOGE("ArmnnPreparedModel_1_2::executeSynchronously invalid request model"); cb(ErrorStatus::INVALID_ARGUMENT, {}, g_NoTiming); return Void(); } @@ -247,12 +266,21 @@ Return ArmnnPreparedModel_1_2::executeSynchronously(const Requ ALOGV("ArmnnPreparedModel_1_2::executeSynchronously() before Execution"); DumpTensorsIfRequired("Input", *pInputTensors); - // run it try { + if (measureTiming == MeasureTiming::YES) + { + deviceStart = Now(); + } + armnn::Status status = m_Runtime->EnqueueWorkload(m_NetworkId, *pInputTensors, *pOutputTensors); + if (measureTiming == MeasureTiming::YES) + { + deviceEnd = Now(); + } + if (status != armnn::Status::Success) { ALOGW("EnqueueWorkload failed"); @@ -277,10 +305,110 @@ Return ArmnnPreparedModel_1_2::executeSynchronously(const Requ pool.update(); } ALOGV("ArmnnPreparedModel_1_2::executeSynchronously() after Execution"); - cb(ErrorStatus::NONE, {}, g_NoTiming); + + if (measureTiming == MeasureTiming::YES) + { + driverEnd = Now(); + Timing timing; + timing.timeOnDevice = MicrosecondsDuration(deviceEnd, deviceStart); + timing.timeInDriver = MicrosecondsDuration(driverEnd, driverStart); + ALOGV("ArmnnPreparedModel_1_2::executeSynchronously timing Device = %lu Driver = %lu", timing.timeOnDevice, + timing.timeInDriver); + cb(ErrorStatus::NONE, {}, timing); + } + else + { + cb(ErrorStatus::NONE, {}, g_NoTiming); + } return Void(); } +template +class ArmnnBurstExecutorWithCache : public ExecutionBurstServer::IBurstExecutorWithCache +{ +public: + ArmnnBurstExecutorWithCache(ArmnnPreparedModel_1_2* preparedModel) + : m_PreparedModel(preparedModel) + {} + + bool isCacheEntryPresent(int slot) const override + { + const auto it = m_MemoryCache.find(slot); + return (it != m_MemoryCache.end()) && it->second.valid(); + } + + void addCacheEntry(const hidl_memory& memory, int slot) override + { + m_MemoryCache[slot] = memory; + } + + void removeCacheEntry(int slot) override + { + m_MemoryCache.erase(slot); + } + + std::tuple, Timing> execute( + const Request& request, const std::vector& slots, + MeasureTiming measure) override { + ALOGV("ArmnnPreparedModel_1_2::BurstExecutorWithCache::execute"); + TimePoint driverStart, driverEnd, deviceStart, deviceEnd; + + if (measure == MeasureTiming::YES) + { + driverStart = Now(); + } + hidl_vec pools(slots.size()); + + for (int slot : slots) + { + if (!isCacheEntryPresent(slot)) + { + ALOGE("ArmnnPreparedModel_1_2::BurstExecutorWithCache::no cache entry present"); + return std::tuple, Timing>(ErrorStatus::INVALID_ARGUMENT, + {}, + g_NoTiming); + } + pools[slot] = m_MemoryCache[slot]; + } + + Request fullRequest = request; + fullRequest.pools = std::move(pools); + + // Setup callback + ErrorStatus returnedStatus = ErrorStatus::GENERAL_FAILURE; + hidl_vec returnedOutputShapes; + Timing returnedTiming; + + auto cb = [&returnedStatus, &returnedOutputShapes, &returnedTiming](ErrorStatus status, + const hidl_vec& outputShapes, + const Timing& timing) + { + returnedStatus = status; + returnedOutputShapes = outputShapes; + returnedTiming = timing; + }; + + // Execute + ALOGV("ArmnnPreparedModel_1_2::BurstExecutorWithCache executing"); + Return ret = m_PreparedModel->executeSynchronously(fullRequest, measure, cb); + + if (!ret.isOk() || returnedStatus != ErrorStatus::NONE) + { + ALOGE("ArmnnPreparedModel_1_2::BurstExecutorWithCache::error executing"); + return std::tuple, Timing>(returnedStatus, {}, returnedTiming); + } + + return std::tuple, Timing>(returnedStatus, + std::move(returnedOutputShapes), + returnedTiming); + } + +private: + Model m_Model; + ArmnnPreparedModel_1_2* m_PreparedModel; + std::map m_MemoryCache; +}; + template Return ArmnnPreparedModel_1_2::configureExecutionBurst( const sp& callback, @@ -289,12 +417,17 @@ Return ArmnnPreparedModel_1_2::configureExecutionBurst( V1_2::IPreparedModel::configureExecutionBurst_cb cb) { ALOGV("ArmnnPreparedModel_1_2::configureExecutionBurst"); - const sp burst = - ExecutionBurstServer::create(callback, requestChannel, resultChannel, this); + const std::shared_ptr> executorWithCache = + std::make_shared>(this); + const sp burst = ExecutionBurstServer::create( + callback, requestChannel, resultChannel, executorWithCache); - if (burst == nullptr) { + if (burst == nullptr) + { cb(ErrorStatus::GENERAL_FAILURE, {}); - } else { + } + else + { cb(ErrorStatus::NONE, burst); } return Void(); -- cgit v1.2.1