Android端使用NNAPI运行ONNX模型无法调用GPU的问题求助
如何让ONNX Runtime通过NNAPI调用Android GPU运行模型
问题描述
我在Android环境下尝试通过NNAPI调用GPU运行ONNX模型,设备是搭载Android 12的Galaxy S10 5G,且所有模型层均支持GPU。但当前代码完全未调用GPU,即使在addNnapi()方法中添加CPU_DISABLES选项也无效。
现有代码实现
MainActivity.kt 部分代码
val modelID = R.raw.mobilenetv2_int8 val mobelbyteArray = resources.openRawResource(modelID).readBytes() val ortEnv = OrtEnvironment.getEnvironment() val ortoption = SessionOptions() ortoption.addNnapi() var orisession = ortEnv?.createSession(mobelbyteArray,ortoption); val height:Long = 224 val width:Long = 224 val batch_size = 1 val shape = longArrayOf(1, 3, height, width) val env = OrtEnvironment.getEnvironment() val imgData = FloatBuffer.allocate(height.toInt() * width.toInt() * batch_size * 3) val inputName = orisession?.inputNames?.iterator()?.next() env.use { val tensor = OnnxTensor.createTensor(env, imgData, shape) val startTime = SystemClock.uptimeMillis() tensor.use { val output = orisession?.run(Collections.singletonMap(inputName, tensor)) } }
build.gradle 配置
plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' } android { namespace 'com.example.onnxrunkt' compileSdk 33 defaultConfig { applicationId "com.example.onnxrunkt" minSdk 24 targetSdk 33 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } kotlinOptions { jvmTarget = '1.8' } /* aaptOptions{ noCompress 'onnx' } */ } dependencies { implementation 'com.microsoft.onnxruntime:onnxruntime-android:1.14.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.8.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' }
解决方案
配置NNAPI强制优先使用GPU
默认addNnapi()不会强制指定设备,需要通过NnapiOptions明确配置执行优先级并禁用CPU,让NNAPI只能选择GPU:val ortoption = SessionOptions() val nnapiOptions = SessionOptions.NnapiOptions() // 优先选择最快的单推理设备(通常为GPU) nnapiOptions.setExecutionPreference(SessionOptions.NnapiOptions.ExecutionPreference.PREFER_FAST_SINGLE_ANSWER) // 禁用CPU,排除CPU执行路径 nnapiOptions.setFlags(SessionOptions.NnapiOptions.Flag.DISABLE_CPU) ortoption.addNnapi(nnapiOptions)修复冗余的OrtEnvironment实例
代码中创建了两个OrtEnvironment实例,可能导致资源冲突,统一使用单个实例:val ortEnv = OrtEnvironment.getEnvironment(OrtLoggingLevel.VERBOSE) // 后续创建Tensor时使用同一个ortEnv val tensor = OnnxTensor.createTensor(ortEnv, imgData, shape)开启ONNX模型的不压缩配置
取消aaptOptions的注释,避免模型文件被压缩导致加载异常:aaptOptions { noCompress 'onnx' }添加日志与设备验证
开启VERBOSE日志查看NNAPI设备选择情况,同时打印可用NNAPI设备:// 初始化环境时开启详细日志 val ortEnv = OrtEnvironment.getEnvironment(OrtLoggingLevel.VERBOSE) // 打印所有可用的NNAPI设备 val nnapiDevices = OrtEnvironment.getAvailableNnapiDevices() nnapiDevices.forEach { device -> Log.d("NNAPI_DEVICE", "设备名称: ${device.name}, 设备类型: ${device.type}") }通过日志可以确认NNAPI是否成功识别GPU,以及是否有层回退到CPU执行。
验证GPU调用状态
使用Android Studio的Profiler工具,查看GPU实时负载;或者运行推理时观察设备发热情况,GPU运行时通常会有明显的负载提升。
内容的提问来源于stack exchange,提问作者Saejun Ko
相关产品推荐
相关产品推荐

