HAL 1.2 của Mạng nơ-ron giới thiệu khái niệm về các lượt thực thi liên tục. Thực thi hàng loạt là một chuỗi quá trình thực thi cùng một mô hình đã chuẩn bị diễn ra liên tiếp và nhanh chóng, chẳng hạn như quá trình thực thi hoạt động trên các khung hình của một lần thu nạp máy ảnh/máy quay hoặc mẫu âm thanh liên tiếp. Đối tượng thực thi hàng loạt được dùng để kiểm soát một nhóm các hoạt động thực thi hàng loạt và để duy trì các tài nguyên giữa các hoạt động thực thi, cho phép các hoạt động thực thi có mức hao tổn thấp hơn. Các đối tượng Burst cho phép 3 hoạt động tối ưu hoá:
- Một đối tượng burst được tạo trước một chuỗi thực thi và được giải phóng khi chuỗi kết thúc. Do đó, thời gian tồn tại của các gợi ý về đối tượng tăng tốc cho trình điều khiển biết thời gian mà đối tượng đó sẽ duy trì ở trạng thái hiệu suất cao.
- Một đối tượng thực thi hàng loạt có thể giữ lại các tài nguyên giữa các lần thực thi. Ví dụ: trình điều khiển có thể ánh xạ một đối tượng bộ nhớ trong lần thực thi đầu tiên và lưu trữ ánh xạ vào bộ nhớ đệm trong đối tượng burst để sử dụng lại trong các lần thực thi tiếp theo. Bạn có thể giải phóng mọi tài nguyên được lưu vào bộ nhớ đệm khi đối tượng burst bị huỷ hoặc khi thời gian chạy NNAPI thông báo cho đối tượng burst rằng tài nguyên không còn cần thiết nữa.
- Một đối tượng truyền phát sử dụng hàng đợi tin nhắn nhanh (FMQ) để giao tiếp giữa các quy trình ứng dụng và trình điều khiển. Điều này có thể giảm độ trễ vì FMQ bỏ qua HIDL và truyền dữ liệu trực tiếp đến một quy trình khác thông qua FIFO tuần hoàn nguyên tử trong bộ nhớ dùng chung. Quy trình của người dùng biết cách loại bỏ một mục khỏi hàng đợi và bắt đầu xử lý bằng cách thăm dò số lượng phần tử trong FIFO hoặc bằng cách chờ cờ sự kiện của FMQ, được báo hiệu bởi nhà sản xuất. Cờ sự kiện này là một mutex không gian người dùng nhanh (futex).
FMQ là một cấu trúc dữ liệu cấp thấp, không đảm bảo thời gian tồn tại trên các quy trình và không có cơ chế tích hợp để xác định xem quy trình ở đầu kia của FMQ có đang chạy như mong đợi hay không. Do đó, nếu ứng dụng sản xuất cho FMQ bị lỗi, thì ứng dụng tiêu dùng có thể bị kẹt khi chờ dữ liệu không bao giờ đến. Một giải pháp cho vấn đề này là trình điều khiển liên kết FMQ với đối tượng truyền dữ liệu hàng loạt cấp cao hơn để phát hiện thời điểm quá trình thực thi truyền dữ liệu hàng loạt kết thúc.
Vì các hoạt động thực thi theo đợt hoạt động trên cùng các đối số và trả về cùng kết quả như các đường dẫn thực thi khác, nên các FMQ cơ bản phải truyền cùng dữ liệu đến và từ trình điều khiển dịch vụ NNAPI. Tuy nhiên, FMQ chỉ có thể chuyển các loại dữ liệu cũ thông thường. Việc chuyển dữ liệu phức tạp được thực hiện bằng cách chuyển đổi tuần tự và huỷ chuyển đổi tuần tự các vùng đệm lồng nhau (các loại vectơ) ngay trong FMQ, đồng thời sử dụng các đối tượng gọi lại HIDL để chuyển các mã nhận dạng nhóm bộ nhớ theo yêu cầu. Phía nhà sản xuất của FMQ phải gửi các thông báo yêu cầu hoặc kết quả cho người dùng một cách riêng lẻ bằng cách sử dụng MessageQueue::writeBlocking
nếu hàng đợi đang chặn hoặc bằng cách sử dụng MessageQueue::write
nếu hàng đợi không chặn.
Giao diện truyền dữ liệu hàng loạt
Các giao diện truyền dữ liệu liên tục cho HAL Mạng nơ-ron nằm trong hardware/interfaces/neuralnetworks/1.2/
và được mô tả dưới đây. Để biết thêm thông tin về các giao diện truyền dữ liệu hàng loạt trong lớp NDK, hãy xem frameworks/ml/nn/runtime/include/NeuralNetworks.h
.
types.hal
types.hal
xác định loại dữ liệu được gửi qua FMQ.
FmqRequestDatum
: Một phần tử duy nhất của một biểu thức được chuyển đổi tuần tự của đối tượngRequest
thực thi và giá trịMeasureTiming
, được gửi qua hàng đợi tin nhắn nhanh.FmqResultDatum
: Một phần tử duy nhất của bản trình bày được chuyển đổi tuần tự của các giá trị được trả về từ một quá trình thực thi (ErrorStatus
,OutputShapes
vàTiming
), được trả về thông qua hàng đợi tin nhắn nhanh.
IBurstContext.hal
IBurstContext.hal
xác định đối tượng giao diện HIDL nằm trong dịch vụ Mạng nơ-ron.
IBurstContext
: Đối tượng bối cảnh để quản lý tài nguyên của một loạt ảnh.
IBurstCallback.hal
IBurstCallback.hal
xác định đối tượng giao diện HIDL cho một lệnh gọi lại do thời gian chạy Mạng nơ-ron tạo và được dịch vụ Mạng nơ-ron dùng để truy xuất các đối tượng hidl_memory
tương ứng với mã nhận dạng khe cắm.
- IBurstCallback: Đối tượng gọi lại mà một dịch vụ dùng để truy xuất các đối tượng trong bộ nhớ.
IPreparedModel.hal
IPreparedModel.hal
được mở rộng trong HAL 1.2 bằng một phương thức để tạo đối tượng IBurstContext
từ một mô hình đã chuẩn bị.
configureExecutionBurst
: Định cấu hình một đối tượng truyền dữ liệu hàng loạt dùng để thực thi nhiều suy luận trên một mô hình đã chuẩn bị sẵn sàng trong thời gian ngắn.
Hỗ trợ thực thi hàng loạt trong trình điều khiển
Cách đơn giản nhất để hỗ trợ các đối tượng truyền dữ liệu liên tục trong dịch vụ HIDL NNAPI là sử dụng hàm tiện ích truyền dữ liệu liên tục ::android::nn::ExecutionBurstServer::create
. Hàm này có trong ExecutionBurstServer.h
và được đóng gói trong các thư viện tĩnh libneuralnetworks_common
và libneuralnetworks_util
. Hàm tạo này có 2 phương thức nạp chồng:
- Một phương thức nạp chồng chấp nhận con trỏ đến đối tượng
IPreparedModel
. Hàm tiện ích này sử dụng phương thứcexecuteSynchronously
trong một đối tượngIPreparedModel
để thực thi mô hình. - Một phương thức nạp chồng chấp nhận đối tượng
IBurstExecutorWithCache
có thể tuỳ chỉnh. Bạn có thể dùng đối tượng này để lưu vào bộ nhớ đệm các tài nguyên (chẳng hạn như mối liên kếthidl_memory
) duy trì trên nhiều lần thực thi.
Mỗi phương thức nạp chồng trả về một đối tượng IBurstContext
(đại diện cho đối tượng burst) chứa và quản lý luồng trình nghe chuyên dụng của riêng đối tượng đó. Luồng này nhận các yêu cầu từ FMQ requestChannel
, thực hiện suy luận, sau đó trả về kết quả thông qua FMQ resultChannel
. Luồng này và tất cả các tài nguyên khác có trong đối tượng IBurstContext
sẽ tự động được phát hành khi máy khách của chuỗi mất tham chiếu đến IBurstContext
.
Ngoài ra, bạn có thể tạo chế độ triển khai IBurstContext
của riêng mình để hiểu cách gửi và nhận tin nhắn qua requestChannel
và resultChannel
FMQ được truyền đến IPreparedModel::configureExecutionBurst
.
Các hàm tiện ích truyền dữ liệu hàng loạt có trong ExecutionBurstServer.h
.
/**
* Create automated context to manage FMQ-based executions.
*
* This function is intended to be used by a service to automatically:
* 1) Receive data from a provided FMQ
* 2) Execute a model with the given information
* 3) Send the result to the created FMQ
*
* @param callback Callback used to retrieve memories corresponding to
* unrecognized slots.
* @param requestChannel Input FMQ channel through which the client passes the
* request to the service.
* @param resultChannel Output FMQ channel from which the client can retrieve
* the result of the execution.
* @param executorWithCache Object which maintains a local cache of the
* memory pools and executes using the cached memory pools.
* @result IBurstContext Handle to the burst context.
*/
static sp<ExecutionBurstServer> create(
const sp<IBurstCallback>& callback, const FmqRequestDescriptor& requestChannel,
const FmqResultDescriptor& resultChannel,
std::shared_ptr<IBurstExecutorWithCache> executorWithCache);
/**
* Create automated context to manage FMQ-based executions.
*
* This function is intended to be used by a service to automatically:
* 1) Receive data from a provided FMQ
* 2) Execute a model with the given information
* 3) Send the result to the created FMQ
*
* @param callback Callback used to retrieve memories corresponding to
* unrecognized slots.
* @param requestChannel Input FMQ channel through which the client passes the
* request to the service.
* @param resultChannel Output FMQ channel from which the client can retrieve
* the result of the execution.
* @param preparedModel PreparedModel that the burst object was created from.
* IPreparedModel::executeSynchronously will be used to perform the
* execution.
* @result IBurstContext Handle to the burst context.
*/
static sp<ExecutionBurstServer> create(const sp<IBurstCallback>& callback,
const FmqRequestDescriptor& requestChannel,
const FmqResultDescriptor& resultChannel,
IPreparedModel* preparedModel);
Sau đây là một cách triển khai tham chiếu của giao diện truyền dữ liệu hàng loạt có trong trình điều khiển mẫu Mạng nơ-ron tại frameworks/ml/nn/driver/sample/SampleDriver.cpp
.
Return<void> SamplePreparedModel::configureExecutionBurst(
const sp<V1_2::IBurstCallback>& callback,
const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
configureExecutionBurst_cb cb) {
NNTRACE_FULL(NNTRACE_LAYER_DRIVER, NNTRACE_PHASE_EXECUTION,
"SampleDriver::configureExecutionBurst");
// Alternatively, the burst could be configured via:
// const sp<V1_2::IBurstContext> burst =
// ExecutionBurstServer::create(callback, requestChannel,
// resultChannel, this);
//
// However, this alternative representation does not include a memory map
// caching optimization, and adds overhead.
const std::shared_ptr<BurstExecutorWithCache> executorWithCache =
std::make_shared<BurstExecutorWithCache>(mModel, mDriver, mPoolInfos);
const sp<V1_2::IBurstContext> burst = ExecutionBurstServer::create(
callback, requestChannel, resultChannel, executorWithCache);
if (burst == nullptr) {
cb(ErrorStatus::GENERAL_FAILURE, {});
} else {
cb(ErrorStatus::NONE, burst);
}
return Void();
}