Android NDK:ARMv6 + VFP 设备。错误的计算、NaN、非正规数、VFP11 bug

2023-12-30

我希望使用 VFP Android 设备来定位 ARMv6。

我的以下行Android.mk文件以启用VFP

LOCAL_CFLAGS    := -marm -mfloat-abi=softfp -mfpu=vfp -Wmultichar

我相信我的目标ARMv5 with VFP.

我编辑过android-ndk-r8b\toolchains\arm-linux-androideabi-4.6\setup.mk去除-msoft-float。我也尝试过用原来的setup.mk

我的代码在 99.99% 的情况下都可以正常工作,但有时在 ARMv6 设备上会变得疯狂。 我有特殊的代码来检测它何时发疯。

Code

glm::vec3 D = P1 - P2;
float f1 = sqrtf(D.x*D.x + D.y*D.y + D.z*D.z);
if(!(f1 < 5)){
    // f1 is bigger then 5 or NaN
    mylog_fmt("Crazy %f %f %f %f", P1.x, P1.y, P1.z, f1);
    mylog_fmt("%f %f %f", P2.x, P2.y, P2.z);
}

LogCat:

12-14 00:59:08.214: I/APP(17091): Crazy -20.000031 0.000000 0.000000 20.000000
12-14 00:59:08.214: I/APP(17091): -20.000000 0.000000 0.000000

它计算 2 点之间的距离。通常为 0.000031 但当crazy mode就在 20.0

当我在 ARMv7 CPU 上运行时,该问题不存在。它仅存在于 ARMv6 CPU 上。

我相信这应该是一些与编译器设置或版本相关的常见已知错误。可能是代码缺少内存屏障。

我希望看到一些类似错误的参考。有办法解决。或者关于错误的性质。

当 ARMv7 上的相同代码不给出 NaN 时,我也经常在 ARMv6 上得到 NaN 值。

我已经调试代码两周了,并在网上搜索。如果有人可以分享类似问题的链接,那将是一个很大的帮助!

附言。这是编译命令之一的示例。我已经尝试了很多不同的设置。

编译器设置

c:/soft/Android/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-g++
-MMD -MP -MF ./obj/local/armeabi/objs/main/sys/base.o.d -fpic -ffunction-sections -funwind-tables -fstack-protector 
-D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__
-D__ARM_ARCH_5TE__  
-march=armv5te -mtune=arm6 
-mfloat-abi=softfp -mfpu=vfp
-fno-exceptions -fno-rtti -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 
-Ijni/main/ -Ijni/main/sys -Ijni/main/bullet/src -Ijni/main/bullet/src/LinearMath -Ijni/main/bullet/src/BulletCollision/BroadphaseCollision 
-Ijni/main/bullet/src/BulletCollision/CollisionDispatch -Ijni/main/bullet/src/BulletCollision/CollisionShapes -Ijni/main/bullet/src/BulletCollision/NarrowPhaseCollision 
-Ijni/main/bullet/src/BulletDynamics/ConstraintSolver -Ijni/main/bullet/src/BulletDynamics/Dynamics -Ijni/main/../libzip/ -Ic:/soft/Android/android-ndk-r8b/sources/cxx-stl/stlport/stlport 
-Ic:/soft/Android/android-ndk-r8b/sources/cxx-stl//gabi++/include -Ijni/main 
-DANDROID

-marm -march=armv6 -mfloat-abi=softfp -mfpu=vfp -Wmultichar

-Wa,--noexecstack  -frtti  -O2 -DNDEBUG -g   -Ic:/soft/Android/android-ndk-r8b/platforms/android-5/arch-arm/usr/include -c  jni/main/sys/base.cpp
-o ./obj/local/armeabi/objs/main/sys/base.o

UPDATE 2

所有这些设备都具有 Qualcomm MSM7227A 它有ARM1136JF-S

到目前为止我了解到该错误可能与de-norms我在某处读到 ARMv7 与 ARMv6 的差异denorms默认情况下刷新为零,ARM1136SF-S 可以选择刷新。http://infocenter.arm.com/help/topic/com.arm.doc.ddi0211k/DDI0211K_arm1136_r1p5_trm.pdf http://infocenter.arm.com/help/topic/com.arm.doc.ddi0211k/DDI0211K_arm1136_r1p5_trm.pdf

尚不确定如何验证 ARM 上的 Flush-To-ZERO 标志。

UPDATE 3

这个CPU的VFP叫做VFP11我发现--vfp11-denorm-fix选项。 还有--vfp-denorm-fix他们纠正了错误VFP11中央处理器。看起来像是我的目标问题。 发现了一些关于 VFP11 勘误表的帖子。希望它能修复代码。


看来我发现了错误。

这是 VFP11(ARMv6 协处理器)分值错误中的错误。非正规数 http://en.wikipedia.org/wiki/Denormal_number数量非常少。

我在通过转储实现 spring 的物理代码中得到了这个数字

force1 = (Center - P1) * k1         // force1 directed to center 
force2 = - Velocity * k2            // force2 directed against velocity
Object->applyForce(force1)
Object->applyForce(force2)

当对象归档时,两种力量都变得非常小Center我得到denormal值在最后。

我可以重写字符串和转储,但我无法重写孔子弹物理或所有数学代码并预测非正规数的每个(甚至内部)出现。

链接器有修复代码选项--vfp11-denorm-fix and --vfp-denorm-fix http://sourceware.org/binutils/docs-2.19/ld/ARM.html http://sourceware.org/binutils/docs-2.19/ld/ARM.html

NDK 链接器有--vfp11-denorm-fix此选项有帮助。代码看起来更可靠,但它并不能 100% 解决问题。

我现在看到的错误更少了。

但是如果我等待 sping 稳定对象,那么我最终会得到 denorm -> NaN

我必须等待更长的时间,但同样的问题也出现了。

如果您知道可以修复类似代码的解决方案--vfp11-denorm-fix那我应该给你赏金吗?

我都尝试过--vfp11-denorm-fix=scalar and --vfp11-denorm-fix=vector

刷新至零位

      int x;
      // compiles in ARM mode
      asm(
              "vmrs %[result],FPSCR \r\n"
              "orr %[result],%[result],#16777216 \r\n"
              "vmsr FPSCR,%[result]"
              :[result] "=r" (x) : :
      );

不知道为什么,但它需要LOCAL_ARM_MODE := arm in Android.mk May be -mfpu=vfp-d16而不是仅仅vfp是必须的。

手动清除非正规数

我有上面描述的弹簧代码。 我通过手动清除非正规数来改进它,而不使用具有以下功能的 FPU。

inline void fixDenorm(float & f){
    union FloatInt32 {
        unsigned int u32;
        float f32;
    };
        FloatInt32 fi;
        fi.f32 = f;

        unsigned int exponent = (fi.u32 >> 23) & ((1 << 8) - 1);
        if(exponent == 0)
            f = 0.f;
}

原始代码在许多地方从一开始就在 15-90 秒内失败。

当前代码在 10 分钟的物理模拟后仅出现了一个可能与此错误相关的问题。


参考错误和修复http://sourceware.org/ml/binutils/2006-12/msg00196.html http://sourceware.org/ml/binutils/2006-12/msg00196.html

他们说GCC仅使用标量代码并且--vfp11-denorm-fix=scalar足够。 它添加了 1 个额外的命令来减慢速度。但即使--vfp11-denorm-fix=vector添加 2 个额外命令是不够的。

问题并不容易重现。在频率较高的 800Mhz 手机上,我比在速度较慢的 600Mhz 手机上更常看到这种情况。修复可能是在市场上没有快速 CPU 的情况下完成的。


我们的项目中有很多文件,每个配置编译大约需要 10 分钟。 根据当前修复状态进行测试需要约 10 分钟才能在手机上玩游戏。 + 我们在灯下加热手机。热手机显示错误的速度更快。

我希望测试不同的配置并报告哪种修复最有效。但现在我们必须添加 hack 来消除最后一个可能与 denorms 有关的错误。

我希望找到解决这个问题的灵丹妙药,但只是-msoft-float性能下降 10 倍或在 ARMv7 上运行应用程序即可实现。


当我替换了之前的fixDenorm功能与新fixDenormE在 spring/dumping 代码中并应用 ViewMatrix 的新函数我摆脱了最后一个错误。

inline void fixDenormE(float & f, float epsilon = 1e-8){
    union Data32 {
        unsigned int u32;
        float f32;
    };
        Data32 d;
        d.f32 = f;

        unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1);
        if(exponent == 0)
            f = 0.f;
        if(fabsf(f) < epsilon){
          f = 0.f;
        }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android NDK:ARMv6 + VFP 设备。错误的计算、NaN、非正规数、VFP11 bug 的相关文章

随机推荐

  • XSD 和多态性

    我有点重复这个问题第一次被错误地问到 我有这个
  • 使用一个 NetStream 对象同时传输两个 Video 对象

    我试图将单个 NetStream 对象附加到两个单独的视频对象 而不是从服务器拉出冗余流 预期的行为是两个视频显示相同的内容 但是 我附加 NetStream 的最后一个视频似乎是唯一会显示内容的视频 还有其他人遇到过这个吗 如果不需要 我
  • 白色背景的错误屏幕

    当 iOS 上的 React Native 出现异常时 我会看到带有白色背景的错误屏幕 您可以通过点击的单元格看到它实际上具有异常堆栈 只是具有白色背景 不知道为什么会发生这种情况 但是有办法解决吗 在 Android 上 屏幕有红色背景
  • 如何访问 TTestSetup 类中 TTestCase 的字段

    我正在使用 DUnit 创建单元测试 我有一个类需要很长时间才能初始化 我从 TTestSetup 派生一个类 TMyTestSetup 并重写其 Setup 方法 对于我的 TTestCase 中的所有测试 仅调用此 SetUp 方法一次
  • 无法连接到 Dockerfile 中的 Wildfly

    我正在创建一个自定义 Dockerfile 其中包含官方 keycloak docker 映像的扩展 我想更改网络上下文并添加一些自定义提供程序 这是我的 Dockerfile FROM jboss keycloak 7 0 0 COPY
  • 屏幕截图不提供整个屏幕的图像

    我正在制作与图像相关的应用程序 我的屏幕上有多个图像 我已经拍了屏幕截图 但它不应该提供我的整个屏幕 最顶部和最底部的一小部分不需要在其中显示 我的顶部有导航栏 底部还有一些按钮 我不想在屏幕截图中捕获该按钮和导航栏 下面是我的屏幕截图代码
  • 正交相机并通过光线投射选择对象

    我在使用光线投射器使用正交相机选择对象时遇到了一些困难 不过 当我使用透视相机时 我没有任何问题 在两者之间切换时 我唯一要改变的是相机类型 我可以在正交视图上选择面 但它仅与我在屏幕上单击的位置松散相关 当我可以在远离物体的地方点击时 它
  • 使用Android绘制自定义视图

    我正在我的应用程序中绘制一个自定义视图 该视图基本上将参数 XML 作为要显示的文本 然后继续无限旋转它 当我进行这个控制时 我有一些疑问我想问 我已经制作了 2 个样式属性 我已在attrs xml文件 这些属性是设置我的控件中使用的圆的
  • 核心数据 - 货币小数类型

    我在最近的一篇文章中读到 十进制数据类型是核心数据中用于货币建模的最佳选择 因为它不存在浮点问题 我搜索了苹果文档和谷歌 似乎找不到任何有关使用 Decimal 类型的文档 有人有相关文档的链接吗 Thanks 使用 Decimal 作为数
  • 如何让我的java程序在GPU上运行?如何更改我的程序可以加速?[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我写了一个由几个类组成的程序 但是计算速度太慢 粗体的程序 我希望让我的java程序在GPU上运行以加快计算速度 或者有其他方法来加快
  • Flutter延迟一段时间后如何运行代码?

    我想在构建小部件后经过一定的延迟后执行一个函数 在 Flutter 中执行此操作的惯用方法是什么 我想要实现的目标 我想从默认开始FlutterLogoWidget 然后更改其style一段时间后的财产 您可以使用Future delaye
  • 键入任何?没有下标成员

    我想从个人资料字典中获取地址 但收到错误 键入任何 没有下标成员 var address String Any Address someLocation City ABC Zip 123 Address someLocation City
  • 将多个多页 tiff 图像合并为单个 tiff C#

    在我的场景中 我有 3 个或更多多页 tiff 图像 我需要将它们合并为单个 tiff 图像 下面是我尝试过的代码 它合并到单个 tiff 图像中 但仅与所有 tiff 图像的第一页合并 private static void MergeT
  • 使用 C# 将函数序列化为 json 中的参数

    我正在尝试使用 C 创建在 jQuery 中创建对象所需的 json 需要的json是 title title text upperVal 40 lowerVal 5 mouseover function return difference
  • 如何在 Visual C++ 中创建 .lib 文件和 .exe 文件?

    我目前有一个控制台项目 它创建一个 exe 文件 我希望它也创建一个 lib 文件 以便编译为 DLL 的其他项目能够调用原始项目中的函数 我知道这是可能的 但我找不到如何做到这一点 如何告诉链接器也链接 lib 发布此内容只是作为参考 我
  • Gmail API 用户模拟 (Python)

    我正在尝试通过服务帐户访问 Gmail API 并模拟我公司 G Suite 域中的用户来更改其电子邮件设置 我按照 Google 文档页面上的说明进行操作here https developers google com identity
  • JSF 重置文本字段[重复]

    这个问题在这里已经有答案了 我想在单击重置按钮时重置文本字段 我怎样才能在 JSF 中做到这一点 好吧 那就做一个
  • 如何在执行请求的控制器的方法之前调用方法:magento

    我想在执行每个控制器的方法之前调用一个方法 我不想去每个方法中都调用该方法 我只想从一个地方调用它 它将在 magento 中任何控制器的任何方法之前调用 我确信我们可以做到这一点 但我不知道如何实现 请提供您的建议 希望我们能够解决这个问
  • 在 Windows 上使用 PyCharm / iPython 控制台时出现“tput:未知终端 'emacs'”消息

    我在 Windows 上将 PyCharm 与 iPython 结合使用 我在盒子上安装的唯一 Python 是最新的 Anaconda 发行版 Python 3 4 版本 在使用控制台时 我经常收到以下警告消息的大量实例 tput unk
  • Android NDK:ARMv6 + VFP 设备。错误的计算、NaN、非正规数、VFP11 bug

    我希望使用 VFP Android 设备来定位 ARMv6 我的以下行Android mk文件以启用VFP LOCAL CFLAGS marm mfloat abi softfp mfpu vfp Wmultichar 我相信我的目标ARM