| 3378 | using ::tflite::delegate::nnapi::kMinSdkVersionForNNAPI12; |
| 3379 | |
| 3380 | TfLiteStatus StatefulNnApiDelegate::DoPrepare(TfLiteContext* context, |
| 3381 | TfLiteDelegate* delegate) { |
| 3382 | // Do not check nodes_ if NN API is unavailable. |
| 3383 | const NnApi* nnapi = NnApiImplementation(); |
| 3384 | if (nnapi->android_sdk_version < kMinSdkVersionForNNAPI || |
| 3385 | !nnapi->nnapi_exists) { |
| 3386 | return kTfLiteOk; |
| 3387 | } |
| 3388 | bool is_accelerator_specified = false; |
| 3389 | // For NNAPI 1.2+, check if there is any accelerator available. |
| 3390 | // If not, don't delegate to NNAPI's CPU reference implementation. |
| 3391 | if (nnapi->android_sdk_version >= kMinSdkVersionForNNAPI12) { |
| 3392 | // Check if user specified an acclelerator to use. |
| 3393 | const char* device_name_ptr = GetOptions(delegate).accelerator_name; |
| 3394 | if (device_name_ptr) { |
| 3395 | if (!GetDeviceHandle(context, device_name_ptr)) { |
| 3396 | // If the selected accelerator cannot be found, NNAPI will not be used. |
| 3397 | return kTfLiteOk; |
| 3398 | } else { |
| 3399 | // also check if the selected device is not CPU reference impl. |
| 3400 | const string kNnapiReferenceImplName = "nnapi-reference"; |
| 3401 | is_accelerator_specified = kNnapiReferenceImplName != device_name_ptr; |
| 3402 | } |
| 3403 | } else { |
| 3404 | // If no accelerator is specified, only use NNAPI if an accelerator is |
| 3405 | // available. Any available accelerator will make the device_count larger |
| 3406 | // than 1. More sophisticated check and whitelisting can be added later. |
| 3407 | uint32_t device_count = 0; |
| 3408 | RETURN_TFLITE_ERROR_IF_NN_ERROR( |
| 3409 | context, nnapi->ANeuralNetworks_getDeviceCount(&device_count)); |
| 3410 | if (device_count <= 1) { |
| 3411 | return kTfLiteOk; |
| 3412 | } |
| 3413 | } |
| 3414 | } |
| 3415 | // Allocate one element in vector already since TensorFlow Lite uses |
| 3416 | // the first value as the number of nodes. The actual value will be set |
| 3417 | // later, after the vector has been filled. |
| 3418 | std::vector<int> supported_nodes(1); |
| 3419 | // We don't care about all nodes_, we only care about ones in the |
| 3420 | // current plan. |
| 3421 | TfLiteIntArray* plan; |
| 3422 | TF_LITE_ENSURE_STATUS(context->GetExecutionPlan(context, &plan)); |
| 3423 | |
| 3424 | int android_sdk_version = NnApiImplementation()->android_sdk_version; |
| 3425 | // Check for every node if it is supported |
| 3426 | for (int node_index : TfLiteIntArrayView(plan)) { |
| 3427 | TfLiteNode* node; |
| 3428 | TfLiteRegistration* registration; |
| 3429 | TF_LITE_ENSURE_STATUS(context->GetNodeAndRegistration( |
| 3430 | context, node_index, &node, ®istration)); |
| 3431 | if (NNAPIDelegateKernel::Map(context, registration->builtin_code, |
| 3432 | registration->version, android_sdk_version, |
| 3433 | node, is_accelerator_specified)) { |
| 3434 | supported_nodes.push_back(node_index); |
| 3435 | } |
| 3436 | } |
| 3437 | // First element in vector must be the number of actual nodes. |
nothing calls this directly
no test coverage detected