diff options
Diffstat (limited to 'neuralnetworks/1.2/utils/src')
-rw-r--r-- | neuralnetworks/1.2/utils/src/Burst.cpp (renamed from neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp) | 155 | ||||
-rw-r--r-- | neuralnetworks/1.2/utils/src/BurstUtils.cpp (renamed from neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp) | 6 | ||||
-rw-r--r-- | neuralnetworks/1.2/utils/src/Callbacks.cpp | 11 | ||||
-rw-r--r-- | neuralnetworks/1.2/utils/src/Conversions.cpp | 126 | ||||
-rw-r--r-- | neuralnetworks/1.2/utils/src/Device.cpp | 24 | ||||
-rw-r--r-- | neuralnetworks/1.2/utils/src/Execution.cpp | 1 | ||||
-rw-r--r-- | neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp | 268 | ||||
-rw-r--r-- | neuralnetworks/1.2/utils/src/PreparedModel.cpp | 52 |
8 files changed, 189 insertions, 454 deletions
diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp b/neuralnetworks/1.2/utils/src/Burst.cpp index b4b6f680d3..23e80709a0 100644 --- a/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp +++ b/neuralnetworks/1.2/utils/src/Burst.cpp @@ -14,10 +14,8 @@ * limitations under the License. */ -#define LOG_TAG "ExecutionBurstController" - -#include "ExecutionBurstController.h" -#include "ExecutionBurstUtils.h" +#include "Burst.h" +#include "BurstUtils.h" #include <android-base/logging.h> #include <android-base/thread_annotations.h> @@ -28,9 +26,9 @@ #include <nnapi/Types.h> #include <nnapi/Validation.h> #include <nnapi/hal/1.0/Conversions.h> +#include <nnapi/hal/1.0/HandleError.h> +#include <nnapi/hal/1.0/ProtectCallback.h> #include <nnapi/hal/CommonUtils.h> -#include <nnapi/hal/HandleError.h> -#include <nnapi/hal/ProtectCallback.h> #include <nnapi/hal/TransferValue.h> #include <algorithm> @@ -57,14 +55,13 @@ class BurstExecution final : public nn::IExecution, public: static nn::GeneralResult<std::shared_ptr<const BurstExecution>> create( - std::shared_ptr<const ExecutionBurstController> controller, - std::vector<FmqRequestDatum> request, hal::utils::RequestRelocation relocation, - std::vector<ExecutionBurstController::OptionalCacheHold> cacheHolds); + std::shared_ptr<const Burst> controller, std::vector<FmqRequestDatum> request, + hal::utils::RequestRelocation relocation, + std::vector<Burst::OptionalCacheHold> cacheHolds); - BurstExecution(PrivateConstructorTag tag, - std::shared_ptr<const ExecutionBurstController> controller, + BurstExecution(PrivateConstructorTag tag, std::shared_ptr<const Burst> controller, std::vector<FmqRequestDatum> request, hal::utils::RequestRelocation relocation, - std::vector<ExecutionBurstController::OptionalCacheHold> cacheHolds); + std::vector<Burst::OptionalCacheHold> cacheHolds); nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> compute( const nn::OptionalTimePoint& deadline) const override; @@ -74,16 +71,16 @@ class BurstExecution final : public nn::IExecution, const nn::OptionalDuration& timeoutDurationAfterFence) const override; private: - const std::shared_ptr<const ExecutionBurstController> kController; + const std::shared_ptr<const Burst> kController; const std::vector<FmqRequestDatum> kRequest; const hal::utils::RequestRelocation kRelocation; - const std::vector<ExecutionBurstController::OptionalCacheHold> kCacheHolds; + const std::vector<Burst::OptionalCacheHold> kCacheHolds; }; nn::GeneralResult<sp<IBurstContext>> executionBurstResultCallback( V1_0::ErrorStatus status, const sp<IBurstContext>& burstContext) { - HANDLE_HAL_STATUS(status) << "IPreparedModel::configureExecutionBurst failed with status " - << toString(status); + HANDLE_STATUS_HIDL(status) << "IPreparedModel::configureExecutionBurst failed with status " + << toString(status); if (burstContext == nullptr) { return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "IPreparedModel::configureExecutionBurst returned nullptr for burst"; @@ -92,8 +89,7 @@ nn::GeneralResult<sp<IBurstContext>> executionBurstResultCallback( } nn::GeneralResult<hidl_vec<hidl_memory>> getMemoriesHelper( - const hidl_vec<int32_t>& slots, - const std::shared_ptr<ExecutionBurstController::MemoryCache>& memoryCache) { + const hidl_vec<int32_t>& slots, const std::shared_ptr<Burst::MemoryCache>& memoryCache) { hidl_vec<hidl_memory> memories(slots.size()); for (size_t i = 0; i < slots.size(); ++i) { const int32_t slot = slots[i]; @@ -110,7 +106,7 @@ nn::GeneralResult<hidl_vec<hidl_memory>> getMemoriesHelper( // MemoryCache methods -ExecutionBurstController::MemoryCache::MemoryCache() { +Burst::MemoryCache::MemoryCache() { constexpr size_t kPreallocatedCount = 1024; std::vector<int32_t> freeSlotsSpace; freeSlotsSpace.reserve(kPreallocatedCount); @@ -119,13 +115,13 @@ ExecutionBurstController::MemoryCache::MemoryCache() { mCacheCleaner.reserve(kPreallocatedCount); } -void ExecutionBurstController::MemoryCache::setBurstContext(sp<IBurstContext> burstContext) { +void Burst::MemoryCache::setBurstContext(sp<IBurstContext> burstContext) { std::lock_guard guard(mMutex); mBurstContext = std::move(burstContext); } -std::pair<int32_t, ExecutionBurstController::MemoryCache::SharedCleanup> -ExecutionBurstController::MemoryCache::cacheMemory(const nn::SharedMemory& memory) { +std::pair<int32_t, Burst::MemoryCache::SharedCleanup> Burst::MemoryCache::cacheMemory( + const nn::SharedMemory& memory) { std::unique_lock lock(mMutex); base::ScopedLockAssertion lockAssert(mMutex); @@ -163,7 +159,7 @@ ExecutionBurstController::MemoryCache::cacheMemory(const nn::SharedMemory& memor return std::make_pair(slot, std::move(cleaner)); } -nn::GeneralResult<nn::SharedMemory> ExecutionBurstController::MemoryCache::getMemory(int32_t slot) { +nn::GeneralResult<nn::SharedMemory> Burst::MemoryCache::getMemory(int32_t slot) { std::lock_guard guard(mMutex); if (slot < 0 || static_cast<size_t>(slot) >= mMemoryCache.size()) { return NN_ERROR() << "Invalid slot: " << slot << " vs " << mMemoryCache.size(); @@ -171,12 +167,15 @@ nn::GeneralResult<nn::SharedMemory> ExecutionBurstController::MemoryCache::getMe return mMemoryCache[slot]; } -void ExecutionBurstController::MemoryCache::freeMemory(const nn::SharedMemory& memory) { +void Burst::MemoryCache::freeMemory(const nn::SharedMemory& memory) { { std::lock_guard guard(mMutex); const int32_t slot = mMemoryIdToSlot.at(memory); if (mBurstContext) { - mBurstContext->freeMemory(slot); + const auto ret = mBurstContext->freeMemory(slot); + if (!ret.isOk()) { + LOG(ERROR) << "IBustContext::freeMemory failed: " << ret.description(); + } } mMemoryIdToSlot.erase(memory); mMemoryCache[slot] = {}; @@ -186,7 +185,7 @@ void ExecutionBurstController::MemoryCache::freeMemory(const nn::SharedMemory& m mCond.notify_all(); } -int32_t ExecutionBurstController::MemoryCache::allocateSlotLocked() { +int32_t Burst::MemoryCache::allocateSlotLocked() { constexpr size_t kMaxNumberOfSlots = std::numeric_limits<int32_t>::max(); // If there is a free slot, use it. @@ -207,18 +206,18 @@ int32_t ExecutionBurstController::MemoryCache::allocateSlotLocked() { // ExecutionBurstCallback methods -ExecutionBurstController::ExecutionBurstCallback::ExecutionBurstCallback( +Burst::ExecutionBurstCallback::ExecutionBurstCallback( const std::shared_ptr<MemoryCache>& memoryCache) : kMemoryCache(memoryCache) { CHECK(memoryCache != nullptr); } -Return<void> ExecutionBurstController::ExecutionBurstCallback::getMemories( - const hidl_vec<int32_t>& slots, getMemories_cb cb) { +Return<void> Burst::ExecutionBurstCallback::getMemories(const hidl_vec<int32_t>& slots, + getMemories_cb cb) { const auto memoryCache = kMemoryCache.lock(); if (memoryCache == nullptr) { - LOG(ERROR) << "ExecutionBurstController::ExecutionBurstCallback::getMemories called after " - "the MemoryCache has been freed"; + LOG(ERROR) << "Burst::ExecutionBurstCallback::getMemories called after the MemoryCache has " + "been freed"; cb(V1_0::ErrorStatus::GENERAL_FAILURE, {}); return Void(); } @@ -226,8 +225,8 @@ Return<void> ExecutionBurstController::ExecutionBurstCallback::getMemories( const auto maybeMemories = getMemoriesHelper(slots, memoryCache); if (!maybeMemories.has_value()) { const auto& [message, code] = maybeMemories.error(); - LOG(ERROR) << "ExecutionBurstController::ExecutionBurstCallback::getMemories failed with " - << code << ": " << message; + LOG(ERROR) << "Burst::ExecutionBurstCallback::getMemories failed with " << code << ": " + << message; cb(V1_0::ErrorStatus::INVALID_ARGUMENT, {}); return Void(); } @@ -236,14 +235,14 @@ Return<void> ExecutionBurstController::ExecutionBurstCallback::getMemories( return Void(); } -// ExecutionBurstController methods +// Burst methods -nn::GeneralResult<std::shared_ptr<const ExecutionBurstController>> ExecutionBurstController::create( +nn::GeneralResult<std::shared_ptr<const Burst>> Burst::create( nn::SharedPreparedModel preparedModel, const sp<V1_2::IPreparedModel>& hidlPreparedModel, std::chrono::microseconds pollingTimeWindow) { // check inputs if (preparedModel == nullptr || hidlPreparedModel == nullptr) { - return NN_ERROR() << "ExecutionBurstController::create passed a nullptr"; + return NN_ERROR() << "Burst::create passed a nullptr"; } // create FMQ objects @@ -279,18 +278,18 @@ nn::GeneralResult<std::shared_ptr<const ExecutionBurstController>> ExecutionBurs deathHandler.protectCallbackForLifetimeOfDeathHandler(resultChannelReceiver.get()); // make and return controller - return std::make_shared<const ExecutionBurstController>( + return std::make_shared<const Burst>( PrivateConstructorTag{}, std::move(preparedModel), std::move(requestChannelSender), std::move(resultChannelReceiver), std::move(burstCallback), std::move(burstContext), std::move(memoryCache), std::move(deathHandler)); } -ExecutionBurstController::ExecutionBurstController( - PrivateConstructorTag /*tag*/, nn::SharedPreparedModel preparedModel, - std::unique_ptr<RequestChannelSender> requestChannelSender, - std::unique_ptr<ResultChannelReceiver> resultChannelReceiver, - sp<ExecutionBurstCallback> callback, sp<IBurstContext> burstContext, - std::shared_ptr<MemoryCache> memoryCache, neuralnetworks::utils::DeathHandler deathHandler) +Burst::Burst(PrivateConstructorTag /*tag*/, nn::SharedPreparedModel preparedModel, + std::unique_ptr<RequestChannelSender> requestChannelSender, + std::unique_ptr<ResultChannelReceiver> resultChannelReceiver, + sp<ExecutionBurstCallback> callback, sp<IBurstContext> burstContext, + std::shared_ptr<MemoryCache> memoryCache, + neuralnetworks::utils::DeathHandler deathHandler) : kPreparedModel(std::move(preparedModel)), mRequestChannelSender(std::move(requestChannelSender)), mResultChannelReceiver(std::move(resultChannelReceiver)), @@ -299,44 +298,41 @@ ExecutionBurstController::ExecutionBurstController( mMemoryCache(std::move(memoryCache)), kDeathHandler(std::move(deathHandler)) {} -ExecutionBurstController::OptionalCacheHold ExecutionBurstController::cacheMemory( - const nn::SharedMemory& memory) const { +Burst::OptionalCacheHold Burst::cacheMemory(const nn::SharedMemory& memory) const { auto [slot, hold] = mMemoryCache->cacheMemory(memory); return hold; } -nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> -ExecutionBurstController::execute(const nn::Request& request, nn::MeasureTiming measure, - const nn::OptionalTimePoint& deadline, - const nn::OptionalDuration& loopTimeoutDuration) const { +nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::execute( + const nn::Request& request, nn::MeasureTiming measure, + const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration, + const std::vector<nn::TokenValuePair>& /*hints*/, + const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const { // This is the first point when we know an execution is occurring, so begin to collect // systraces. Note that the first point we can begin collecting systraces in // ExecutionBurstServer is when the RequestChannelReceiver realizes there is data in the FMQ, so // ExecutionBurstServer collects systraces at different points in the code. - NNTRACE_RT(NNTRACE_PHASE_EXECUTION, "ExecutionBurstController::execute"); + NNTRACE_RT(NNTRACE_PHASE_EXECUTION, "Burst::execute"); // if the request is valid but of a higher version than what's supported in burst execution, // fall back to another execution path - if (const auto version = NN_TRY(hal::utils::makeExecutionFailure(nn::validate(request))); - version > nn::Version::ANDROID_Q) { + if (!compliantVersion(request).ok()) { // fallback to another execution path if the packet could not be sent - return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration); + return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration, {}, {}); } // ensure that request is ready for IPC std::optional<nn::Request> maybeRequestInShared; hal::utils::RequestRelocation relocation; - const nn::Request& requestInShared = - NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared( - &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding, - &maybeRequestInShared, &relocation))); + const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared( + &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding, + &maybeRequestInShared, &relocation)); // clear pools field of request, as they will be provided via slots const auto requestWithoutPools = nn::Request{ .inputs = requestInShared.inputs, .outputs = requestInShared.outputs, .pools = {}}; - auto hidlRequest = NN_TRY( - hal::utils::makeExecutionFailure(V1_0::utils::unvalidatedConvert(requestWithoutPools))); - const auto hidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure))); + auto hidlRequest = NN_TRY(V1_0::utils::unvalidatedConvert(requestWithoutPools)); + const auto hidlMeasure = NN_TRY(convert(measure)); std::vector<int32_t> slots; std::vector<OptionalCacheHold> holds; @@ -351,23 +347,25 @@ ExecutionBurstController::execute(const nn::Request& request, nn::MeasureTiming // send request packet const auto requestPacket = serialize(hidlRequest, hidlMeasure, slots); const auto fallback = [this, &request, measure, &deadline, &loopTimeoutDuration] { - return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration); + return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration, {}, {}); }; return executeInternal(requestPacket, relocation, fallback); } // See IBurst::createReusableExecution for information on this method. -nn::GeneralResult<nn::SharedExecution> ExecutionBurstController::createReusableExecution( +nn::GeneralResult<nn::SharedExecution> Burst::createReusableExecution( const nn::Request& request, nn::MeasureTiming measure, - const nn::OptionalDuration& loopTimeoutDuration) const { - NNTRACE_RT(NNTRACE_PHASE_EXECUTION, "ExecutionBurstController::createReusableExecution"); + const nn::OptionalDuration& loopTimeoutDuration, + const std::vector<nn::TokenValuePair>& /*hints*/, + const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const { + NNTRACE_RT(NNTRACE_PHASE_EXECUTION, "Burst::createReusableExecution"); // if the request is valid but of a higher version than what's supported in burst execution, // fall back to another execution path - if (const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(request))); - version > nn::Version::ANDROID_Q) { + if (!compliantVersion(request).ok()) { // fallback to another execution path if the packet could not be sent - return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration); + return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration, {}, + {}); } // ensure that request is ready for IPC @@ -398,12 +396,10 @@ nn::GeneralResult<nn::SharedExecution> ExecutionBurstController::createReusableE std::move(relocation), std::move(holds)); } -nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> -ExecutionBurstController::executeInternal(const std::vector<FmqRequestDatum>& requestPacket, - const hal::utils::RequestRelocation& relocation, - FallbackFunction fallback) const { - NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION, - "ExecutionBurstController::executeInternal"); +nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::executeInternal( + const std::vector<FmqRequestDatum>& requestPacket, + const hal::utils::RequestRelocation& relocation, FallbackFunction fallback) const { + NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION, "Burst::executeInternal"); // Ensure that at most one execution is in flight at any given time. const bool alreadyInFlight = mExecutionInFlight.test_and_set(); @@ -427,8 +423,7 @@ ExecutionBurstController::executeInternal(const std::vector<FmqRequestDatum>& re } // get result packet - const auto [status, outputShapes, timing] = - NN_TRY(hal::utils::makeExecutionFailure(mResultChannelReceiver->getBlocking())); + const auto [status, outputShapes, timing] = NN_TRY(mResultChannelReceiver->getBlocking()); if (relocation.output) { relocation.output->flush(); @@ -437,9 +432,9 @@ ExecutionBurstController::executeInternal(const std::vector<FmqRequestDatum>& re } nn::GeneralResult<std::shared_ptr<const BurstExecution>> BurstExecution::create( - std::shared_ptr<const ExecutionBurstController> controller, - std::vector<FmqRequestDatum> request, hal::utils::RequestRelocation relocation, - std::vector<ExecutionBurstController::OptionalCacheHold> cacheHolds) { + std::shared_ptr<const Burst> controller, std::vector<FmqRequestDatum> request, + hal::utils::RequestRelocation relocation, + std::vector<Burst::OptionalCacheHold> cacheHolds) { if (controller == nullptr) { return NN_ERROR() << "V1_2::utils::BurstExecution::create must have non-null controller"; } @@ -450,10 +445,10 @@ nn::GeneralResult<std::shared_ptr<const BurstExecution>> BurstExecution::create( } BurstExecution::BurstExecution(PrivateConstructorTag /*tag*/, - std::shared_ptr<const ExecutionBurstController> controller, + std::shared_ptr<const Burst> controller, std::vector<FmqRequestDatum> request, hal::utils::RequestRelocation relocation, - std::vector<ExecutionBurstController::OptionalCacheHold> cacheHolds) + std::vector<Burst::OptionalCacheHold> cacheHolds) : kController(std::move(controller)), kRequest(std::move(request)), kRelocation(std::move(relocation)), diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp b/neuralnetworks/1.2/utils/src/BurstUtils.cpp index 38710cf3fd..c4c096da2d 100644 --- a/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp +++ b/neuralnetworks/1.2/utils/src/BurstUtils.cpp @@ -14,9 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "ExecutionBurstUtils" - -#include "ExecutionBurstUtils.h" +#include "BurstUtils.h" #include <android-base/logging.h> #include <android-base/properties.h> @@ -27,7 +25,7 @@ #include <hidl/MQDescriptor.h> #include <nnapi/Result.h> #include <nnapi/Types.h> -#include <nnapi/hal/ProtectCallback.h> +#include <nnapi/hal/1.0/ProtectCallback.h> #include <atomic> #include <chrono> diff --git a/neuralnetworks/1.2/utils/src/Callbacks.cpp b/neuralnetworks/1.2/utils/src/Callbacks.cpp index 9f54bb12dd..cb61f21775 100644 --- a/neuralnetworks/1.2/utils/src/Callbacks.cpp +++ b/neuralnetworks/1.2/utils/src/Callbacks.cpp @@ -29,10 +29,10 @@ #include <nnapi/Types.h> #include <nnapi/hal/1.0/Callbacks.h> #include <nnapi/hal/1.0/Conversions.h> +#include <nnapi/hal/1.0/HandleError.h> #include <nnapi/hal/1.0/PreparedModel.h> +#include <nnapi/hal/1.0/ProtectCallback.h> #include <nnapi/hal/CommonUtils.h> -#include <nnapi/hal/HandleError.h> -#include <nnapi/hal/ProtectCallback.h> #include <nnapi/hal/TransferValue.h> #include <utility> @@ -62,7 +62,7 @@ convertExecutionGeneralResultsHelper(const hidl_vec<OutputShape>& outputShapes, nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback( V1_0::ErrorStatus status, const sp<IPreparedModel>& preparedModel) { - HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status); + HANDLE_STATUS_HIDL(status) << "model preparation failed with " << toString(status); return NN_TRY(PreparedModel::create(preparedModel, /*executeSynchronously=*/true)); } @@ -74,9 +74,8 @@ nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executi return NN_ERROR(nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, std::move(canonicalOutputShapes)) << "execution failed with " << toString(status); } - HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status); - return hal::utils::makeExecutionFailure( - convertExecutionGeneralResultsHelper(outputShapes, timing)); + HANDLE_STATUS_HIDL(status) << "execution failed with " << toString(status); + return convertExecutionGeneralResultsHelper(outputShapes, timing); } Return<void> PreparedModelCallback::notify(V1_0::ErrorStatus status, diff --git a/neuralnetworks/1.2/utils/src/Conversions.cpp b/neuralnetworks/1.2/utils/src/Conversions.cpp index 29945b75e5..78d71cf990 100644 --- a/neuralnetworks/1.2/utils/src/Conversions.cpp +++ b/neuralnetworks/1.2/utils/src/Conversions.cpp @@ -28,7 +28,6 @@ #include <nnapi/hal/1.0/Conversions.h> #include <nnapi/hal/1.1/Conversions.h> #include <nnapi/hal/CommonUtils.h> -#include <nnapi/hal/HandleError.h> #include <algorithm> #include <functional> @@ -120,9 +119,8 @@ GeneralResult<Capabilities> unvalidatedConvert(const hal::V1_2::Capabilities& ca NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)); auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance)); - auto table = NN_TRY(hal::utils::makeGeneralFailure( - Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)), - nn::ErrorStatus::GENERAL_FAILURE)); + auto table = + NN_TRY(Capabilities::OperandPerformanceTable::create(std::move(operandPerformance))); return Capabilities{ .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar, @@ -133,15 +131,18 @@ GeneralResult<Capabilities> unvalidatedConvert(const hal::V1_2::Capabilities& ca GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert( const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) { + const auto type = NN_TRY(unvalidatedConvert(operandPerformance.type)); + const auto info = NN_TRY(unvalidatedConvert(operandPerformance.info)); return Capabilities::OperandPerformance{ - .type = NN_TRY(unvalidatedConvert(operandPerformance.type)), - .info = NN_TRY(unvalidatedConvert(operandPerformance.info)), + .type = type, + .info = info, }; } GeneralResult<Operation> unvalidatedConvert(const hal::V1_2::Operation& operation) { + const auto type = NN_TRY(unvalidatedConvert(operation.type)); return Operation{ - .type = NN_TRY(unvalidatedConvert(operation.type)), + .type = type, .inputs = operation.inputs, .outputs = operation.outputs, }; @@ -156,14 +157,18 @@ GeneralResult<Operand::SymmPerChannelQuantParams> unvalidatedConvert( } GeneralResult<Operand> unvalidatedConvert(const hal::V1_2::Operand& operand) { + const auto type = NN_TRY(unvalidatedConvert(operand.type)); + const auto lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)); + const auto location = NN_TRY(unvalidatedConvert(operand.location)); + auto extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)); return Operand{ - .type = NN_TRY(unvalidatedConvert(operand.type)), + .type = type, .dimensions = operand.dimensions, .scale = operand.scale, .zeroPoint = operand.zeroPoint, - .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)), - .location = NN_TRY(unvalidatedConvert(operand.location)), - .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)), + .lifetime = lifetime, + .location = location, + .extraParams = std::move(extraParams), }; } @@ -188,7 +193,7 @@ GeneralResult<Model> unvalidatedConvert(const hal::V1_2::Model& model) { // Verify number of consumers. const auto numberOfConsumers = - NN_TRY(hal::utils::countNumberOfConsumers(model.operands.size(), operations)); + NN_TRY(countNumberOfConsumers(model.operands.size(), operations)); CHECK(model.operands.size() == numberOfConsumers.size()); for (size_t i = 0; i < model.operands.size(); ++i) { if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) { @@ -198,25 +203,29 @@ GeneralResult<Model> unvalidatedConvert(const hal::V1_2::Model& model) { } } + auto operands = NN_TRY(unvalidatedConvert(model.operands)); auto main = Model::Subgraph{ - .operands = NN_TRY(unvalidatedConvert(model.operands)), + .operands = std::move(operands), .operations = std::move(operations), .inputIndexes = model.inputIndexes, .outputIndexes = model.outputIndexes, }; + auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues)); + auto pools = NN_TRY(unvalidatedConvert(model.pools)); + auto extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)); return Model{ .main = std::move(main), - .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)), - .pools = NN_TRY(unvalidatedConvert(model.pools)), + .operandValues = std::move(operandValues), + .pools = std::move(pools), .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16, - .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)), + .extensionNameToPrefix = std::move(extensionNameToPrefix), }; } -GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert( +GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert( const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) { - return Model::ExtensionNameAndPrefix{ + return ExtensionNameAndPrefix{ .name = extensionNameAndPrefix.name, .prefix = extensionNameAndPrefix.prefix, }; @@ -250,9 +259,10 @@ GeneralResult<Timing> unvalidatedConvert(const hal::V1_2::Timing& timing) { } GeneralResult<Extension> unvalidatedConvert(const hal::V1_2::Extension& extension) { + auto operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)); return Extension{ .name = extension.name, - .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)), + .operandTypes = std::move(operandTypes), }; } @@ -265,14 +275,6 @@ GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert( }; } -GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& hidlHandle) { - if (hidlHandle.getNativeHandle() == nullptr) { - return nullptr; - } - auto handle = NN_TRY(hal::utils::sharedHandleFromNativeHandle(hidlHandle.getNativeHandle())); - return std::make_shared<const Handle>(std::move(handle)); -} - GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) { return validatedConvert(deviceType); } @@ -335,6 +337,10 @@ nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert( return V1_0::utils::unvalidatedConvert(operandValues); } +nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) { + return V1_0::utils::unvalidatedConvert(handle); +} + nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) { return V1_0::utils::unvalidatedConvert(memory); } @@ -412,35 +418,41 @@ nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceTyp } nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) { - std::vector<nn::Capabilities::OperandPerformance> operandPerformance; - operandPerformance.reserve(capabilities.operandPerformance.asVector().size()); + std::vector<nn::Capabilities::OperandPerformance> filteredOperandPerformances; + filteredOperandPerformances.reserve(capabilities.operandPerformance.asVector().size()); std::copy_if(capabilities.operandPerformance.asVector().begin(), capabilities.operandPerformance.asVector().end(), - std::back_inserter(operandPerformance), + std::back_inserter(filteredOperandPerformances), [](const nn::Capabilities::OperandPerformance& operandPerformance) { return compliantVersion(operandPerformance.type).has_value(); }); + const auto relaxedFloat32toFloat16PerformanceScalar = + NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)); + const auto relaxedFloat32toFloat16PerformanceTensor = + NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)); + auto operandPerformance = NN_TRY(unvalidatedConvert(filteredOperandPerformances)); return Capabilities{ - .relaxedFloat32toFloat16PerformanceScalar = NN_TRY( - unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)), - .relaxedFloat32toFloat16PerformanceTensor = NN_TRY( - unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)), - .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)), + .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar, + .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor, + .operandPerformance = std::move(operandPerformance), }; } nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert( const nn::Capabilities::OperandPerformance& operandPerformance) { + const auto type = NN_TRY(unvalidatedConvert(operandPerformance.type)); + const auto info = NN_TRY(unvalidatedConvert(operandPerformance.info)); return Capabilities::OperandPerformance{ - .type = NN_TRY(unvalidatedConvert(operandPerformance.type)), - .info = NN_TRY(unvalidatedConvert(operandPerformance.info)), + .type = type, + .info = info, }; } nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) { + const auto type = NN_TRY(unvalidatedConvert(operation.type)); return Operation{ - .type = NN_TRY(unvalidatedConvert(operation.type)), + .type = type, .inputs = operation.inputs, .outputs = operation.outputs, }; @@ -455,15 +467,19 @@ nn::GeneralResult<SymmPerChannelQuantParams> unvalidatedConvert( } nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) { + const auto type = NN_TRY(unvalidatedConvert(operand.type)); + const auto lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)); + const auto location = NN_TRY(unvalidatedConvert(operand.location)); + auto extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)); return Operand{ - .type = NN_TRY(unvalidatedConvert(operand.type)), + .type = type, .dimensions = operand.dimensions, .numberOfConsumers = 0, .scale = operand.scale, .zeroPoint = operand.zeroPoint, - .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)), - .location = NN_TRY(unvalidatedConvert(operand.location)), - .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)), + .lifetime = lifetime, + .location = location, + .extraParams = std::move(extraParams), }; } @@ -482,26 +498,30 @@ nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) { // Update number of consumers. const auto numberOfConsumers = - NN_TRY(hal::utils::countNumberOfConsumers(operands.size(), model.main.operations)); + NN_TRY(countNumberOfConsumers(operands.size(), model.main.operations)); CHECK(operands.size() == numberOfConsumers.size()); for (size_t i = 0; i < operands.size(); ++i) { operands[i].numberOfConsumers = numberOfConsumers[i]; } + auto operations = NN_TRY(unvalidatedConvert(model.main.operations)); + auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues)); + auto pools = NN_TRY(unvalidatedConvert(model.pools)); + auto extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)); return Model{ .operands = std::move(operands), - .operations = NN_TRY(unvalidatedConvert(model.main.operations)), + .operations = std::move(operations), .inputIndexes = model.main.inputIndexes, .outputIndexes = model.main.outputIndexes, - .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)), - .pools = NN_TRY(unvalidatedConvert(model.pools)), + .operandValues = std::move(operandValues), + .pools = std::move(pools), .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16, - .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)), + .extensionNameToPrefix = std::move(extensionNameToPrefix), }; } nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert( - const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) { + const nn::ExtensionNameAndPrefix& extensionNameAndPrefix) { return Model::ExtensionNameAndPrefix{ .name = extensionNameAndPrefix.name, .prefix = extensionNameAndPrefix.prefix, @@ -530,9 +550,10 @@ nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) { } nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) { + auto operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)); return Extension{ .name = extension.name, - .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)), + .operandTypes = std::move(operandTypes), }; } @@ -545,13 +566,6 @@ nn::GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert( }; } -nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) { - if (handle == nullptr) { - return {}; - } - return hal::utils::hidlHandleFromSharedHandle(*handle); -} - nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) { return validatedConvert(deviceType); } diff --git a/neuralnetworks/1.2/utils/src/Device.cpp b/neuralnetworks/1.2/utils/src/Device.cpp index 9fe0de25b3..3a58d2c7cc 100644 --- a/neuralnetworks/1.2/utils/src/Device.cpp +++ b/neuralnetworks/1.2/utils/src/Device.cpp @@ -30,10 +30,10 @@ #include <nnapi/OperandTypes.h> #include <nnapi/Result.h> #include <nnapi/Types.h> +#include <nnapi/hal/1.0/HandleError.h> +#include <nnapi/hal/1.0/ProtectCallback.h> #include <nnapi/hal/1.1/Conversions.h> #include <nnapi/hal/CommonUtils.h> -#include <nnapi/hal/HandleError.h> -#include <nnapi/hal/ProtectCallback.h> #include <functional> #include <memory> @@ -49,31 +49,31 @@ namespace { nn::GeneralResult<nn::Capabilities> capabilitiesCallback(V1_0::ErrorStatus status, const Capabilities& capabilities) { - HANDLE_HAL_STATUS(status) << "getting capabilities failed with " << toString(status); + HANDLE_STATUS_HIDL(status) << "getting capabilities failed with " << toString(status); return nn::convert(capabilities); } nn::GeneralResult<std::string> versionStringCallback(V1_0::ErrorStatus status, const hidl_string& versionString) { - HANDLE_HAL_STATUS(status) << "getVersionString failed with " << toString(status); + HANDLE_STATUS_HIDL(status) << "getVersionString failed with " << toString(status); return versionString; } nn::GeneralResult<nn::DeviceType> deviceTypeCallback(V1_0::ErrorStatus status, DeviceType deviceType) { - HANDLE_HAL_STATUS(status) << "getDeviceType failed with " << toString(status); + HANDLE_STATUS_HIDL(status) << "getDeviceType failed with " << toString(status); return nn::convert(deviceType); } nn::GeneralResult<std::vector<nn::Extension>> supportedExtensionsCallback( V1_0::ErrorStatus status, const hidl_vec<Extension>& extensions) { - HANDLE_HAL_STATUS(status) << "getExtensions failed with " << toString(status); + HANDLE_STATUS_HIDL(status) << "getExtensions failed with " << toString(status); return nn::convert(extensions); } nn::GeneralResult<std::pair<uint32_t, uint32_t>> numberOfCacheFilesNeededCallback( V1_0::ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) { - HANDLE_HAL_STATUS(status) << "getNumberOfCacheFilesNeeded failed with " << toString(status); + HANDLE_STATUS_HIDL(status) << "getNumberOfCacheFilesNeeded failed with " << toString(status); if (numModelCache > nn::kMaxNumberOfCacheFiles) { return NN_ERROR() << "getNumberOfCacheFilesNeeded returned numModelCache files greater " "than allowed max (" @@ -192,7 +192,7 @@ const std::string& Device::getVersionString() const { } nn::Version Device::getFeatureLevel() const { - return nn::Version::ANDROID_Q; + return kVersion; } nn::DeviceType Device::getType() const { @@ -236,7 +236,9 @@ nn::GeneralResult<std::vector<bool>> Device::getSupportedOperations(const nn::Mo nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel( const nn::Model& model, nn::ExecutionPreference preference, nn::Priority /*priority*/, nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& modelCache, - const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const { + const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token, + const std::vector<nn::TokenValuePair>& /*hints*/, + const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const { // Ensure that model is ready for IPC. std::optional<nn::Model> maybeModelInShared; const nn::Model& modelInShared = @@ -254,7 +256,7 @@ nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel( const auto ret = kDevice->prepareModel_1_2(hidlModel, hidlPreference, hidlModelCache, hidlDataCache, hidlToken, cb); const auto status = HANDLE_TRANSPORT_FAILURE(ret); - HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status); + HANDLE_STATUS_HIDL(status) << "model preparation failed with " << toString(status); return cb->get(); } @@ -271,7 +273,7 @@ nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModelFromCache( const auto ret = kDevice->prepareModelFromCache(hidlModelCache, hidlDataCache, hidlToken, cb); const auto status = HANDLE_TRANSPORT_FAILURE(ret); - HANDLE_HAL_STATUS(status) << "model preparation from cache failed with " << toString(status); + HANDLE_STATUS_HIDL(status) << "model preparation from cache failed with " << toString(status); return cb->get(); } diff --git a/neuralnetworks/1.2/utils/src/Execution.cpp b/neuralnetworks/1.2/utils/src/Execution.cpp index 18d1c90edd..320b0e1e2f 100644 --- a/neuralnetworks/1.2/utils/src/Execution.cpp +++ b/neuralnetworks/1.2/utils/src/Execution.cpp @@ -29,7 +29,6 @@ #include <nnapi/TypeUtils.h> #include <nnapi/Types.h> #include <nnapi/hal/CommonUtils.h> -#include <nnapi/hal/HandleError.h> #include <memory> #include <utility> diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp deleted file mode 100644 index c67159e895..0000000000 --- a/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "ExecutionBurstServer" - -#include "ExecutionBurstServer.h" -#include "Conversions.h" -#include "ExecutionBurstUtils.h" - -#include <android-base/logging.h> -#include <nnapi/IBurst.h> -#include <nnapi/Result.h> -#include <nnapi/TypeUtils.h> -#include <nnapi/Types.h> -#include <nnapi/Validation.h> -#include <nnapi/hal/1.0/Conversions.h> -#include <nnapi/hal/HandleError.h> -#include <nnapi/hal/ProtectCallback.h> -#include <nnapi/hal/TransferValue.h> - -#include <algorithm> -#include <cstring> -#include <limits> -#include <map> -#include <memory> -#include <tuple> -#include <utility> -#include <vector> - -#include "Tracing.h" - -namespace android::hardware::neuralnetworks::V1_2::utils { -namespace { - -using neuralnetworks::utils::makeExecutionFailure; - -constexpr V1_2::Timing kNoTiming = {std::numeric_limits<uint64_t>::max(), - std::numeric_limits<uint64_t>::max()}; - -nn::GeneralResult<std::vector<nn::SharedMemory>> getMemoriesCallback( - V1_0::ErrorStatus status, const hidl_vec<hidl_memory>& memories) { - HANDLE_HAL_STATUS(status) << "getting burst memories failed with " << toString(status); - std::vector<nn::SharedMemory> canonicalMemories; - canonicalMemories.reserve(memories.size()); - for (const auto& memory : memories) { - canonicalMemories.push_back(NN_TRY(nn::convert(memory))); - } - return canonicalMemories; -} - -} // anonymous namespace - -ExecutionBurstServer::MemoryCache::MemoryCache(nn::SharedBurst burstExecutor, - sp<IBurstCallback> burstCallback) - : kBurstExecutor(std::move(burstExecutor)), kBurstCallback(std::move(burstCallback)) { - CHECK(kBurstExecutor != nullptr); - CHECK(kBurstCallback != nullptr); -} - -nn::GeneralResult<std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>> -ExecutionBurstServer::MemoryCache::getCacheEntries(const std::vector<int32_t>& slots) { - std::lock_guard guard(mMutex); - NN_TRY(ensureCacheEntriesArePresentLocked(slots)); - - std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>> results; - results.reserve(slots.size()); - for (int32_t slot : slots) { - results.push_back(NN_TRY(getCacheEntryLocked(slot))); - } - - return results; -} - -nn::GeneralResult<void> ExecutionBurstServer::MemoryCache::ensureCacheEntriesArePresentLocked( - const std::vector<int32_t>& slots) { - const auto slotIsKnown = [this](int32_t slot) - REQUIRES(mMutex) { return mCache.count(slot) > 0; }; - - // find unique unknown slots - std::vector<int32_t> unknownSlots = slots; - std::sort(unknownSlots.begin(), unknownSlots.end()); - auto unknownSlotsEnd = std::unique(unknownSlots.begin(), unknownSlots.end()); - unknownSlotsEnd = std::remove_if(unknownSlots.begin(), unknownSlotsEnd, slotIsKnown); - unknownSlots.erase(unknownSlotsEnd, unknownSlots.end()); - - // quick-exit if all slots are known - if (unknownSlots.empty()) { - return {}; - } - - auto cb = neuralnetworks::utils::CallbackValue(getMemoriesCallback); - - const auto ret = kBurstCallback->getMemories(unknownSlots, cb); - HANDLE_TRANSPORT_FAILURE(ret); - - auto returnedMemories = NN_TRY(cb.take()); - - if (returnedMemories.size() != unknownSlots.size()) { - return NN_ERROR() - << "ExecutionBurstServer::MemoryCache::ensureCacheEntriesArePresentLocked: Error " - "retrieving memories -- count mismatch between requested memories (" - << unknownSlots.size() << ") and returned memories (" << returnedMemories.size() - << ")"; - } - - // add memories to unknown slots - for (size_t i = 0; i < unknownSlots.size(); ++i) { - addCacheEntryLocked(unknownSlots[i], std::move(returnedMemories[i])); - } - - return {}; -} - -nn::GeneralResult<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>> -ExecutionBurstServer::MemoryCache::getCacheEntryLocked(int32_t slot) { - if (const auto iter = mCache.find(slot); iter != mCache.end()) { - return iter->second; - } - return NN_ERROR() - << "ExecutionBurstServer::MemoryCache::getCacheEntryLocked failed because slot " << slot - << " is not present in the cache"; -} - -void ExecutionBurstServer::MemoryCache::addCacheEntryLocked(int32_t slot, nn::SharedMemory memory) { - auto hold = kBurstExecutor->cacheMemory(memory); - mCache.emplace(slot, std::make_pair(std::move(memory), std::move(hold))); -} - -void ExecutionBurstServer::MemoryCache::removeCacheEntry(int32_t slot) { - std::lock_guard guard(mMutex); - mCache.erase(slot); -} - -// ExecutionBurstServer methods - -nn::GeneralResult<sp<ExecutionBurstServer>> ExecutionBurstServer::create( - const sp<IBurstCallback>& callback, const MQDescriptorSync<FmqRequestDatum>& requestChannel, - const MQDescriptorSync<FmqResultDatum>& resultChannel, nn::SharedBurst burstExecutor, - std::chrono::microseconds pollingTimeWindow) { - // check inputs - if (callback == nullptr || burstExecutor == nullptr) { - return NN_ERROR() << "ExecutionBurstServer::create passed a nullptr"; - } - - // create FMQ objects - auto requestChannelReceiver = - NN_TRY(RequestChannelReceiver::create(requestChannel, pollingTimeWindow)); - auto resultChannelSender = NN_TRY(ResultChannelSender::create(resultChannel)); - - // check FMQ objects - CHECK(requestChannelReceiver != nullptr); - CHECK(resultChannelSender != nullptr); - - // make and return context - return sp<ExecutionBurstServer>::make(PrivateConstructorTag{}, callback, - std::move(requestChannelReceiver), - std::move(resultChannelSender), std::move(burstExecutor)); -} - -ExecutionBurstServer::ExecutionBurstServer(PrivateConstructorTag /*tag*/, - const sp<IBurstCallback>& callback, - std::unique_ptr<RequestChannelReceiver> requestChannel, - std::unique_ptr<ResultChannelSender> resultChannel, - nn::SharedBurst burstExecutor) - : mCallback(callback), - mRequestChannelReceiver(std::move(requestChannel)), - mResultChannelSender(std::move(resultChannel)), - mBurstExecutor(std::move(burstExecutor)), - mMemoryCache(mBurstExecutor, mCallback) { - // TODO: highly document the threading behavior of this class - mWorker = std::thread([this] { task(); }); -} - -ExecutionBurstServer::~ExecutionBurstServer() { - // set teardown flag - mTeardown = true; - mRequestChannelReceiver->invalidate(); - - // wait for task thread to end - mWorker.join(); -} - -Return<void> ExecutionBurstServer::freeMemory(int32_t slot) { - mMemoryCache.removeCacheEntry(slot); - return Void(); -} - -void ExecutionBurstServer::task() { - // loop until the burst object is being destroyed - while (!mTeardown) { - // receive request - auto arguments = mRequestChannelReceiver->getBlocking(); - - // if the request packet was not properly received, return a generic error and skip the - // execution - // - // if the burst is being torn down, skip the execution so the "task" function can end - if (!arguments.has_value()) { - if (!mTeardown) { - mResultChannelSender->send(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming); - } - continue; - } - - // unpack the arguments; types are Request, std::vector<int32_t>, and MeasureTiming, - // respectively - const auto [requestWithoutPools, slotsOfPools, measure] = std::move(arguments).value(); - - auto result = execute(requestWithoutPools, slotsOfPools, measure); - - // return result - if (result.has_value()) { - const auto& [outputShapes, timing] = result.value(); - mResultChannelSender->send(V1_0::ErrorStatus::NONE, outputShapes, timing); - } else { - const auto& [message, code, outputShapes] = result.error(); - LOG(ERROR) << "IBurst::execute failed with " << code << ": " << message; - mResultChannelSender->send(convert(code).value(), convert(outputShapes).value(), - kNoTiming); - } - } -} - -nn::ExecutionResult<std::pair<hidl_vec<OutputShape>, Timing>> ExecutionBurstServer::execute( - const V1_0::Request& requestWithoutPools, const std::vector<int32_t>& slotsOfPools, - MeasureTiming measure) { - NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION, - "ExecutionBurstServer getting memory, executing, and returning results"); - - // ensure executor with cache has required memory - const auto cacheEntries = - NN_TRY(makeExecutionFailure(mMemoryCache.getCacheEntries(slotsOfPools))); - - // convert request, populating its pools - // This code performs an unvalidated convert because the request object without its pools is - // invalid because it is incomplete. Instead, the validation is performed after the memory pools - // have been added to the request. - auto canonicalRequest = - NN_TRY(makeExecutionFailure(nn::unvalidatedConvert(requestWithoutPools))); - CHECK(canonicalRequest.pools.empty()); - std::transform(cacheEntries.begin(), cacheEntries.end(), - std::back_inserter(canonicalRequest.pools), - [](const auto& cacheEntry) { return cacheEntry.first; }); - NN_TRY(makeExecutionFailure(validate(canonicalRequest))); - - nn::MeasureTiming canonicalMeasure = NN_TRY(makeExecutionFailure(nn::convert(measure))); - - const auto [outputShapes, timing] = - NN_TRY(mBurstExecutor->execute(canonicalRequest, canonicalMeasure, {}, {})); - - return std::make_pair(NN_TRY(makeExecutionFailure(convert(outputShapes))), - NN_TRY(makeExecutionFailure(convert(timing)))); -} - -} // namespace android::hardware::neuralnetworks::V1_2::utils diff --git a/neuralnetworks/1.2/utils/src/PreparedModel.cpp b/neuralnetworks/1.2/utils/src/PreparedModel.cpp index d0ef36e7b5..feb3951a4a 100644 --- a/neuralnetworks/1.2/utils/src/PreparedModel.cpp +++ b/neuralnetworks/1.2/utils/src/PreparedModel.cpp @@ -16,11 +16,11 @@ #include "PreparedModel.h" +#include "Burst.h" +#include "BurstUtils.h" #include "Callbacks.h" #include "Conversions.h" #include "Execution.h" -#include "ExecutionBurstController.h" -#include "ExecutionBurstUtils.h" #include "Utils.h" #include <android/hardware/neuralnetworks/1.0/types.h> @@ -31,9 +31,9 @@ #include <nnapi/Result.h> #include <nnapi/Types.h> #include <nnapi/hal/1.0/Conversions.h> +#include <nnapi/hal/1.0/HandleError.h> +#include <nnapi/hal/1.0/ProtectCallback.h> #include <nnapi/hal/CommonUtils.h> -#include <nnapi/hal/HandleError.h> -#include <nnapi/hal/ProtectCallback.h> #include <chrono> #include <memory> @@ -82,7 +82,7 @@ PreparedModel::executeAsynchronously(const V1_0::Request& request, MeasureTiming const auto ret = kPreparedModel->execute_1_2(request, measure, cb); const auto status = HANDLE_TRANSPORT_FAILURE(ret); if (status != V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) { - HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status); + HANDLE_STATUS_HIDL(status) << "execution failed with " << toString(status); } return cb->get(); @@ -91,17 +91,18 @@ PreparedModel::executeAsynchronously(const V1_0::Request& request, MeasureTiming nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute( const nn::Request& request, nn::MeasureTiming measure, const nn::OptionalTimePoint& /*deadline*/, - const nn::OptionalDuration& /*loopTimeoutDuration*/) const { + const nn::OptionalDuration& /*loopTimeoutDuration*/, + const std::vector<nn::TokenValuePair>& /*hints*/, + const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const { // Ensure that request is ready for IPC. std::optional<nn::Request> maybeRequestInShared; hal::utils::RequestRelocation relocation; - const nn::Request& requestInShared = - NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared( - &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding, - &maybeRequestInShared, &relocation))); + const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared( + &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding, + &maybeRequestInShared, &relocation)); - const auto hidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared))); - const auto hidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure))); + const auto hidlRequest = NN_TRY(convert(requestInShared)); + const auto hidlMeasure = NN_TRY(convert(measure)); return executeInternal(hidlRequest, hidlMeasure, relocation); } @@ -124,19 +125,22 @@ PreparedModel::executeInternal(const V1_0::Request& request, MeasureTiming measu } nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> -PreparedModel::executeFenced(const nn::Request& /*request*/, - const std::vector<nn::SyncFence>& /*waitFor*/, - nn::MeasureTiming /*measure*/, - const nn::OptionalTimePoint& /*deadline*/, - const nn::OptionalDuration& /*loopTimeoutDuration*/, - const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const { +PreparedModel::executeFenced( + const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/, + nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/, + const nn::OptionalDuration& /*loopTimeoutDuration*/, + const nn::OptionalDuration& /*timeoutDurationAfterFence*/, + const std::vector<nn::TokenValuePair>& /*hints*/, + const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const { return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "IPreparedModel::executeFenced is not supported on 1.2 HAL service"; } nn::GeneralResult<nn::SharedExecution> PreparedModel::createReusableExecution( const nn::Request& request, nn::MeasureTiming measure, - const nn::OptionalDuration& /*loopTimeoutDuration*/) const { + const nn::OptionalDuration& /*loopTimeoutDuration*/, + const std::vector<nn::TokenValuePair>& /*hints*/, + const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const { // Ensure that request is ready for IPC. std::optional<nn::Request> maybeRequestInShared; hal::utils::RequestRelocation relocation; @@ -151,16 +155,8 @@ nn::GeneralResult<nn::SharedExecution> PreparedModel::createReusableExecution( } nn::GeneralResult<nn::SharedBurst> PreparedModel::configureExecutionBurst() const { - auto self = shared_from_this(); - auto fallback = [preparedModel = std::move(self)]( - const nn::Request& request, nn::MeasureTiming measure, - const nn::OptionalTimePoint& deadline, - const nn::OptionalDuration& loopTimeoutDuration) - -> nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> { - return preparedModel->execute(request, measure, deadline, loopTimeoutDuration); - }; const auto pollingTimeWindow = getBurstControllerPollingTimeWindow(); - return ExecutionBurstController::create(shared_from_this(), kPreparedModel, pollingTimeWindow); + return Burst::create(shared_from_this(), kPreparedModel, pollingTimeWindow); } std::any PreparedModel::getUnderlyingResource() const { |