TFLite 模型在 GPU 上溢出,在 CPU 上正常。内部有什么区别?

TFLite model overflows on GPU, ok on CPU. What are the differences internally?

在 Android 上,我有一个模型在 CPU 上运行良好,但在切换到 GPU 委托时会溢出(结果为 'Infinity')。如果我重新缩放输入,我可以消除溢出,所以这似乎是 CPU 和 GPU 之间不同内部 range/precision 的问题。我的印象是 CPU 和 GPU 默认都使用 32 位浮点数,所以结果应该是相同的。有谁知道 TFLite 的内部结构足以提供一些见解?

关于浮点精度,Android上的TFLite GPU delegate可以运行两种模式,您可以在Options class中通过以下方法选择. (从 here 复制)

    /**
     * Sets whether precision loss is allowed.
     *
     * @param precisionLossAllowed When `true` (default), the GPU may quantify tensors, downcast
     *     values, process in FP16. When `false`, computations are carried out in 32-bit floating
     *     point.
     */
    public Options setPrecisionLossAllowed(boolean precisionLossAllowed) {
      this.precisionLossAllowed = precisionLossAllowed;
      return this;
    }

由于此 precisionLossAllowed 选项的默认值为 true,您的模型在默认情况下使用 GPU 时将 运行 在 FP16 模式下。如果你想像 CPU 那样在 FP32 模式下强制 运行ning,你应该在创建委托时明确地将此选项设置为 false

GpuDelegate.Options gpuOptions = new GpuDelegate.Options();
gpuOptions.setPrecisionLossAllowed(false);
GpuDelegate gpuDelegate = new GpuDelegate(gpuOptions);

Interpreter.Options interpreterOptions = new Interpreter.Options();
interpreterOptions.addDelegate(gpuDelegate);
Interpreter interpreter = new Interpreter(tflite_model_file, interpreterOptions);

这应该会为您提供与 CPU 模式相同的结果,但与 FP16 模式相比执行速度较慢。