Trang này mô tả các cấu trúc dữ liệu và phương pháp được sử dụng để giao tiếp hiệu quả bộ đệm toán hạng giữa trình điều khiển và khung.
Tại thời điểm biên dịch mô hình, khung cung cấp các giá trị của các toán hạng không đổi cho trình điều khiển. Tùy thuộc vào thời gian tồn tại của toán hạng hằng số, các giá trị của nó được đặt trong một vectơ HIDL hoặc một nhóm bộ nhớ dùng chung.
- Nếu thời gian tồn tại là
CONSTANT_COPY
, các giá trị được đặt trong trườngoperandValues
của cấu trúc mô hình. Vì các giá trị trong vectơ HIDL được sao chép trong quá trình giao tiếp giữa các quá trình (IPC), điều này thường chỉ được sử dụng để giữ một lượng nhỏ dữ liệu như toán hạng vô hướng (ví dụ, vô hướng kích hoạt trongADD
) và các tham số tensor nhỏ (ví dụ: hình dạng tensor trongRESHAPE
). - Nếu thời gian tồn tại là
CONSTANT_REFERENCE
, các giá trị được đặt trong trườngpools
của cấu trúc mô hình. Chỉ các chốt của vùng bộ nhớ dùng chung mới được sao chép trong IPC thay vì sao chép các giá trị thô. Do đó, sẽ hiệu quả hơn khi lưu trữ một lượng lớn dữ liệu (ví dụ: các tham số trọng lượng theo dạng chập) bằng cách sử dụng nhóm bộ nhớ được chia sẻ hơn là vectơ HIDL.
Tại thời điểm thực thi mô hình, khung công tác cung cấp bộ đệm của các toán hạng đầu vào và đầu ra cho trình điều khiển. Không giống như các hằng số thời gian biên dịch có thể được gửi trong một vectơ HIDL, dữ liệu đầu vào và đầu ra của một quá trình thực thi luôn được giao tiếp thông qua một tập hợp các nhóm bộ nhớ.
Kiểu dữ liệu hidl_memory
được sử dụng trong cả biên dịch và thực thi để đại diện cho một nhóm bộ nhớ được chia sẻ không được ánh xạ. Trình điều khiển nên ánh xạ bộ nhớ phù hợp để làm cho nó có thể sử dụng được dựa trên tên của kiểu dữ liệu hidl_memory
. Các tên bộ nhớ được hỗ trợ là:
-
ashmem
: bộ nhớ dùng chung của Android. Để biết thêm chi tiết, hãy xem bộ nhớ . -
mmap_fd
: Bộ nhớ dùng chung được hỗ trợ bởi bộ mô tả tệp thông quammap
. -
hardware_buffer_blob
: Bộ nhớ dùng chung được hỗ trợ bởi AHardwareBuffer với định dạngAHARDWARE_BUFFER_FORMAT_BLOB
. Có sẵn từ Mạng thần kinh (NN) HAL 1.2. Để biết thêm chi tiết, hãy xem AHardwareBuffer . -
hardware_buffer
: Bộ nhớ dùng chung được hỗ trợ bởi AHardwareBuffer chung không sử dụng định dạngAHARDWARE_BUFFER_FORMAT_BLOB
. Bộ đệm phần cứng không phải chế độ BLOB chỉ được hỗ trợ trong quá trình thực thi mô hình. Có sẵn từ NN HAL 1.2. Để biết thêm chi tiết, hãy xem AHardwareBuffer .
Từ NN HAL 1.3, NNAPI hỗ trợ các miền bộ nhớ cung cấp các giao diện cấp phát cho bộ đệm do trình điều khiển quản lý. Bộ đệm do trình điều khiển quản lý cũng có thể được sử dụng làm đầu vào hoặc đầu ra thực thi. Để biết thêm chi tiết, hãy xem Miền bộ nhớ .
Trình điều khiển NNAPI phải hỗ trợ ánh xạ tên bộ nhớ ashmem
và mmap_fd
. Từ NN HAL 1.3, trình điều khiển cũng phải hỗ trợ ánh xạ hardware_buffer_blob
. Hỗ trợ cho các miền hardware_buffer
và bộ nhớ đệm không phải chế độ BLOB chung là tùy chọn.
AHardwareBuffer
AHardwareBuffer là một loại bộ nhớ dùng chung bao bọc một bộ đệm Gralloc . Trong Android 10, Neural Networks API (NNAPI) hỗ trợ sử dụng AHardwareBuffer , cho phép trình điều khiển thực hiện các thao tác mà không cần sao chép dữ liệu, giúp cải thiện hiệu suất và mức tiêu thụ điện năng cho các ứng dụng. Ví dụ: ngăn xếp HAL của máy ảnh có thể chuyển các đối tượng AHardwareBuffer tới NNAPI cho khối lượng công việc học máy bằng cách sử dụng các tay cầm AHardwareBuffer được tạo bởi các API NDK của máy ảnh và phương tiện NDK. Để biết thêm thông tin, hãy xem ANeuralNetworksMemory_createFromAHardwareBuffer
.
Các đối tượng AHardwareBuffer được sử dụng trong NNAPI được chuyển đến trình điều khiển thông qua một cấu trúc hidl_memory
có tên là phần cứng_bộ đệm hoặc hardware_buffer
cứng_bộ hardware_buffer_blob
. Cấu trúc hidl_memory
hardware_buffer_blob
chỉ đại diện cho các đối tượng AHardwareBuffer có định dạng AHARDWAREBUFFER_FORMAT_BLOB
.
Thông tin mà khung yêu cầu được mã hóa trong trường hidl_handle
của cấu trúc hidl_memory
. Trường hidl_handle
bao bọc native_handle
, trường này mã hóa tất cả siêu dữ liệu bắt buộc về AHardwareBuffer hoặc bộ đệm Gralloc.
Trình điều khiển phải giải mã đúng trường hidl_handle
được cung cấp và truy cập bộ nhớ được mô tả bởi hidl_handle
. Khi phương thức getSupportedOperations_1_2
, getSupportedOperations_1_1
hoặc getSupportedOperations
được gọi, trình điều khiển sẽ phát hiện xem nó có thể giải mã hidl_handle
được cung cấp hay không và truy cập bộ nhớ được mô tả bởi hidl_handle
. Việc chuẩn bị mô hình phải thất bại nếu trường hidl_handle
được sử dụng cho một toán hạng không đổi không được hỗ trợ. Việc thực thi phải thất bại nếu trường hidl_handle
được sử dụng cho toán hạng đầu vào hoặc đầu ra của việc thực thi không được hỗ trợ. Trình điều khiển nên trả về mã lỗi GENERAL_FAILURE
nếu việc chuẩn bị hoặc thực thi mô hình không thành công.
Miền bộ nhớ
Đối với các thiết bị chạy Android 11 trở lên, NNAPI hỗ trợ các miền bộ nhớ cung cấp giao diện bộ cấp phát cho bộ đệm do trình điều khiển quản lý. Điều này cho phép chuyển các bộ nhớ gốc của thiết bị qua các lần thực thi, ngăn chặn việc sao chép và chuyển đổi dữ liệu không cần thiết giữa các lần thực thi liên tiếp trên cùng một trình điều khiển. Luồng này được minh họa trong Hình 1.
Hình 1. Luồng dữ liệu đệm sử dụng các miền bộ nhớ
Tính năng miền bộ nhớ dành cho các bộ căng chủ yếu nằm trong trình điều khiển và không cần truy cập thường xuyên ở phía máy khách. Ví dụ về các bộ căng như vậy bao gồm các bộ căng trạng thái trong các mô hình tuần tự. Đối với các bộ căng cần truy cập CPU thường xuyên ở phía máy khách, bạn nên sử dụng các nhóm bộ nhớ dùng chung.
Để hỗ trợ tính năng miền bộ nhớ, hãy triển khai IDevice::allocate
để cho phép khuôn khổ yêu cầu cấp phát bộ đệm do trình điều khiển quản lý. Trong quá trình cấp phát, khuôn khổ cung cấp các thuộc tính và mẫu sử dụng sau cho bộ đệm:
-
BufferDesc
mô tả các thuộc tính cần thiết của bộ đệm. -
BufferRole
mô tả mô hình sử dụng tiềm năng của bộ đệm như một đầu vào hoặc đầu ra của một mô hình đã chuẩn bị. Nhiều vai trò có thể được chỉ định trong quá trình cấp phát bộ đệm và bộ đệm được cấp phát chỉ có thể được sử dụng như những vai trò được chỉ định đó.
Bộ đệm được cấp phát là nội bộ của trình điều khiển. Trình điều khiển có thể chọn bất kỳ vị trí đệm hoặc bố trí dữ liệu nào. Khi bộ đệm được cấp phát thành công, ứng dụng khách của trình điều khiển có thể tham chiếu hoặc tương tác với bộ đệm bằng cách sử dụng mã thông báo trả về hoặc đối tượng IBuffer
.
Mã thông báo từ IDevice::allocate
được cung cấp khi tham chiếu bộ đệm như một trong các đối tượng MemoryPool
trong cấu trúc Request
của một thực thi. Để ngăn một quá trình cố gắng truy cập bộ đệm được cấp phát trong một quá trình khác, trình điều khiển phải áp dụng xác nhận thích hợp cho mỗi lần sử dụng bộ đệm. Trình điều khiển phải xác nhận rằng việc sử dụng bộ đệm là một trong những vai trò BufferRole
được cung cấp trong quá trình cấp phát và phải thực thi không thành công ngay lập tức nếu việc sử dụng là bất hợp pháp.
Đối tượng IBuffer
được sử dụng để sao chép bộ nhớ rõ ràng. Trong một số tình huống nhất định, ứng dụng khách của trình điều khiển phải khởi tạo bộ đệm do trình điều khiển quản lý từ một nhóm bộ nhớ dùng chung hoặc sao chép bộ đệm ra một nhóm bộ nhớ dùng chung. Các trường hợp sử dụng ví dụ bao gồm:
- Khởi tạo tensor trạng thái
- Lưu vào bộ nhớ đệm kết quả trung gian
- Thực thi dự phòng trên CPU
Để hỗ trợ các trường hợp sử dụng này, trình điều khiển phải triển khai IBuffer::copyTo
và IBuffer::copyFrom
với ashmem
, mmap_fd
và hardware_buffer_blob
nếu nó hỗ trợ cấp phát miền bộ nhớ. Nó là tùy chọn để trình điều khiển hỗ trợ hardware_buffer
cứng_bộ đệm chế độ không phải BLOB.
Trong quá trình cấp phát bộ đệm, các kích thước của bộ đệm có thể được suy ra từ các toán hạng mô hình tương ứng của tất cả các vai trò được chỉ định bởi BufferRole
và các kích thước được cung cấp trong BufferDesc
. Với tất cả thông tin về chiều được kết hợp, bộ đệm có thể có kích thước hoặc thứ hạng không xác định. Trong trường hợp như vậy, bộ đệm ở trạng thái linh hoạt trong đó các kích thước được cố định khi được sử dụng làm đầu vào mô hình và ở trạng thái động khi được sử dụng làm đầu ra mô hình. Có thể sử dụng cùng một bộ đệm với các hình dạng đầu ra khác nhau trong các lần thực thi khác nhau và trình điều khiển phải xử lý việc thay đổi kích thước bộ đệm đúng cách.
Miền bộ nhớ là một tính năng tùy chọn. Trình điều khiển có thể xác định rằng nó không thể hỗ trợ một yêu cầu phân bổ nhất định vì một số lý do. Ví dụ:
- Bộ đệm được yêu cầu có kích thước động.
- Trình điều khiển có các hạn chế về bộ nhớ ngăn nó xử lý các bộ đệm lớn.
Có thể đồng thời đọc nhiều luồng khác nhau từ bộ đệm do trình điều khiển quản lý. Việc truy cập đồng thời bộ đệm để ghi hoặc đọc / ghi là không xác định, nhưng nó không được làm hỏng dịch vụ trình điều khiển hoặc chặn người gọi vô thời hạn. Trình điều khiển có thể trả về lỗi hoặc để nội dung của bộ đệm ở trạng thái không xác định.