以前一直用D11,用了好多年,没有什么大问题,但小问题不少,最近把Delphi升级到了D12,最担心的几个控件包也解决了兼容问题(我只用5个,DevExpress,NextSuite,ComPort,FFVCL和多年累积下来自己写的一些工具控件),庆幸之余试了一下前几年自己封装的一套Tensorflow Lite 库,没想到出问题了。
我是封装了 Tensorflow Lite 的API接口库,包括CPU、GPU和NPU上推理,其中,CPU和NPU推理没有问题,但GPU调不起来,始终返回一个空指针对象
FDelegateOptions.is_precision_loss_allowed := 1;
FDelegateOptions.inference_preference :=Int32(TFLITE_GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED);
FDelegateOptions.inference_priority1 := Int32(TFLITE_GPU_INFERENCE_PRIORITY_MIN_LATENCY);
FDelegateOptions.inference_priority2 := Int32(TFLITE_GPU_INFERENCE_PRIORITY_AUTO);
FDelegateOptions.inference_priority3 := Int32(TFLITE_GPU_INFERENCE_PRIORITY_AUTO);
FDelegateOptions.experimental_flags:=Int32(TFLITE_GPU_EXPERIMENTAL_FLAGS_CL_ONLY);
FDelegateOptions.max_delegated_partitions:=1;
FDelegateOptions.model_token:=nil;
FDelegateOptions.serialization_dir:=nil;
FDelegateOptions.first_delegate_node_index:=0;
FDelegateOptions.last_delegate_node_index:=High(Integer);
FDelegateOptions.gpu_invoke_loop_times:=1;
GpuDelegate := GpuDelegateV2Create(@FDelegateOptions);
if (GpuDelegate <> nil) then
begin
InterpreterOptionsAddDelegate(InterpreterOptions, GpuDelegate);
GpuAvailable := True;
end;
//创建GPU的解释器
Interpreter := InterpreterCreate(Model, InterpreterOptions);
if Interpreter = nil then //在 D11.2, D11.3 和 D12 下总是返回一个空对象指针
raise ETensorFlowLiteFMXError.Create('Create interpreter error');
我总觉得这个和 Java SDK的版本有冲突,不兼容导致的,然后一顿输出尝试不同的Android Java SDK库,但结果全部失败,不死心,尝试把D11下的所有关于安卓的库和相关文件复制到D12下,也全部失败,然后尝试修改 PAClient 的库,试来试去还是失败,心里一凉,难到安卓下要用Delphi开发AI程序只能终结到D11了吗?
在折腾了几天后,今天冷静下来仔细想了想,之前看过一篇文章,提到过Delphi开发安卓程序有个重要的配置文件 AndroidManifest.xml,马上打开对比了一下,有点区别,最引起我注意的是这句话:
D12生成的是:
...
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="34" />
...
D11生成的是:
...
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="30" />
...
很明显,D11使用的是低版本的SDK,但之前我在D12的 SDK Manager 中导入过 D11 低版本的 Java SDK库啊? 难道光用 SDK Manager 中导入低版本的还不够? 于是我又在网上趴了一番,
这篇文章中提到 AndroidManifest.xml 文件是通过项目中 AndroidManifest.template.xml 这个模板文件中配置的,于是乎,直接在这个模板中指定 SdkVersion =30
再次编译运行,问题解决
使用CPU的推理速度,只有可怜的 1.2帧
使用NPU的推理速度,可以达到 8帧
使用GPU的推理速度,可以达到恐怖的 50帧