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 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.

HAL mạng nơron

HAL Mạng nơron (NN) định nghĩa khái quát hoá 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 các 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 chức 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 tất cả các loại dữ liệu và biểu thị hiệu suất không thư giãn bằ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 chức năng để hiểu tốc độ và mức tiết kiệm năng lượng của từng trình điều khiển khi thực thi. Để cung cấp thông tin này, trình điều khiển phải cung cấp các con số 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 cho các loại dữ liệu tương ứng. Bạn nên sử dụng các mô hình MobileNet v1 và v2, asr_floattts_float để đo lường hiệu suất cho các giá trị dấu phẩy động 32 bit và 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ài viết Bộ kiểm thử học máy Android.

Trong Android 9 trở xuống, cấu trúc Capabilities chỉ bao gồm thông tin về hiệu suất trình điều khiển cho tensor dấu phẩy động và 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.
  • 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 toán tích chập 3x3 và 5x5, nhưng không hỗ trợ các phép toán tích chập 7x7.
  • Trình điều khiển có các quy tắc ràng buộc về bộ nhớ khiến trình điều khiển không thể xử lý các biểu đồ hoặc dữ liệu đầu vào lớn.

Trong quá trình biên dịch, 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ó kích thước 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 trình điều khiển đó. Ví dụ: trình điều khiển có thể tạo mã hoặc tạo bản sao trọng số được sắp xếp lại. 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.

Nếu thành công, trình điều khiển sẽ trả về một tay điều khiển @1.3::IPreparedModel. Nếu trình điều khiển trả về 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 này 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.

Lệnh gọi thực thi đồng bộ cải thiện hiệu suất và giảm hao tổn khi tạo luồng so với 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ự hàng chính với phương diện đầ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 về thời gian sẽ được trả về 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 không xác định. Khi ít nhất một toán hạng đầu ra có thứ hạng hoặc phương diện 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 một 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 biết, 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 tuần tự hoá các lần 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 phải được giới hạn ở các thao tác ả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ư đặt trước bộ đệ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 mô hình đồng thời có hạn có thể phải khởi chạy lần đầu.

Trong 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 nhanh chóng, ứng dụng có thể chọn sử dụng đối tượng luồng thực thi để giao tiếp giữa các quy trình ứ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 theo đợt và hàng đợi thông báo nhanh.

Để cải thiện hiệu suất cho nhiều lần 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ó tất cả các kích thước được chỉ định, 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 mỗi 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 bộ đệm đầu ra có kích thước nhỏ, thì trình điều khiển phải cho biết những toán hạng đầu ra nào có kích thước bộ đệm không đủ trong danh sách 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ể, sử dụng giá trị 0 cho các kích thước không xác định.

Thời gian

Trong Android 10, ứng dụng có thể yêu cầu thời gian thực thi nếu ứng dụng đã chỉ định một thiết bị duy nhất để sử 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 khoảng thời gian này phải bao gồm thời gian thực thi bị tạm ngưng, ví dụ: khi thực thi bị các tác vụ khác chiếm quyền hoặc khi đang chờ 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 lớn 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 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 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ơ hàng rào đồng bộ hoá để chờ. Nếu tác vụ không đồng bộ hoàn tất trước khi lệnh gọi trả về, thì hệ thống 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ề một đối tượng IFencedExecutionCallback để cho phép khung truy vấn trạng thái lỗi và thông tin về thời lượng.

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 cho 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 hai toán tử luồng điều khiển, IFWHILE, lấy các mô hình khác làm đối số và thực thi các mô hình đó theo điều kiện (IF) hoặc lặp lại (WHILE). Để biết thêm thông tin về cách triển khai điều này, hãy xem phần Luồng điều khiển.

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

Trong Android 11, NNAPI giúp nâng cao chất lượng dịch vụ (QoS) bằng cách cho phép ứng dụng cho biết các mức độ ưu tiên tương đối của các mô hình, khoảng thời gian tối đa dự kiến cần để chuẩn bị một mô hình nhất định và thời lượng tối đa dự kiến cần để hoàn tất một phép tính nhất định. Để 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 hoàn tất việc sử dụng mô hình đã chuẩn bị, khung sẽ phát hành 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 này sẽ tự động bị huỷ trong dịch vụ trình điều khiển đã tạo đố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 dự kiế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 thao tác NNAPI, ngoại trừ các thao tác do nhà cung cấp xác định. Để biết thêm thông tin, hãy xem phần Tiện ích của nhà cung cấp.

Các toán tử đượ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 các kiểm thử CTS và VTS là chính xác. Bạn nên triển khai các phương thức tối ưu hoá có trong khung học máy dành cho thiết bị di động thay vì triển khai CPU NNAPI.

Hàm hiệu dụng

Cơ sở mã NNAPI bao gồm các hàm tiện ích 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 tiện ích, 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 khác nhau.

  • 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 các 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ể sử dụng các hàm nonExtensionOperandPerformanceupdate để giúp 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 tiện ích để xác thực rằng đối tượng HAL NN 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 HAL NN 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 theo dõi hệ thống vào mã Mạng nơron. Để 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 nội dung đại diện cho mô hình ở định dạng Graphviz (.dot) vào luồng đã chỉ định (nếu có) 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ử cách 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 hàm này kiểm thử từng phương thức API và xác minh rằng tất cả các thao tác do trình điều khiển hỗ trợ đều hoạt động chính xác 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:

  • Dấu phẩy động: 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ử tìm lỗi ngẫu nhiên NNAPI, Android sử dụng các kiểm thử dựa trên libFuzzer. Các kiểm thử này hiệu quả trong việc tìm lỗi ngẫu nhiên vì 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ử để tìm mã có vấn đề.

Để kiểm thử tìm lỗi mã nguồn 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ử tìm lỗi ngẫu nhiên 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 trình điều khiển phải xác thực các đối số của lệnh gọi mà chúng 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 thể 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 thử học máy Android

Bộ kiểm thử máy học Android (MLTS) là một điểm chuẩn NNAPI có trong CTS và VTS để xác thực độ chính xác của các mô hình thực trên 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 rằng độ chính xác của trình điều khiển không kém hơn so với cách 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.

  • MobileNetV1 độ 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.
  • MobileNetV2 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.
  • Mô hình âm thanh dựa trên bộ nhớ ngắn hạn dài (LSTM) để chuyển văn bản sang lời nói, chạy trên một tập hợp con nhỏ 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 điều kiện sử dụng nhiều hoặc trong các trường hợp đặc biệt về hành vi của ứng dụng.

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

  • Phát hiện tình trạng treo: Nếu ứng dụng NNAPI bị treo trong quá trình kiểm thử, thì kiểm thử sẽ không thành công với lý do thất bại 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 khi ứng dụng xảy ra sự cố và hoạt động 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 chương trình kiểm thử có thể phát hiện sự cố trình điều khiển gây ra lỗi trên lệnh gọi NNAPI. Xin lưu ý rằng có thể có sự cố trong các quy trình trình điều khiển không gây ra lỗi NNAPI và không gây ra lỗi kiểm thử. Để khắc phục 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 lỗi hoặc sự cố liên quan đến trình điều khiển.
  • 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ả các thử nghiệm sự cố đều có thể có 4 kết quả sau:

  • SUCCESS: Quá trình thực thi đã hoàn tất mà không gặp 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ột 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: Quy trình kiểm thử 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 thiết bị mục tiêu với máy trạm và đảm bảo bạn có thể truy cập thiết bị đó 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 của mạng nơron

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 ra mắt NN HAL 1.3, bao gồm các 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 các phiên bản đã ký và chưa ký của hầu hết các thao tác được lượng tử hoá, trình điều khiển phải tạo ra cùng một kết quả với độ lệch tối đa là 128. Có 5 trường hợp ngoại lệ đối với yêu cầu này: CAST, HASHTABLE_LOOKUP, LSH_PROJECTION, PAD_V2QUANTIZED_16BIT_LSTM. Toán tử QUANTIZED_16BIT_LSTM không hỗ trợ toán hạng đã ký và bốn toán tử còn lại hỗ trợ việc lấy mẫu đã ký 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ơ hàng rào đồng bộ hoá để chờ. Để biết thêm thông tin, hãy xem phần Thực thi có bảo vệ.
  • Hỗ trợ luồng điều khiển. Thêm các toán tử IFWHILE. Các toán tử này lấy các mô hình khác làm đối số và thực thi các mô hình đó theo điều kiện (IF) hoặc lặp lại (WHILE). Để biết thêm thông tin, hãy xem phần Luồng điều khiển.
  • Cải thiện chất lượng dịch vụ (QoS) vì các ứng dụng có thể cho biết các mức độ ưu tiên tương đối của các mô hình, khoảng thời gian tối đa dự kiến cần để chuẩn bị một mô hình nhất định và thời lượng tối đa dự kiến cần để hoàn tất một quá trình thực thi. Để biết thêm thông tin, hãy xem nội dung 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 phần Miền bộ nhớ.

Android 10

Android 10 ra mắt NN HAL 1.2, trong đó có các thay đổi đáng chú ý sau.

  • Cấu trúc Capabilities bao gồm tất cả các loại dữ liệu, bao gồm cả loại dữ liệu vô hướng và biểu thị hiệu suất không thư giãn bằng cách sử dụng 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. 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 một quá trình thực thi đồng bộ. Phương thức execute_1_2 yêu cầu khung thực hiện một quá trình thực thi một cách không đồng bộ. Hãy xem phần Thực thi.
  • Thông số MeasureTiming cho executeSynchronously, execute_1_2 và quá trình thực thi theo đợt chỉ định liệu trình điều khiển có đo lường 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à loại 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 phần Tiện ích của nhà cung cấp.
  • Khả năng một đối tượng hàng loạt kiểm soát một loạt 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ễ. Xem bài viết 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. Xem 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.

  • 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ó. Các bản cập nhật này 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 hoạt động mềm và chuẩn hoá
  • Hỗ trợ các phép tích chập mở rộng
  • 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. Trình điều khiển có thể sử dụng thông tin này để điều chỉnh quá trình chuẩn bị, vì biết rằng ứng dụng ưu tiên tiết kiệm pin hoặc sẽ thực thi mô hình trong các lệnh gọi liên tiếp nhanh chóng.
  • 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ó thêm trường relaxedFloat32toFloat16Performance để trình điều khiển có thể báo cáo hiệu suất thư giãn của nó 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/.