支持 Android 的硬浮点数的 OpenCV
OpenCV with hard-float support for Android
我想在我的 Android 应用程序中使用硬件浮点支持,该应用程序大量使用 OpenCV 库。但是,当我为 hard-float 设置 gcc 标志时(如 here and here 所述),我收到链接器错误消息:
XXX.o uses VFP register arguments, output does not
。然后我添加链接器标志 -Xlinker --no-warn-mismatch
使这些错误消失但应用程序立即崩溃似乎是与 OpenCV 库的第一次交互。
到底是怎么回事?我是否正在编译代码的硬浮点版本并将其与软浮点 OpenCV 链接?
是否有一个版本的 OpenCV4Android 带有使用 hard-float 架构的预构建二进制文件?如果没有,是否可以编译这样的版本?一个人会怎么做?在使用 OpenCV 时是否有更聪明的方法来利用硬件浮点支持?
您无需在硬浮点模式下构建即可使用硬件浮点单元。只要您为 armeabi-v7a
ABI 构建,它就会使用硬件浮点单元 (VFPv3
)。
澄清一下,hard-float 选项(通过向编译器添加 -mhard-float
参数,或为 armeabi-v7a-hard
ABI 构建)仅更改将参数传递给函数的方式。在内部,Android 在整数寄存器中传递所有 float/double 函数参数。这确保了为 armeabi
构建的代码(ARMv5 不保证浮点单元,需要以这种方式传递这些参数)在 FPU 上的现代设备上 运行 时仍然有效。即,函数获取整数寄存器中的所有浮点参数并将它们移至 FPU 寄存器以在函数内进行所有计算。
使用 hard-float 选项构建时,此类参数直接在 FPU 寄存器中传递,但正如您的第二个 link 指出的那样,这要求您调用的所有代码都使用相同的选项构建,并且 JNI 函数入口点需要用 JNICALL
.
正确标记
因此,您从 hardfloat 中获得的实际好处只是您在每次函数调用中节省了一些指令(正如第一个 link 中的答案所指出的,这些非常便宜)。根据库的功能结构,这可能是一个完全无关紧要的更改,也可能很明显。不幸的是,我不太了解 OpenCV 的内部结构,无法猜测有多大的潜在加速(如果有的话)。
所以回顾一下,是的,你是对的,你只是在构建你的代码的硬浮点版本,但 link将它转换为 OpenCV 的软浮点 ABI 版本。为了使事情正常进行,您还可以在对 OpenCV 的所有函数调用上添加 __attribute__((pcs("aapcs")))
标记,但这几乎会抛弃所有潜在的优势,因为所有繁重的工作(很可能)是在库中完成的,而不是在您的调用代码中。
因此,为了获得硬浮动 ABI 的潜在好处,您需要使用 -mhard-float
参数重建所有 OpenCV(具体如何操作,虽然我帮不了您).但只要它是针对 armeabi-v7a
(使用 -march=armv7-a -mfpu=vfpv3
参数)构建的,它就应该已经在使用硬件 FPU,它只是使用向后兼容的 ABI。 softfp ABI 的开销比完整的 softfloat 版本(不是用 -mfpu=vfpv3
构建)的开销小几个数量级。
我想在我的 Android 应用程序中使用硬件浮点支持,该应用程序大量使用 OpenCV 库。但是,当我为 hard-float 设置 gcc 标志时(如 here and here 所述),我收到链接器错误消息:
XXX.o uses VFP register arguments, output does not
。然后我添加链接器标志 -Xlinker --no-warn-mismatch
使这些错误消失但应用程序立即崩溃似乎是与 OpenCV 库的第一次交互。
到底是怎么回事?我是否正在编译代码的硬浮点版本并将其与软浮点 OpenCV 链接?
是否有一个版本的 OpenCV4Android 带有使用 hard-float 架构的预构建二进制文件?如果没有,是否可以编译这样的版本?一个人会怎么做?在使用 OpenCV 时是否有更聪明的方法来利用硬件浮点支持?
您无需在硬浮点模式下构建即可使用硬件浮点单元。只要您为 armeabi-v7a
ABI 构建,它就会使用硬件浮点单元 (VFPv3
)。
澄清一下,hard-float 选项(通过向编译器添加 -mhard-float
参数,或为 armeabi-v7a-hard
ABI 构建)仅更改将参数传递给函数的方式。在内部,Android 在整数寄存器中传递所有 float/double 函数参数。这确保了为 armeabi
构建的代码(ARMv5 不保证浮点单元,需要以这种方式传递这些参数)在 FPU 上的现代设备上 运行 时仍然有效。即,函数获取整数寄存器中的所有浮点参数并将它们移至 FPU 寄存器以在函数内进行所有计算。
使用 hard-float 选项构建时,此类参数直接在 FPU 寄存器中传递,但正如您的第二个 link 指出的那样,这要求您调用的所有代码都使用相同的选项构建,并且 JNI 函数入口点需要用 JNICALL
.
因此,您从 hardfloat 中获得的实际好处只是您在每次函数调用中节省了一些指令(正如第一个 link 中的答案所指出的,这些非常便宜)。根据库的功能结构,这可能是一个完全无关紧要的更改,也可能很明显。不幸的是,我不太了解 OpenCV 的内部结构,无法猜测有多大的潜在加速(如果有的话)。
所以回顾一下,是的,你是对的,你只是在构建你的代码的硬浮点版本,但 link将它转换为 OpenCV 的软浮点 ABI 版本。为了使事情正常进行,您还可以在对 OpenCV 的所有函数调用上添加 __attribute__((pcs("aapcs")))
标记,但这几乎会抛弃所有潜在的优势,因为所有繁重的工作(很可能)是在库中完成的,而不是在您的调用代码中。
因此,为了获得硬浮动 ABI 的潜在好处,您需要使用 -mhard-float
参数重建所有 OpenCV(具体如何操作,虽然我帮不了您).但只要它是针对 armeabi-v7a
(使用 -march=armv7-a -mfpu=vfpv3
参数)构建的,它就应该已经在使用硬件 FPU,它只是使用向后兼容的 ABI。 softfp ABI 的开销比完整的 softfloat 版本(不是用 -mfpu=vfpv3
构建)的开销小几个数量级。