Trình điều khiển Neural Networks API

Trang này cung cấp thông tin tổng quan về cách triển khai trình điều khiển Neural Networks API (NNAPI). Để biết thêm thông tin chi tiết, hãy xem tài liệu có trong các tệp định nghĩa HAL (Lớp trừu tượng phần cứng) trong hardware/interfaces/neuralnetworks. Quá trình triển khai trình điều khiển mẫu nằm trong frameworks/ml/nn/driver/sample.

Để biết thêm thông tin về Neural Networks API, hãy xem bài viết về Neural Networks API.

Lớp trừu tượng phần cứng (HAL) cho mạng nơron

HAL Mạng nơron (NN) định nghĩa khái quát về nhiều thiết bị, chẳng hạn như đơn vị xử lý đồ hoạ (GPU) và bộ xử lý tín hiệu kỹ thuật số (DSP) có trong một sản phẩm (ví dụ: điện thoại hoặc máy tính bảng). Trình điều khiển cho các thiết bị này phải tuân thủ NN HAL. Giao diện được chỉ định trong tệp định nghĩa HAL trong hardware/interfaces/neuralnetworks.

Quy trình chung của giao diện giữa khung và trình điều khiển được mô tả trong hình 1.

Luồng mạng nơron

Hình 1. Luồng mạng nơron

Khởi chạy

Khi khởi chạy, khung này sẽ truy vấn trình điều khiển về các tính năng của khung bằng cách sử dụng IDevice::getCapabilities_1_3. Cấu trúc @1.3::Capabilities bao gồm mọi loại dữ liệu và thể hiện hiệu suất không đơn giản bằng cách sử dụng một vectơ.

Để xác định cách phân bổ các phép tính cho các thiết bị có sẵn, khung này sử dụng các tính năng để tìm hiểu tốc độ và mức độ tiết kiệm năng lượng mà mỗi trình điều khiển có thể thực hiện. Để cung cấp thông tin này, trình điều khiển phải cung cấp số liệu hiệu suất được chuẩn hoá dựa trên việc thực thi khối lượng công việc tham chiếu.

Để xác định các giá trị mà trình điều khiển trả về để phản hồi IDevice::getCapabilities_1_3, hãy sử dụng ứng dụng điểm chuẩn NNAPI để đo lường hiệu suất của các loại dữ liệu tương ứng. Bạn nên sử dụng các mô hình MobileNet v1, v2, asr_floattts_float để đo lường hiệu suất cho các giá trị dấu phẩy động 32 bit, đồng thời nên dùng các mô hình lượng tử hoá MobileNet v1 và v2 cho các giá trị lượng tử hoá 8 bit. Để biết thêm thông tin, hãy xem Bộ kiểm thử học máy dành cho Android.

Trong Android 9 trở xuống, cấu trúc Capabilities chỉ bao gồm thông tin về hiệu suất của trình điều khiển cho dấu phẩy động và tensor lượng tử hoá, đồng thời không bao gồm các loại dữ liệu vô hướng.

Trong quá trình khởi chạy, khung có thể truy vấn thêm thông tin, bằng cách sử dụng IDevice::getType, IDevice::getVersionString, IDevice:getSupportedExtensionsIDevice::getNumberOfCacheFilesNeeded.

Giữa các lần khởi động lại sản phẩm, khung sẽ yêu cầu tất cả các truy vấn được mô tả trong phần này luôn báo cáo cùng một giá trị cho một trình điều khiển nhất định. Nếu không, một ứng dụng dùng trình điều khiển đó có thể bị giảm hiệu suất hoặc có hành vi không chính xác.

Biên dịch

Khung này xác định sẽ sử dụng thiết bị nào khi nhận được yêu cầu từ một ứng dụng. Trong Android 10, các ứng dụng có thể khám phá và chỉ định các thiết bị mà khung này chọn. Để biết thêm thông tin, hãy xem bài viết Khám phá và chỉ định thiết bị.

Tại thời điểm biên dịch mô hình, khung sẽ gửi mô hình cho từng trình điều khiển đề xuất bằng cách gọi IDevice::getSupportedOperations_1_3. Mỗi trình điều khiển trả về một mảng boolean cho biết toán tử nào của mô hình được hỗ trợ. Trình điều khiển có thể xác định rằng không thể hỗ trợ một thao tác nhất định vì một số lý do. Ví dụ:

  • Trình điều khiển không hỗ trợ loại dữ liệu này.
  • Trình điều khiển chỉ hỗ trợ các thao tác có tham số đầu vào cụ thể. Ví dụ: trình điều khiển có thể hỗ trợ các phép 3x3 và 5x5, nhưng không hỗ trợ phép tích chập 7x7.
  • Trình điều khiển có các hạn chế về bộ nhớ ngăn không cho xử lý các biểu đồ hoặc dữ liệu đầu vào lớn.

Trong quá trình biên dịch, các toán hạng đầu vào, đầu ra và nội bộ của mô hình (như mô tả trong OperandLifeTime) có thể có các chiều hoặc thứ hạng không xác định. Để biết thêm thông tin, hãy xem phần Hình dạng đầu ra.

Khung này sẽ hướng dẫn từng trình điều khiển đã chọn chuẩn bị thực thi một tập hợp con của mô hình bằng cách gọi IDevice::prepareModel_1_3. Sau đó, mỗi trình điều khiển sẽ biên dịch tập hợp con của mình. Ví dụ: trình điều khiển có thể tạo mã hoặc tạo bản sao được sắp xếp lại thứ tự của trọng số. Vì có thể có một khoảng thời gian đáng kể từ lúc biên dịch mô hình đến khi thực thi yêu cầu, nên bạn không nên chỉ định các tài nguyên như các phần lớn bộ nhớ thiết bị trong quá trình biên dịch.

Khi thành công, trình điều khiển sẽ trả về tên người dùng @1.3::IPreparedModel. Nếu trình điều khiển trả về một mã lỗi khi chuẩn bị tập hợp con của mô hình, thì khung sẽ chạy toàn bộ mô hình trên CPU.

Để giảm thời gian biên dịch khi một ứng dụng khởi động, trình điều khiển có thể lưu các cấu phần phần mềm biên dịch vào bộ nhớ đệm. Để biết thêm thông tin, hãy xem phần Lưu vào bộ nhớ đệm biên dịch.

Thực thi

Khi một ứng dụng yêu cầu khung thực thi một yêu cầu, theo mặc định, khung sẽ gọi phương thức HAL IPreparedModel::executeSynchronously_1_3 để thực hiện quá trình thực thi đồng bộ trên một mô hình đã chuẩn bị. Bạn cũng có thể thực thi không đồng bộ yêu cầu bằng phương thức execute_1_3, phương thức executeFenced (xem phần Thực thi được bảo vệ) hoặc được thực thi bằng cách sử dụng thực thi hàng loạt.

Các lệnh gọi thực thi đồng bộ giúp cải thiện hiệu suất và giảm mức hao tổn phân luồng so với các lệnh gọi không đồng bộ, vì quyền kiểm soát chỉ được trả về cho quy trình ứng dụng sau khi quá trình thực thi hoàn tất. Điều này có nghĩa là trình điều khiển không cần một cơ chế riêng để thông báo cho quy trình ứng dụng rằng quá trình thực thi đã hoàn tất.

Với phương thức execute_1_3 không đồng bộ, quyền kiểm soát sẽ quay lại quy trình ứng dụng sau khi quá trình thực thi bắt đầu và trình điều khiển phải thông báo cho khung khi quá trình thực thi hoàn tất bằng cách sử dụng @1.3::IExecutionCallback.

Tham số Request được truyền đến phương thức thực thi liệt kê các toán hạng đầu vào và đầu ra được dùng để thực thi. Bộ nhớ lưu trữ dữ liệu toán hạng phải sử dụng thứ tự chính của hàng có kích thước đầu tiên lặp lại chậm nhất và không có khoảng đệm ở cuối bất kỳ hàng nào. Để biết thêm thông tin về các loại toán hạng, hãy xem phần Toán hạng.

Đối với trình điều khiển NN HAL 1.2 trở lên, khi một yêu cầu hoàn tất, trạng thái lỗi, hình dạng đầu rathông tin thời gian sẽ được trả về cho khung. Trong quá trình thực thi, các toán hạng đầu ra hoặc nội bộ của mô hình có thể có một hoặc nhiều chiều chưa biết hoặc thứ hạng chưa xác định. Khi ít nhất một toán hạng đầu ra có kích thước hoặc thứ hạng không xác định, trình điều khiển phải trả về thông tin đầu ra có kích thước động.

Đối với trình điều khiển có NN HAL 1.1 trở xuống, hệ thống chỉ trả về trạng thái lỗi khi yêu cầu hoàn tất. Kích thước cho các toán hạng đầu vào và đầu ra phải được chỉ định đầy đủ để quá trình thực thi hoàn tất thành công. Toán hạng nội bộ có thể có một hoặc nhiều chiều chưa xác định, nhưng phải chỉ định thứ hạng.

Đối với các yêu cầu của người dùng trải rộng trên nhiều trình điều khiển, khung chịu trách nhiệm dành riêng bộ nhớ trung gian và sắp xếp trình tự các lệnh gọi đến từng trình điều khiển.

Bạn có thể khởi tạo nhiều yêu cầu song song trên cùng một @1.3::IPreparedModel. Trình điều khiển có thể thực thi các yêu cầu song song hoặc chuyển đổi tuần tự các quá trình thực thi.

Khung này có thể yêu cầu người lái xe giữ lại nhiều mô hình đã chuẩn bị. Ví dụ: chuẩn bị mô hình m1, chuẩn bị m2, thực thi yêu cầu r1 trên m1, thực thi r2 trên m2, thực thi r3 trên m1, thực thi r4 trên m2, phát hành (được mô tả trong phần Dọn dẹp) m1 và phát hành m2.

Để tránh việc thực thi lần đầu bị chậm có thể dẫn đến trải nghiệm người dùng kém (ví dụ: kết xuất khung hình đầu tiên bị gián đoạn), trình điều khiển nên thực hiện hầu hết các thao tác khởi chạy trong giai đoạn biên dịch. Việc khởi chạy trong lần thực thi đầu tiên nên được giới hạn ở những hành động ảnh hưởng tiêu cực đến tình trạng hệ thống khi được thực hiện sớm, chẳng hạn như dành riêng các vùng đệm tạm thời lớn hoặc tăng tốc độ xung nhịp của thiết bị. Các trình điều khiển chỉ có thể chuẩn bị một số lượng giới hạn các mô hình đồng thời có thể phải khởi chạy trong lần thực thi đầu tiên.

Trên Android 10 trở lên, trong trường hợp nhiều quá trình thực thi với cùng một mô hình đã chuẩn bị được thực thi liên tiếp liên tiếp, ứng dụng có thể chọn sử dụng một đối tượng hàng loạt thực thi để giao tiếp giữa quy trình của ứng dụng và trình điều khiển. Để biết thêm thông tin, hãy xem phần Thực thi hàng loạt và Hàng đợi thông báo nhanh.

Để nhanh chóng cải thiện hiệu suất cho nhiều quá trình thực thi liên tiếp, trình điều khiển có thể giữ lại vùng đệm tạm thời hoặc tăng tốc độ xung nhịp. Bạn nên tạo luồng theo dõi để giải phóng tài nguyên nếu không có yêu cầu mới nào được tạo sau một khoảng thời gian cố định.

Hình dạng đầu ra

Đối với các yêu cầu mà một hoặc nhiều toán hạng đầu ra không được chỉ định tất cả các chiều, trình điều khiển phải cung cấp danh sách các hình dạng đầu ra chứa thông tin kích thước cho từng toán hạng đầu ra sau khi thực thi. Để biết thêm thông tin về các phương diện, hãy xem OutputShape.

Nếu quá trình thực thi không thành công do vùng đệm đầu ra quá nhỏ, thì trình điều khiển phải chỉ ra toán hạng đầu ra nào không đủ dung lượng bộ nhớ đệm trong danh sách các hình dạng đầu ra và phải báo cáo nhiều thông tin kích thước nhất có thể, bằng cách sử dụng 0 cho các chiều không xác định.

Thời gian

Trên Android 10, một ứng dụng có thể yêu cầu thời gian thực thi nếu đã chỉ định một thiết bị duy nhất để dùng trong quá trình biên dịch. Để biết thông tin chi tiết, hãy xem MeasureTimingKhám phá và chỉ định thiết bị. Trong trường hợp này, trình điều khiển NN HAL 1.2 phải đo lường thời lượng thực thi hoặc báo cáo UINT64_MAX (để cho biết rằng không có thời lượng) khi thực thi một yêu cầu. Trình điều khiển sẽ giảm thiểu mọi mức ảnh hưởng về hiệu suất do việc đo lường thời lượng thực thi.

Trình điều khiển báo cáo các thời lượng sau đây tính bằng micrô giây trong cấu trúc Timing:

  • Thời gian thực thi trên thiết bị: Không bao gồm thời gian thực thi trong trình điều khiển chạy trên bộ xử lý máy chủ.
  • Thời gian thực thi trong trình điều khiển: Bao gồm thời gian thực thi trên thiết bị.

Các thời lượng này phải bao gồm cả thời điểm tạm ngưng quá trình thực thi, ví dụ: khi quá trình thực thi đã bị các tác vụ khác giành quyền hoặc khi đang chờ một tài nguyên có sẵn.

Khi chưa được yêu cầu đo lường thời lượng thực thi hoặc khi có lỗi thực thi thì trình điều khiển phải báo cáo thời lượng là UINT64_MAX. Ngay cả khi được yêu cầu đo thời lượng thực thi, trình điều khiển vẫn có thể báo cáo UINT64_MAX về thời gian trên thiết bị, thời gian trong trình điều khiển hoặc cả hai. Khi trình điều khiển báo cáo cả hai khoảng thời gian dưới dạng một giá trị khác với UINT64_MAX, thời gian thực thi trong trình điều khiển phải bằng hoặc nhiều hơn thời gian trên thiết bị.

Thực thi có bảo vệ

Trong Android 11, NNAPI cho phép các quá trình thực thi chờ danh sách các ô điều khiển sync_fence và tuỳ ý trả về một đối tượng sync_fence. Đối tượng này được báo hiệu khi quá trình thực thi hoàn tất. Điều này làm giảm mức hao tổn cho các mô hình trình tự nhỏ và trường hợp sử dụng truyền trực tuyến. Quá trình thực thi có bảo vệ cũng cho phép khả năng tương tác hiệu quả hơn với các thành phần khác có thể báo hiệu hoặc chờ sync_fence. Để biết thêm thông tin về sync_fence, hãy xem Khung đồng bộ hoá.

Trong một quá trình thực thi có hàng rào, khung này sẽ gọi phương thức IPreparedModel::executeFenced để khởi chạy một quá trình thực thi không đồng bộ, có hàng rào trên một mô hình đã chuẩn bị với một vectơ của hàng rào đồng bộ hoá để chờ đợi. Nếu tác vụ không đồng bộ hoàn tất trước khi lệnh gọi trả về, thì bạn có thể trả về một tên người dùng trống cho sync_fence. Bạn cũng phải trả về đối tượng IFencedExecutionCallback để cho phép khung truy vấn thông tin về thời lượng và trạng thái lỗi.

Sau khi quá trình thực thi hoàn tất, hệ thống có thể truy vấn hai giá trị thời gian sau đây để đo lường thời lượng thực thi thông qua IFencedExecutionCallback::getExecutionInfo.

  • timingLaunched: Thời lượng từ khi executeFenced được gọi đến khi executeFenced báo hiệu syncFence được trả về.
  • timingFenced: Thời lượng từ khi tất cả hàng rào đồng bộ hoá mà quá trình thực thi đang chờ được báo hiệu khi executeFenced báo hiệu syncFence được trả về.

Luồng điều khiển

Đối với các thiết bị chạy Android 11 trở lên, NNAPI bao gồm 2 toán tử luồng điều khiển là IFWHILE, lấy các mô hình khác làm đối số và thực thi các mô hình đó theo cách có điều kiện (IF) hoặc nhiều lần (WHILE). Để biết thêm thông tin về cách triển khai, hãy xem Luồng điều khiển.

Chất lượng dịch vụ

Trong Android 11, NNAPI bao gồm cải thiện chất lượng dịch vụ (QoS) bằng cách cho phép một ứng dụng cho biết các mức độ ưu tiên tương đối của các mô hình, thời lượng tối đa dự kiến cần chuẩn bị một mô hình và lượng thời gian tối đa dự kiến hoàn tất quá trình thực thi. Để biết thêm thông tin, hãy xem bài viết Chất lượng dịch vụ.

Dọn dẹp

Khi một ứng dụng sử dụng xong mô hình đã chuẩn bị, khung sẽ giải phóng tham chiếu đến đối tượng @1.3::IPreparedModel. Khi đối tượng IPreparedModel không còn được tham chiếu, đối tượng đó sẽ tự động bị huỷ trong dịch vụ trình điều khiển tạo ra đối tượng đó. Tại thời điểm này, trong quá trình triển khai hàm huỷ, bạn có thể lấy lại các tài nguyên cụ thể của mô hình. Nếu dịch vụ trình điều khiển muốn đối tượng IPreparedModel tự động bị huỷ khi không còn cần đến ứng dụng, thì dịch vụ đó không được chứa bất kỳ tham chiếu nào đến đối tượng IPreparedModel sau khi đối tượng IPreparedeModel được trả về thông qua IPreparedModelCallback::notify_1_3.

Mức sử dụng CPU

Trình điều khiển sẽ sử dụng CPU để thiết lập các phép tính. Trình điều khiển không nên sử dụng CPU để thực hiện các phép tính biểu đồ vì việc đó ảnh hưởng đến khả năng phân bổ công việc chính xác của khung. Trình điều khiển phải báo cáo các phần mà trình điều khiển không thể xử lý và để khung này xử lý phần còn lại.

Khung này cung cấp cách triển khai CPU cho tất cả các toán tử NNAPI, ngoại trừ các toán tử do nhà cung cấp xác định. Để biết thêm thông tin, hãy xem bài viết Tiện ích dành cho nhà cung cấp.

Các thao tác được giới thiệu trong Android 10 (API cấp 29) chỉ triển khai CPU tham chiếu để xác minh rằng bài kiểm thử CTS và VTS là chính xác. Các phương thức triển khai được tối ưu hoá trong khung máy học dành cho thiết bị di động được ưu tiên hơn so với việc triển khai bằng CPU NNAPI.

Hàm hiệu dụng

Cơ sở mã NNAPI bao gồm các hàm hiệu dụng mà các dịch vụ trình điều khiển có thể sử dụng.

Tệp frameworks/ml/nn/common/include/Utils.h chứa nhiều hàm hiệu dụng, chẳng hạn như các hàm dùng để ghi nhật ký và để chuyển đổi giữa các phiên bản NN HAL (Lớp trừu tượng phần cứng).

  • VLogging: VLOG là một macro trình bao bọc xung quanh LOG của Android, chỉ ghi nhật ký thông báo nếu thẻ thích hợp được đặt trong thuộc tính debug.nn.vlog. Phải gọi initVLogMask() trước mọi lệnh gọi đến VLOG. Bạn có thể sử dụng macro VLOG_IS_ON để kiểm tra xem VLOG hiện đã được bật hay chưa, cho phép bỏ qua mã ghi nhật ký phức tạp nếu không cần thiết. Giá trị của thuộc tính phải là một trong những giá trị sau:

    • Một chuỗi trống cho biết không cần ghi nhật ký.
    • Mã thông báo 1 hoặc all, cho biết rằng đã hoàn tất toàn bộ quá trình ghi nhật ký.
    • Danh sách thẻ được phân tách bằng dấu cách, dấu phẩy hoặc dấu hai chấm cho biết cần ghi nhật ký nào. Các thẻ đó là compilation, cpuexe, driver, execution, managermodel.
  • compliantWithV1_*: Trả về true nếu có thể chuyển đổi đối tượng NN HAL sang cùng một loại phiên bản HAL khác mà không làm mất thông tin. Ví dụ: việc gọi compliantWithV1_0 trên V1_2::Model sẽ trả về false nếu mô hình bao gồm các loại thao tác được giới thiệu trong NN HAL 1.1 hoặc NN HAL 1.2.

  • convertToV1_*: Chuyển đổi đối tượng NN HAL từ phiên bản này sang phiên bản khác. Một cảnh báo sẽ được ghi lại nếu lượt chuyển đổi dẫn đến việc mất thông tin (tức là nếu phiên bản mới của loại này không thể thể hiện đầy đủ giá trị).

  • Chức năng: Bạn có thể dùng các hàm nonExtensionOperandPerformanceupdate để tạo trường Capabilities::operandPerformance.

  • Truy vấn thuộc tính thuộc các loại: isExtensionOperandType, isExtensionOperationType, nonExtensionSizeOfData, nonExtensionOperandSizeOfData, nonExtensionOperandTypeIsScalar, tensorHasUnspecifiedDimensions.

Tệp frameworks/ml/nn/common/include/ValidateHal.h chứa các hàm hiệu dụng để xác thực rằng đối tượng NN HAL là hợp lệ theo thông số kỹ thuật của phiên bản HAL.

  • validate*: Trả về true nếu đối tượng NN HAL hợp lệ theo thông số kỹ thuật của phiên bản HAL. Các loại OEM và loại tiện ích không được xác thực. Ví dụ: validateModel trả về false nếu mô hình chứa một toán tử tham chiếu đến chỉ mục toán hạng không tồn tại hoặc một toán tử không được hỗ trợ ở phiên bản HAL đó.

Tệp frameworks/ml/nn/common/include/Tracing.h chứa các macro để đơn giản hoá việc thêm thông tin systracing vào mã Neural Networks. Để biết ví dụ, hãy xem các lệnh gọi macro NNTRACE_* trong trình điều khiển mẫu.

Tệp frameworks/ml/nn/common/include/GraphDump.h chứa một hàm tiện ích để kết xuất nội dung của Model ở dạng đồ hoạ cho mục đích gỡ lỗi.

  • graphDump: Ghi bản trình bày của mô hình ở định dạng Graphviz (.dot) vào luồng được chỉ định (nếu được cung cấp) hoặc vào logcat (nếu không có luồng nào được cung cấp).

Xác nhận kết quả

Để kiểm thử việc triển khai NNAPI, hãy sử dụng các bài kiểm thử VTS và CTS có trong khung Android. VTS sẽ trực tiếp kiểm tra người lái xe của bạn (không sử dụng khung), trong khi CTS thực thi gián tiếp thông qua khung. Các thao tác này sẽ kiểm thử từng phương thức API và xác minh rằng tất cả các thao tác mà trình điều khiển hỗ trợ đều hoạt động đúng cách và cung cấp kết quả đáp ứng các yêu cầu về độ chính xác.

Sau đây là các yêu cầu về độ chính xác trong CTS và VTS đối với NNAPI:

  • Điểm nổi: abs(dự kiến – thực tế) <= atol + rtol * abs(dự kiến); trong đó:

    • Đối với FP32, atol = 1e-5f, rtol = 5.0f * 1.1920928955078125e-7
    • Đối với FP16, atol = rtol = 5.0f * 0.0009765625f
  • Được định lượng hoá: song song một (ngoại trừ mobilenet_quantized, không theo từng ba)

  • Boolean: khớp chính xác

Một cách CTS kiểm thử NNAPI là tạo các đồ thị giả ngẫu nhiên cố định dùng để kiểm thử và so sánh kết quả thực thi từ mỗi trình điều khiển với phương thức triển khai tham chiếu NNAPI. Đối với trình điều khiển có NN HAL 1.2 trở lên, nếu kết quả không đáp ứng các tiêu chí về độ chính xác, CTS sẽ báo cáo lỗi và kết xuất một tệp thông số kỹ thuật cho mô hình bị lỗi trong /data/local/tmp để gỡ lỗi. Để biết thêm thông tin chi tiết về các tiêu chí về độ chính xác, hãy xem TestRandomGraph.cppTestHarness.h.

Kiểm thử mờ

Mục đích của kiểm thử mờ là tìm các sự cố, câu nhận định, lỗi vi phạm bộ nhớ hoặc hành vi không xác định chung trong mã đang được kiểm thử do các yếu tố như dữ liệu đầu vào không mong muốn. Đối với kiểm thử mờ NNAPI, Android sử dụng các phép kiểm thử dựa trên libFuzzer. Đây là một phương pháp hiệu quả trong việc kiểm thử mờ vì các kiểm thử này sử dụng mức độ bao phủ dòng của các trường hợp kiểm thử trước đó để tạo dữ liệu đầu vào ngẫu nhiên mới. Ví dụ: libFuzzer ưu tiên các trường hợp kiểm thử chạy trên các dòng mã mới. Điều này giúp giảm đáng kể thời gian kiểm thử cần thiết để tìm mã có vấn đề.

Để thực hiện kiểm thử mờ nhằm xác thực việc triển khai trình điều khiển, hãy sửa đổi frameworks/ml/nn/runtime/test/android_fuzzing/DriverFuzzTest.cpp trong tiện ích kiểm thử libneuralnetworks_driver_fuzzer có trong AOSP để đưa mã trình điều khiển vào. Để biết thêm thông tin về kiểm thử mờ NNAPI, hãy xem frameworks/ml/nn/runtime/test/android_fuzzing/README.md.

Bảo mật

Vì các quy trình ứng dụng giao tiếp trực tiếp với quy trình của trình điều khiển, nên các trình điều khiển phải xác thực các đối số của lệnh gọi nhận được. Việc xác thực này được VTS xác minh. Mã xác thực nằm trong frameworks/ml/nn/common/include/ValidateHal.h.

Trình điều khiển cũng phải đảm bảo rằng ứng dụng không được làm ảnh hưởng đến các ứng dụng khác khi sử dụng cùng một thiết bị.

Bộ kiểm tra học máy Android

Bộ kiểm thử học máy (MLTS) của Android là một điểm chuẩn NNAPI có trong CTS và VTS nhằm xác thực độ chính xác của các mô hình thực trên các thiết bị của nhà cung cấp. Điểm chuẩn này đánh giá độ trễ và độ chính xác, đồng thời so sánh kết quả của trình điều khiển với kết quả bằng TF Lite chạy trên CPU, cho cùng một mô hình và tập dữ liệu. Điều này đảm bảo độ chính xác của trình điều khiển không kém hơn hoạt động triển khai tham chiếu CPU.

Các nhà phát triển nền tảng Android cũng sử dụng MLTS để đánh giá độ trễ và độ chính xác của các trình điều khiển.

Bạn có thể tìm thấy điểm chuẩn NNAPI trong hai dự án trong AOSP:

Mô hình và tập dữ liệu

Điểm chuẩn NNAPI sử dụng các mô hình và tập dữ liệu sau đây.

  • MobileNetV1 có độ chính xác đơn và u8 lượng tử hoá ở nhiều kích thước, chạy trên một tập hợp con nhỏ (1500 hình ảnh) của Tập dữ liệu hình ảnh mở phiên bản 4.
  • MobileNetV2 độ chính xác đơn và u8 lượng tử hoá ở các kích thước khác nhau, chạy trên một tập hợp con nhỏ (1500 hình ảnh) của Tập dữ liệu hình ảnh mở v4.
  • Mô hình âm thanh dựa trên bộ nhớ ngắn hạn (LSTM) để chuyển văn bản sang lời nói, được chạy trên một tập hợp con của tập hợp CMU Arctic.
  • Mô hình âm thanh dựa trên LSTM để nhận dạng lời nói tự động, chạy trên một nhóm nhỏ tập dữ liệu Librispeech.

Để biết thêm thông tin, hãy xem platform/test/mlts/models.

Kiểm tra căng thẳng

Bộ kiểm thử học máy Android bao gồm một loạt các bài kiểm thử sự cố để xác thực khả năng phục hồi của trình điều khiển trong các điều kiện sử dụng cao hoặc trong các trường hợp góc cạnh về hành vi của ứng dụng.

Tất cả kiểm thử sự cố đều cung cấp các tính năng sau:

  • Phát hiện treo: Nếu ứng dụng NNAPI bị treo trong quá trình kiểm thử, thì quá trình kiểm thử không thành công với lý do không thành công là HANG và bộ kiểm thử sẽ chuyển sang kiểm thử tiếp theo.
  • Phát hiện sự cố ứng dụng NNAPI: Các hoạt động kiểm thử tiếp tục có hiệu lực sau sự cố ứng dụng, còn kiểm thử không thành công với lý do không thành công CRASH.
  • Phát hiện sự cố trình điều khiển: Các bài kiểm thử có thể phát hiện sự cố trình điều khiển gây ra lỗi trong lệnh gọi NNAPI. Lưu ý rằng có thể có sự cố trong các quy trình của trình điều khiển không gây ra lỗi NNAPI và không làm cho quá trình kiểm thử không thành công. Để xử lý loại lỗi này, bạn nên chạy lệnh tail trên nhật ký hệ thống để tìm các lỗi hoặc sự cố liên quan đến người lái xe.
  • Nhắm mục tiêu tất cả trình tăng tốc hiện có: Các chương trình kiểm thử sẽ chạy trên tất cả trình điều khiển hiện có.

Tất cả kiểm thử sự cố đều có thể có 4 kết quả sau đây:

  • SUCCESS: Quá trình thực thi đã hoàn tất mà không có lỗi.
  • FAILURE: Thực thi không thành công. Thường xảy ra do lỗi khi kiểm thử mô hình, cho biết rằng trình điều khiển không thể biên dịch hoặc thực thi mô hình.
  • HANG: Quá trình thử nghiệm không phản hồi.
  • CRASH: Quy trình kiểm thử đã gặp sự cố.

Để biết thêm thông tin về quy trình kiểm thử nghiêm ngặt và danh sách đầy đủ các bài kiểm thử sự cố, hãy xem platform/test/mlts/benchmark/README.txt.

Sử dụng MLTS

Cách sử dụng MLTS:

  1. Kết nối một thiết bị mục tiêu với máy trạm của bạn và đảm bảo rằng thiết bị đó có thể truy cập được thông qua adb. Xuất biến môi trường ANDROID_SERIAL của thiết bị mục tiêu nếu có nhiều thiết bị được kết nối.
  2. cd vào thư mục nguồn cấp cao nhất của Android.

    source build/envsetup.sh
    lunch aosp_arm-userdebug # Or aosp_arm64-userdebug if available.
    ./test/mlts/benchmark/build_and_run_benchmark.sh
    

    Khi kết thúc lần chạy đo điểm chuẩn, kết quả sẽ được trình bày dưới dạng trang HTML và được chuyển đến xdg-open.

Để biết thêm thông tin, hãy xem platform/test/mlts/benchmark/README.txt.

Phiên bản HAL (Lớp trừu tượng phần cứng) cho mạng Neural Networks

Phần này mô tả những thay đổi được giới thiệu trong phiên bản HAL (Lớp trừu tượng phần cứng) cho Android và Mạng Neural.

Android 11

Android 11 giới thiệu NN HAL 1.3, bao gồm những thay đổi đáng chú ý sau.

  • Hỗ trợ lượng tử hoá 8 bit có dấu trong NNAPI. Thêm loại toán hạng TENSOR_QUANT8_ASYMM_SIGNED. Các trình điều khiển có NN HAL 1.3 hỗ trợ các thao tác có lượng tử hoá chưa ký cũng phải hỗ trợ biến thể đã ký của các thao tác đó. Khi chạy phiên bản đã ký và chưa ký của hầu hết các phép toán lượng tử, trình điều khiển phải cho ra cùng kết quả với độ lệch tối đa là 128. Yêu cầu này có 5 trường hợp ngoại lệ: CAST, HASHTABLE_LOOKUP, LSH_PROJECTION, PAD_V2QUANTIZED_16BIT_LSTM. Toán tử QUANTIZED_16BIT_LSTM không hỗ trợ các toán hạng đã ký, còn 4 toán tử còn lại hỗ trợ lượng tử hoá có dấu nhưng không yêu cầu kết quả phải giống nhau.
  • Hỗ trợ các quá trình thực thi có hàng rào, trong đó khung gọi phương thức IPreparedModel::executeFenced để khởi chạy một quá trình thực thi không đồng bộ, có hàng rào trên một mô hình đã chuẩn bị với một vectơ của hàng rào đồng bộ hoá để chờ đợi. Để biết thêm thông tin, hãy xem phần Thực thi có bảo vệ.
  • Hỗ trợ cho quy trình điều khiển. Thêm các toán tử IFWHILE. Các toán tử này sẽ lấy các mô hình khác làm đối số và thực thi các mô hình đó theo cách có điều kiện (IF) hoặc lặp lại (WHILE). Để biết thêm thông tin, hãy xem phần Kiểm soát luồng.
  • Cải thiện chất lượng dịch vụ (QoS) vì ứng dụng có thể cho biết mức độ ưu tiên tương đối của các mô hình, thời gian tối đa dự kiến để chuẩn bị mô hình và khoảng thời gian tối đa dự kiến để hoàn tất quá trình thực thi. Để biết thêm thông tin, hãy xem bài viết Chất lượng dịch vụ.
  • Hỗ trợ các miền bộ nhớ cung cấp giao diện trình phân bổ cho vùng đệm do người lái xe quản lý. Điều này cho phép truyền bộ nhớ gốc của thiết bị trong các quá trình 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. Để biết thêm thông tin, hãy xem bài viết Miền bộ nhớ.

Android 10

Android 10 giới thiệu NN HAL 1.2, bao gồm những thay đổi đáng chú ý sau.

  • Cấu trúc Capabilities bao gồm mọi kiểu dữ liệu, kể cả các kiểu dữ liệu vô hướng, đồng thời thể hiện hiệu suất không gián đoạn bằng cách sử dụng một vectơ thay vì các trường được đặt tên.
  • Các phương thức getVersionStringgetType cho phép khung truy xuất loại thiết bị (DeviceType) và thông tin phiên bản. Hãy xem phần Khám phá và chỉ định thiết bị.
  • Theo mặc định, phương thức executeSynchronously được gọi để thực hiện quá trình thực thi một cách đồng bộ. Phương thức execute_1_2 yêu cầu khung thực hiện quá trình thực thi một cách không đồng bộ. Hãy xem phần Thực thi.
  • Tham số MeasureTiming cho executeSynchronously, execute_1_2 và quá trình thực thi hàng loạt chỉ định liệu trình điều khiển có đo thời lượng thực thi hay không. Kết quả được báo cáo trong cấu trúc Timing. Hãy xem phần Thời gian.
  • Hỗ trợ các quá trình thực thi khi một hoặc nhiều toán hạng đầu ra có kích thước hoặc thứ hạng không xác định. Xem Hình dạng đầu ra.
  • Hỗ trợ tiện ích của nhà cung cấp, là tập hợp các thao tác và kiểu dữ liệu do nhà cung cấp xác định. Trình điều khiển báo cáo các tiện ích được hỗ trợ thông qua phương thức IDevice::getSupportedExtensions. Xem Tiện ích dành cho nhà cung cấp.
  • Khả năng một đối tượng hàng loạt kiểm soát một nhóm các quá trình thực thi hàng loạt bằng cách sử dụng hàng đợi tin nhắn nhanh (FMQ) để giao tiếp giữa quy trình của ứng dụng và trình điều khiển, giúp giảm độ trễ. Hãy xem phần Thực thi hàng loạt và hàng đợi tin nhắn nhanh.
  • Hỗ trợ AHardwareBuffer để cho phép trình điều khiển thực thi các quá trình thực thi mà không cần sao chép dữ liệu. Hãy xem phần AHardwareBuffer.
  • Cải thiện tính năng hỗ trợ cho việc lưu các cấu phần phần mềm biên dịch vào bộ nhớ đệm nhằm giảm thời gian biên dịch khi ứng dụng khởi động. Hãy xem phần Lưu nội dung tổng hợp vào bộ nhớ đệm.

Android 10 ra mắt các kiểu toán hạng và toán tử sau.

  • Các loại toán hạng

    • ANEURALNETWORKS_BOOL
    • ANEURALNETWORKS_FLOAT16
    • ANEURALNETWORKS_TENSOR_BOOL8
    • ANEURALNETWORKS_TENSOR_FLOAT16
    • ANEURALNETWORKS_TENSOR_QUANT16_ASYMM
    • ANEURALNETWORKS_TENSOR_QUANT16_SYMM
    • ANEURALNETWORKS_TENSOR_QUANT8_SYMM
    • ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL
  • Vận hành

    • ANEURALNETWORKS_ABS
    • ANEURALNETWORKS_ARGMAX
    • ANEURALNETWORKS_ARGMIN
    • ANEURALNETWORKS_AXIS_ALIGNED_BBOX_TRANSFORM
    • ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_LSTM
    • ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_RNN
    • ANEURALNETWORKS_BOX_WITH_NMS_LIMIT
    • ANEURALNETWORKS_CAST
    • ANEURALNETWORKS_CHANNEL_SHUFFLE
    • ANEURALNETWORKS_DETECTION_POSTPROCESSING
    • ANEURALNETWORKS_EQUAL
    • ANEURALNETWORKS_EXP
    • ANEURALNETWORKS_EXPAND_DIMS
    • ANEURALNETWORKS_GATHER
    • ANEURALNETWORKS_GENERATE_PROPOSALS
    • ANEURALNETWORKS_GREATER
    • ANEURALNETWORKS_GREATER_EQUAL
    • ANEURALNETWORKS_GROUPED_CONV_2D
    • ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT
    • ANEURALNETWORKS_INSTANCE_NORMALIZATION
    • ANEURALNETWORKS_LESS
    • ANEURALNETWORKS_LESS_EQUAL
    • ANEURALNETWORKS_LOG
    • ANEURALNETWORKS_LOGICAL_AND
    • ANEURALNETWORKS_LOGICAL_NOT
    • ANEURALNETWORKS_LOGICAL_OR
    • ANEURALNETWORKS_LOG_SOFTMAX
    • ANEURALNETWORKS_MAXIMUM
    • ANEURALNETWORKS_MINIMUM
    • ANEURALNETWORKS_NEG
    • ANEURALNETWORKS_NOT_EQUAL
    • ANEURALNETWORKS_PAD_V2
    • ANEURALNETWORKS_POW
    • ANEURALNETWORKS_PRELU
    • ANEURALNETWORKS_QUANTIZE
    • ANEURALNETWORKS_QUANTIZED_16BIT_LSTM
    • ANEURALNETWORKS_RANDOM_MULTINOMIAL
    • ANEURALNETWORKS_REDUCE_ALL
    • ANEURALNETWORKS_REDUCE_ANY
    • ANEURALNETWORKS_REDUCE_MAX
    • ANEURALNETWORKS_REDUCE_MIN
    • ANEURALNETWORKS_REDUCE_PROD
    • ANEURALNETWORKS_REDUCE_SUM
    • ANEURALNETWORKS_RESIZE_NEAREST_NEIGHBOR
    • ANEURALNETWORKS_ROI_ALIGN
    • ANEURALNETWORKS_ROI_POOLING
    • ANEURALNETWORKS_RSQRT
    • ANEURALNETWORKS_SELECT
    • ANEURALNETWORKS_SIN
    • ANEURALNETWORKS_SLICE
    • ANEURALNETWORKS_SPLIT
    • ANEURALNETWORKS_SQRT
    • ANEURALNETWORKS_TILE
    • ANEURALNETWORKS_TOPK_V2
    • ANEURALNETWORKS_TRANSPOSE_CONV_2D
    • ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_LSTM
    • ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_RNN

Android 10 đưa ra bản cập nhật cho nhiều thao tác hiện có. Nội dung cập nhật chủ yếu liên quan đến những nội dung sau:

  • Hỗ trợ bố cục bộ nhớ NCHW
  • Hỗ trợ các tensor có thứ hạng khác 4 trong các thao tác mềm và chuẩn hoá
  • Hỗ trợ tích chập bị giãn
  • Hỗ trợ các đầu vào có lượng tử hoá hỗn hợp trong ANEURALNETWORKS_CONCATENATION

Danh sách dưới đây cho thấy các thao tác được sửa đổi trong Android 10. Để biết đầy đủ thông tin chi tiết về các thay đổi, hãy xem OperationCode trong tài liệu tham khảo của NNAPI.

  • ANEURALNETWORKS_ADD
  • ANEURALNETWORKS_AVERAGE_POOL_2D
  • ANEURALNETWORKS_BATCH_TO_SPACE_ND
  • ANEURALNETWORKS_CONCATENATION
  • ANEURALNETWORKS_CONV_2D
  • ANEURALNETWORKS_DEPTHWISE_CONV_2D
  • ANEURALNETWORKS_DEPTH_TO_SPACE
  • ANEURALNETWORKS_DEQUANTIZE
  • ANEURALNETWORKS_DIV
  • ANEURALNETWORKS_FLOOR
  • ANEURALNETWORKS_FULLY_CONNECTED
  • ANEURALNETWORKS_L2_NORMALIZATION
  • ANEURALNETWORKS_L2_POOL_2D
  • ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION
  • ANEURALNETWORKS_LOGISTIC
  • ANEURALNETWORKS_LSH_PROJECTION
  • ANEURALNETWORKS_LSTM
  • ANEURALNETWORKS_MAX_POOL_2D
  • ANEURALNETWORKS_MEAN
  • ANEURALNETWORKS_MUL
  • ANEURALNETWORKS_PAD
  • ANEURALNETWORKS_RELU
  • ANEURALNETWORKS_RELU1
  • ANEURALNETWORKS_RELU6
  • ANEURALNETWORKS_RESHAPE
  • ANEURALNETWORKS_RESIZE_BILINEAR
  • ANEURALNETWORKS_RNN
  • ANEURALNETWORKS_ROI_ALIGN
  • ANEURALNETWORKS_SOFTMAX
  • ANEURALNETWORKS_SPACE_TO_BATCH_ND
  • ANEURALNETWORKS_SPACE_TO_DEPTH
  • ANEURALNETWORKS_SQUEEZE
  • ANEURALNETWORKS_STRIDED_SLICE
  • ANEURALNETWORKS_SUB
  • ANEURALNETWORKS_SVDF
  • ANEURALNETWORKS_TANH
  • ANEURALNETWORKS_TRANSPOSE

Android 9

NN HAL 1.1 được giới thiệu trong Android 9 và có những thay đổi đáng chú ý sau đây.

  • IDevice::prepareModel_1_1 bao gồm một tham số ExecutionPreference. Người lái xe có thể sử dụng phương thức này để điều chỉnh quá trình chuẩn bị khi biết rằng ứng dụng muốn tiết kiệm pin hoặc sẽ thực thi mô hình trong các lệnh gọi nhanh liên tiếp.
  • 9 toán tử mới đã được thêm vào: BATCH_TO_SPACE_ND, DIV, MEAN, PAD, SPACE_TO_BATCH_ND, SQUEEZE, STRIDED_SLICE, SUB, TRANSPOSE.
  • Ứng dụng có thể chỉ định rằng có thể chạy các phép tính có độ chính xác đơn 32 bit bằng cách sử dụng dải số thực 16 bit và/hoặc độ chính xác bằng cách đặt Model.relaxComputationFloat32toFloat16 thành true. Cấu trúc Capabilities có trường relaxedFloat32toFloat16Performance bổ sung để trình điều khiển có thể báo cáo hiệu suất thoải mái cho khung.

Android 8.1

Neural Networks HAL (1.0) ban đầu được phát hành trong Android 8.1. Để biết thêm thông tin, hãy xem /neuralnetworks/1.0/.