Files
hardware_interfaces/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp

171 lines
6.6 KiB
C++
Raw Normal View History

/*
* Copyright (C) 2018 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 "neuralnetworks_hidl_hal_test"
#include <chrono>
#include "1.0/Utils.h"
#include "1.2/Callbacks.h"
NNAPI Burst -- HAL VTS tests FastMessageQueue is a Treble-compliant data structure that enables fast communication between two processes. The FMQ object itself is an atomic circular buffer that is optionally synchronized with a futex. However, FMQ has no notion of ownership or lifetime across processes, so it must be paired with higher-level constructs to manage the lifetime and ownership. The NNAPI is introducing the notion of an "Execution Burst" object (or more simply a "Burst" object), which is similar to an ANeuralNetworksExecution, but is intended to be reused across multiple executions and has lower IPC overheads. It achieves this low IPC overhead by replacing HIDL HwBinder calls with FMQ messages. Specifically, it replaces IPreparedModel::executeSynchronously's call from the client into the service with fmq_sync<FmqRequestDatum> (an FMQ channel used to pass a serialized Request object) and it replaces the return from the service into the client with fmq_sync<FmqResultDatum> (an FMQ channel used to return serialized result status and OutputShapes information). Each channel is a unidirectional flow of information with exactly one producer and exactly one consumer. The channels are created by the NN runtime and passed to the service via IPreparedModel::configureExecutionBurst. This CL tests the Burst in both the execution path and validation path in the Vendor Test Suite (VTS) in neuralnetworks/1.*/vts/functional/. The VTS binary--VtsHalNeuralnetworksV1_2TargetTest--can be built and run as any previous version could. Bug: 119570067 Test: mma Test: VtsHalNeuralnetworksV1_2TargetTest Change-Id: I3a36484eff9565c2d028c07c099804a0289f294a Merged-In: I3a36484eff9565c2d028c07c099804a0289f294a (cherry picked from commit 814d8372f36fa0b7e6a8ac37784b4ec6ffa890fd)
2019-01-15 11:02:55 -08:00
#include "ExecutionBurstController.h"
#include "GeneratedTestHarness.h"
#include "TestHarness.h"
#include "VtsHalNeuralnetworks.h"
namespace android::hardware::neuralnetworks::V1_2::vts::functional {
using implementation::ExecutionCallback;
using V1_0::ErrorStatus;
using V1_0::Request;
using ExecutionMutation = std::function<void(Request*)>;
///////////////////////// UTILITY FUNCTIONS /////////////////////////
static bool badTiming(Timing timing) {
return timing.timeOnDevice == UINT64_MAX && timing.timeInDriver == UINT64_MAX;
}
// Primary validation function. This function will take a valid request, apply a
// mutation to it to invalidate the request, then pass it to interface calls
// that use the request.
static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
const Request& originalRequest, const ExecutionMutation& mutate) {
Request request = originalRequest;
mutate(&request);
// We'd like to test both with timing requested and without timing
// requested. Rather than running each test both ways, we'll decide whether
// to request timing by hashing the message. We do not use std::hash because
// it is not guaranteed stable across executions.
char hash = 0;
for (auto c : message) {
hash ^= c;
};
MeasureTiming measure = (hash & 1) ? MeasureTiming::YES : MeasureTiming::NO;
NNAPI Burst -- HAL VTS tests FastMessageQueue is a Treble-compliant data structure that enables fast communication between two processes. The FMQ object itself is an atomic circular buffer that is optionally synchronized with a futex. However, FMQ has no notion of ownership or lifetime across processes, so it must be paired with higher-level constructs to manage the lifetime and ownership. The NNAPI is introducing the notion of an "Execution Burst" object (or more simply a "Burst" object), which is similar to an ANeuralNetworksExecution, but is intended to be reused across multiple executions and has lower IPC overheads. It achieves this low IPC overhead by replacing HIDL HwBinder calls with FMQ messages. Specifically, it replaces IPreparedModel::executeSynchronously's call from the client into the service with fmq_sync<FmqRequestDatum> (an FMQ channel used to pass a serialized Request object) and it replaces the return from the service into the client with fmq_sync<FmqResultDatum> (an FMQ channel used to return serialized result status and OutputShapes information). Each channel is a unidirectional flow of information with exactly one producer and exactly one consumer. The channels are created by the NN runtime and passed to the service via IPreparedModel::configureExecutionBurst. This CL tests the Burst in both the execution path and validation path in the Vendor Test Suite (VTS) in neuralnetworks/1.*/vts/functional/. The VTS binary--VtsHalNeuralnetworksV1_2TargetTest--can be built and run as any previous version could. Bug: 119570067 Test: mma Test: VtsHalNeuralnetworksV1_2TargetTest Change-Id: I3a36484eff9565c2d028c07c099804a0289f294a Merged-In: I3a36484eff9565c2d028c07c099804a0289f294a (cherry picked from commit 814d8372f36fa0b7e6a8ac37784b4ec6ffa890fd)
2019-01-15 11:02:55 -08:00
// asynchronous
{
SCOPED_TRACE(message + " [execute_1_2]");
sp<ExecutionCallback> executionCallback = new ExecutionCallback();
Return<ErrorStatus> executeLaunchStatus =
preparedModel->execute_1_2(request, measure, executionCallback);
ASSERT_TRUE(executeLaunchStatus.isOk());
ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
executionCallback->wait();
ErrorStatus executionReturnStatus = executionCallback->getStatus();
const auto& outputShapes = executionCallback->getOutputShapes();
Timing timing = executionCallback->getTiming();
ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
ASSERT_EQ(outputShapes.size(), 0);
ASSERT_TRUE(badTiming(timing));
}
NNAPI Burst -- HAL VTS tests FastMessageQueue is a Treble-compliant data structure that enables fast communication between two processes. The FMQ object itself is an atomic circular buffer that is optionally synchronized with a futex. However, FMQ has no notion of ownership or lifetime across processes, so it must be paired with higher-level constructs to manage the lifetime and ownership. The NNAPI is introducing the notion of an "Execution Burst" object (or more simply a "Burst" object), which is similar to an ANeuralNetworksExecution, but is intended to be reused across multiple executions and has lower IPC overheads. It achieves this low IPC overhead by replacing HIDL HwBinder calls with FMQ messages. Specifically, it replaces IPreparedModel::executeSynchronously's call from the client into the service with fmq_sync<FmqRequestDatum> (an FMQ channel used to pass a serialized Request object) and it replaces the return from the service into the client with fmq_sync<FmqResultDatum> (an FMQ channel used to return serialized result status and OutputShapes information). Each channel is a unidirectional flow of information with exactly one producer and exactly one consumer. The channels are created by the NN runtime and passed to the service via IPreparedModel::configureExecutionBurst. This CL tests the Burst in both the execution path and validation path in the Vendor Test Suite (VTS) in neuralnetworks/1.*/vts/functional/. The VTS binary--VtsHalNeuralnetworksV1_2TargetTest--can be built and run as any previous version could. Bug: 119570067 Test: mma Test: VtsHalNeuralnetworksV1_2TargetTest Change-Id: I3a36484eff9565c2d028c07c099804a0289f294a Merged-In: I3a36484eff9565c2d028c07c099804a0289f294a (cherry picked from commit 814d8372f36fa0b7e6a8ac37784b4ec6ffa890fd)
2019-01-15 11:02:55 -08:00
// synchronous
{
SCOPED_TRACE(message + " [executeSynchronously]");
Return<void> executeStatus = preparedModel->executeSynchronously(
request, measure,
[](ErrorStatus error, const hidl_vec<OutputShape>& outputShapes,
const Timing& timing) {
ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
EXPECT_EQ(outputShapes.size(), 0);
EXPECT_TRUE(badTiming(timing));
});
ASSERT_TRUE(executeStatus.isOk());
}
NNAPI Burst -- HAL VTS tests FastMessageQueue is a Treble-compliant data structure that enables fast communication between two processes. The FMQ object itself is an atomic circular buffer that is optionally synchronized with a futex. However, FMQ has no notion of ownership or lifetime across processes, so it must be paired with higher-level constructs to manage the lifetime and ownership. The NNAPI is introducing the notion of an "Execution Burst" object (or more simply a "Burst" object), which is similar to an ANeuralNetworksExecution, but is intended to be reused across multiple executions and has lower IPC overheads. It achieves this low IPC overhead by replacing HIDL HwBinder calls with FMQ messages. Specifically, it replaces IPreparedModel::executeSynchronously's call from the client into the service with fmq_sync<FmqRequestDatum> (an FMQ channel used to pass a serialized Request object) and it replaces the return from the service into the client with fmq_sync<FmqResultDatum> (an FMQ channel used to return serialized result status and OutputShapes information). Each channel is a unidirectional flow of information with exactly one producer and exactly one consumer. The channels are created by the NN runtime and passed to the service via IPreparedModel::configureExecutionBurst. This CL tests the Burst in both the execution path and validation path in the Vendor Test Suite (VTS) in neuralnetworks/1.*/vts/functional/. The VTS binary--VtsHalNeuralnetworksV1_2TargetTest--can be built and run as any previous version could. Bug: 119570067 Test: mma Test: VtsHalNeuralnetworksV1_2TargetTest Change-Id: I3a36484eff9565c2d028c07c099804a0289f294a Merged-In: I3a36484eff9565c2d028c07c099804a0289f294a (cherry picked from commit 814d8372f36fa0b7e6a8ac37784b4ec6ffa890fd)
2019-01-15 11:02:55 -08:00
// burst
{
SCOPED_TRACE(message + " [burst]");
// create burst
std::shared_ptr<::android::nn::ExecutionBurstController> burst =
android::nn::ExecutionBurstController::create(preparedModel,
std::chrono::microseconds{0});
NNAPI Burst -- HAL VTS tests FastMessageQueue is a Treble-compliant data structure that enables fast communication between two processes. The FMQ object itself is an atomic circular buffer that is optionally synchronized with a futex. However, FMQ has no notion of ownership or lifetime across processes, so it must be paired with higher-level constructs to manage the lifetime and ownership. The NNAPI is introducing the notion of an "Execution Burst" object (or more simply a "Burst" object), which is similar to an ANeuralNetworksExecution, but is intended to be reused across multiple executions and has lower IPC overheads. It achieves this low IPC overhead by replacing HIDL HwBinder calls with FMQ messages. Specifically, it replaces IPreparedModel::executeSynchronously's call from the client into the service with fmq_sync<FmqRequestDatum> (an FMQ channel used to pass a serialized Request object) and it replaces the return from the service into the client with fmq_sync<FmqResultDatum> (an FMQ channel used to return serialized result status and OutputShapes information). Each channel is a unidirectional flow of information with exactly one producer and exactly one consumer. The channels are created by the NN runtime and passed to the service via IPreparedModel::configureExecutionBurst. This CL tests the Burst in both the execution path and validation path in the Vendor Test Suite (VTS) in neuralnetworks/1.*/vts/functional/. The VTS binary--VtsHalNeuralnetworksV1_2TargetTest--can be built and run as any previous version could. Bug: 119570067 Test: mma Test: VtsHalNeuralnetworksV1_2TargetTest Change-Id: I3a36484eff9565c2d028c07c099804a0289f294a Merged-In: I3a36484eff9565c2d028c07c099804a0289f294a (cherry picked from commit 814d8372f36fa0b7e6a8ac37784b4ec6ffa890fd)
2019-01-15 11:02:55 -08:00
ASSERT_NE(nullptr, burst.get());
// create memory keys
std::vector<intptr_t> keys(request.pools.size());
for (size_t i = 0; i < keys.size(); ++i) {
keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
}
// execute and verify
const auto [n, outputShapes, timing, fallback] = burst->compute(request, measure, keys);
const ErrorStatus status = nn::legacyConvertResultCodeToErrorStatus(n);
EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
NNAPI Burst -- HAL VTS tests FastMessageQueue is a Treble-compliant data structure that enables fast communication between two processes. The FMQ object itself is an atomic circular buffer that is optionally synchronized with a futex. However, FMQ has no notion of ownership or lifetime across processes, so it must be paired with higher-level constructs to manage the lifetime and ownership. The NNAPI is introducing the notion of an "Execution Burst" object (or more simply a "Burst" object), which is similar to an ANeuralNetworksExecution, but is intended to be reused across multiple executions and has lower IPC overheads. It achieves this low IPC overhead by replacing HIDL HwBinder calls with FMQ messages. Specifically, it replaces IPreparedModel::executeSynchronously's call from the client into the service with fmq_sync<FmqRequestDatum> (an FMQ channel used to pass a serialized Request object) and it replaces the return from the service into the client with fmq_sync<FmqResultDatum> (an FMQ channel used to return serialized result status and OutputShapes information). Each channel is a unidirectional flow of information with exactly one producer and exactly one consumer. The channels are created by the NN runtime and passed to the service via IPreparedModel::configureExecutionBurst. This CL tests the Burst in both the execution path and validation path in the Vendor Test Suite (VTS) in neuralnetworks/1.*/vts/functional/. The VTS binary--VtsHalNeuralnetworksV1_2TargetTest--can be built and run as any previous version could. Bug: 119570067 Test: mma Test: VtsHalNeuralnetworksV1_2TargetTest Change-Id: I3a36484eff9565c2d028c07c099804a0289f294a Merged-In: I3a36484eff9565c2d028c07c099804a0289f294a (cherry picked from commit 814d8372f36fa0b7e6a8ac37784b4ec6ffa890fd)
2019-01-15 11:02:55 -08:00
EXPECT_EQ(outputShapes.size(), 0);
EXPECT_TRUE(badTiming(timing));
EXPECT_FALSE(fallback);
NNAPI Burst -- HAL VTS tests FastMessageQueue is a Treble-compliant data structure that enables fast communication between two processes. The FMQ object itself is an atomic circular buffer that is optionally synchronized with a futex. However, FMQ has no notion of ownership or lifetime across processes, so it must be paired with higher-level constructs to manage the lifetime and ownership. The NNAPI is introducing the notion of an "Execution Burst" object (or more simply a "Burst" object), which is similar to an ANeuralNetworksExecution, but is intended to be reused across multiple executions and has lower IPC overheads. It achieves this low IPC overhead by replacing HIDL HwBinder calls with FMQ messages. Specifically, it replaces IPreparedModel::executeSynchronously's call from the client into the service with fmq_sync<FmqRequestDatum> (an FMQ channel used to pass a serialized Request object) and it replaces the return from the service into the client with fmq_sync<FmqResultDatum> (an FMQ channel used to return serialized result status and OutputShapes information). Each channel is a unidirectional flow of information with exactly one producer and exactly one consumer. The channels are created by the NN runtime and passed to the service via IPreparedModel::configureExecutionBurst. This CL tests the Burst in both the execution path and validation path in the Vendor Test Suite (VTS) in neuralnetworks/1.*/vts/functional/. The VTS binary--VtsHalNeuralnetworksV1_2TargetTest--can be built and run as any previous version could. Bug: 119570067 Test: mma Test: VtsHalNeuralnetworksV1_2TargetTest Change-Id: I3a36484eff9565c2d028c07c099804a0289f294a Merged-In: I3a36484eff9565c2d028c07c099804a0289f294a (cherry picked from commit 814d8372f36fa0b7e6a8ac37784b4ec6ffa890fd)
2019-01-15 11:02:55 -08:00
// additional burst testing
if (request.pools.size() > 0) {
// valid free
burst->freeMemory(keys.front());
// negative test: invalid free of unknown (blank) memory
burst->freeMemory(intptr_t{});
// negative test: double free of memory
burst->freeMemory(keys.front());
}
}
}
///////////////////////// REMOVE INPUT ////////////////////////////////////
static void removeInputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
for (size_t input = 0; input < request.inputs.size(); ++input) {
const std::string message = "removeInput: removed input " + std::to_string(input);
validate(preparedModel, message, request,
[input](Request* request) { hidl_vec_removeAt(&request->inputs, input); });
}
}
///////////////////////// REMOVE OUTPUT ////////////////////////////////////
static void removeOutputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
for (size_t output = 0; output < request.outputs.size(); ++output) {
const std::string message = "removeOutput: removed Output " + std::to_string(output);
validate(preparedModel, message, request,
[output](Request* request) { hidl_vec_removeAt(&request->outputs, output); });
}
}
///////////////////////////// ENTRY POINT //////////////////////////////////
void validateRequest(const sp<IPreparedModel>& preparedModel, const Request& request) {
removeInputTest(preparedModel, request);
removeOutputTest(preparedModel, request);
}
void validateRequestFailure(const sp<IPreparedModel>& preparedModel, const Request& request) {
SCOPED_TRACE("Expecting request to fail [executeSynchronously]");
Return<void> executeStatus = preparedModel->executeSynchronously(
request, MeasureTiming::NO,
[](ErrorStatus error, const hidl_vec<OutputShape>& outputShapes, const Timing& timing) {
ASSERT_NE(ErrorStatus::NONE, error);
EXPECT_EQ(outputShapes.size(), 0);
EXPECT_TRUE(badTiming(timing));
});
ASSERT_TRUE(executeStatus.isOk());
}
} // namespace android::hardware::neuralnetworks::V1_2::vts::functional