本文介绍了Android的NDK:ARMv6的VFP +设备。计算错误,NaN的,非正规的数字,VFP11错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想指定的ARMv6 VFP与Android设备。

我已经按照我行 Android.mk 文件以启用 VFP

  LOCAL_CFLAGS:= -marm -mfloat-ABI = softfp -mfpu = VFP -Wmultichar

我相信,我的目标的ARMv5 VFP

我编辑 Android的NDK-R8B \\工具链\\ ARM-Linux的androideabi-4.6 \\ setup.mk 删除 -msoft浮动。我也试图与原始的 setup.mk

我的code工作时间的罚款99.99%,但有些时候去疯狂在ARMv6设备。
我有特殊的code当它疯狂的检测。

code

  GLM :: VEC3 D = P1  -  P2;
浮F1 = sqrtf(D.x * D.x + D.y * D.y + D.z * D.z);
如果((F1<!5)){
    // f1是更大然后5或NaN
    mylog_fmt(疯狂%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):疯狂-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
但是,当疯狂模式是是20.0

问题不再当我的ARMv7 CPU上运行它的存在。它仅存的ARMv6的CPU。

我相信这应该是编译器设置或版本相关的一些常见的已知的bug。可codeS缺少内存屏障。

我想看到一些参考类似的错误。的方式来解决它。或约错误的性质。

我也经常得到的ARMv6 NaN值时相同的ARMv7 code不给NaN的。

我调试code为2周已经和Web搜索。如果有人可以分享链接,类似的问题,这将是一个很大的帮助!

PS。我这里是编译命令之一。我尝试了许多不同的设置了。

编译器设置

<$p$p><$c$c>c:/soft/Android/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/$p$pbuilt/windows/bin/arm-linux-androideabi-g++
-MMD -MP -MF ./obj/local/armeabi/objs/main/sys/base.o.d -fpic -ffunction截面-funwind桌-fstack保护器
-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-例外-fno-RTTI -mthumb -Os -fomit-frame-pointer的-fno严格混叠-finline限制= 64
-Ijni /主/ -Ijni /主/ SYS -Ijni /主/子弹头/ src目录-Ijni /主/子弹头/ src目录/ LinearMath -Ijni /主/子弹头/ src目录/ BulletCollision / BroadphaseCollision
-Ijni /主/子弹头/ src目录/ BulletCollision / CollisionDispatch -Ijni /主/子弹头/ src目录/ BulletCollision / CollisionShapes -Ijni /主/子弹头/ src目录/ BulletCollision / NarrowPhaseCollision
-Ijni /主/子弹头/ src目录/ BulletDynamics / ConstraintSolver -Ijni /主/子弹头/ src目录/ BulletDynamics /动力学-Ijni /主/../ libzip / -Ic:/柔和/ Android版/ Android的NDK-R8B /来源/ CXX-STL / STLport的/的STLport
-ic:/柔和/ Android版/ Android的NDK-R8B /来源/ CXX-STL //加比++ /包括-Ijni /主
-DANDROID-marm -march = ARMv6的-mfloat-ABI = softfp -mfpu = VFP -Wmultichar-Wa, - noexecstack -frtti -O2 -DNDEBUG -g -Ic:/柔和/ Android版/ Android的NDK-R8B /平台/ Android的-5 /弓臂/ usr / include目录-c JNI /主/ SYS /基的.cpp
-o ./obj/local/armeabi/objs/main/sys/base.o

更新2

所有这些器件具有高通MSM7227A
它具有ARM1136JF-S

我学到到目前为止该错误可能涉及到去规范
我阅读的ARMv6地方ARMv7的差异是有 denorms 刷新为零默认和ARM1136SF-S有它可选。

尚未确定如何验证ARM的嵌入式到零的标志。

更新3

此CPU的VFP叫做 VFP11
我发现 - VFP11-denorm修复选项。
还有 - VFP-denorm修复
他们纠正勘误VFP11 的CPU。貌似我的目标问题。
几个有关VFP11排错发现帖子。希望这将解决code。


解决方案

好像我认定错误。

这是错误的VFP11(ARMv6的协处理器)denorm错误。
是非常小的数目。

我得到了物理code这个数字落实春季倾销

  = FORCE1(中心 -  P1)* K1 // FORCE1定向到中心
force2 = - 速度* K2 // force2针对速度
对象 - &GT; applyForce(FORCE1)
对象 - &GT; applyForce(force2)

这两种力量得到很小的时候对象archieve 中心我得到在结束非正规值。

我可以重新写入SRING和倾倒,但我不能重新写入漏洞BulletPhysics或所有数学code和predict每一个非正规的数(甚至内部)次数。

链接器修复code选项 - VFP11-denorm修复 - VFP-denorm修复

NDK链接器 - VFP11-denorm修复
此选项可帮助。 code看起来更repliable但它并不为100%解决问题。

我现在看到更少的错误。

但如果我等待稳定蔓延扩散对象,然后我终于我得到denorm - > NaN的

我要等待更长的时间,但同样的问题来。

如果您知道的解决方案,将解决code像 - 然后VFP11-denorm修复我应该给你提成

我都尝试 - VFP11-denorm修复=标 - VFP11-denorm修复=载体

刷新到零位

  INT X;
      //编译在ARM模式
      ASM(
              VMRS%[结果],FPSCR \\ r \\ n
              奥尔%[结果]%[结果]#16777216 \\ r \\ n
              VMSR FPSCR,%[结果]
              :[结果]= R(x)的:
      );

不知道为什么,但它需要 LOCAL_ARM_MODE:=手臂 Android.mk
可能是 -mfpu = VFP-D16 的,而不是仅仅 VFP 是必需的。

手动清除非正规数

我有上述春天code。
我通过手动清除非正规号码,而无需使用FPU具有以下功能改善了。

 内嵌无效fixDenorm(浮球放; F){
    工会FloatInt32 {
        无符号整数U32;
        浮F32;
    };
        FloatInt32网络连接;
        fi.f32 = F;        无符号整型指数=(fi.u32&GT;&GT; 23)及((1 <        如果(指数== 0)
            F = 0.f;
}


原创code在15-90秒内未能从开始在很多地方。

当前$ C下10分钟的物理模拟后显示的问题可能与此相关的错误只在一个到位。


引用错误并修复

他们说, GCC 只使用scalr code和 - VFP11-denorm修复=标足够。
它增加了1个额外的命令放缓。但是,即使 - ,增加了2个额外的命令VFP11-denorm修复=载体是远远不够的。

问题是不是更容易重新可生产。在具有较高的频率800Mhz的电话时,我看到它更经常然后在较慢的600Mhz的。可能的是,当有在市场中没有快速的CPU修复已完成。


我们在项目的许多文件和每个配置编译大约需要10分钟。
与固定的当前状态测试需要大约10分钟在手机上玩。 +我们在灯下热的手机。热门手机显示错误更快。

我想测试不同的配置和报告解决什么是最有效的。但现在我们必须添加黑客杀臭虫最后可能与denorms。

我希望能够找到灵丹妙药,这将修复它,但只有 -msoft浮动与ARMv7的10倍性能下降或运行应用程序做的。


在我换成previous fixDenorm 新的春天 fixDenormE /倾销code函数和申请ViewMatrix我摆脱过去错误的新功能。

 内嵌无效fixDenormE(浮球放; F,浮动小量= 1E-8){
    工会Data32 {
        无符号整数U32;
        浮F32;
    };
        Data32 D组;
        d.f32 = F;        无符号整型指数=(d.u32&GT;&GT; 23)及((1 <        如果(指数== 0)
            F = 0.f;
        如果(fabsf(F)&LT;小量){
          F = 0.f;
        }
}

I wish to target ARMv6 with VFP Android device.

I have following line in my Android.mk file to enable VFP

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

I believe I target ARMv5 with VFP.

I edited android-ndk-r8b\toolchains\arm-linux-androideabi-4.6\setup.mk to remove -msoft-float. I also tried with original setup.mk

My code works fine 99.99% of time but some times goes crazy on ARMv6 devices.I have special code to detect when it goes crazy.

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

It calculates distance between 2 points. Usually it is 0.000031But when crazy mode is on it is 20.0

The problem does not exists when I run it on ARMv7 CPU. It exists on ARMv6 CPU only.

I believe it should be some common known bug related to compiler settings or version. May be codes is missing memory barrier.

I would like to see some reference to similar bugs. Way to solve it. Or about nature of bug.

I also often get NaN values on ARMv6 when same code on ARMv7 does not give NaN.

I am debugging code for for 2 weeks already and searching the web. If someone could share link to similar problem it would be a great help!

PS. here is example of one of compile commands. I tried many different settings already.

Compiler Settings

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

All these devices have Qualcomm MSM7227AIt has ARM1136JF-S

What I learnt so far is that the bug could relate to de-normsI read somewhere ARMv7 differences WITH ARMv6 that is has denorms flush to zero by default and ARM1136SF-S has it optionally.http://infocenter.arm.com/help/topic/com.arm.doc.ddi0211k/DDI0211K_arm1136_r1p5_trm.pdf

Not yet sure how to verify that Flush-To-ZERO flag on ARM.

UPDATE 3

This CPU's VFP is called VFP11I found --vfp11-denorm-fix option.There is also --vfp-denorm-fixThey correct erratum in VFP11 cpus. Looks like my target problem.Found few posts about VFP11 erratum. Hope it will fix the code.

解决方案

Seems like I identified bug.

It is bug in VFP11 (ARMv6 coprocessor) denorm bug.denormal numbers are very small number.

I get this numbers in physics code implementing spring with dumping

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

Both forces get very small when object archieve Center and I get denormal values at the end.

I can re-write sring and dumping but I can't re-write hole BulletPhysics or all math code and predict every (even internal) occurance of denormal number.

Linker has fix code options --vfp11-denorm-fix and --vfp-denorm-fixhttp://sourceware.org/binutils/docs-2.19/ld/ARM.html

NDK linker has --vfp11-denorm-fixThis option helps. Code looks more repliable but it does not fix problem for 100%.

I see less bugs now.

BUt if I wait sping stabilize object then I finally I get denorm -> NaN

I have to wait longer but same problems arrive.

If you know solution that will fix code like --vfp11-denorm-fix should then I give you bounty.

I tried both --vfp11-denorm-fix=scalar and --vfp11-denorm-fix=vector

Flush to Zero bit

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

Not sure why but it requires LOCAL_ARM_MODE := arm in Android.mkMay be -mfpu=vfp-d16 instead of of just vfp is required.

Manually clear denormal numbers

I have spring code described above.I improved it by clearing denormal number manually without using FPU with following function.

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;
}


Original code was failing in 15-90 seconds from start in many places.

Current code showed issue possibly related to this bug in only one in place after 10 minutes of physics simulation.


Reference to bug and fixhttp://sourceware.org/ml/binutils/2006-12/msg00196.html

They say that GCC uses only scalr code and --vfp11-denorm-fix=scalar is enough.It adds 1 extra command to slow down. But even --vfp11-denorm-fix=vector that adds 2 extra commands is not enough.

Problem is not easier re-producible. On phones with higher frequency 800Mhz I see it more often then on slower one 600Mhz. It is possible that fix was done when there was no fast CPUs on market.


We have many files in project and every configuration compilations takes around 10 minutes.Testing with current state of fix requires ~10 minutes to play on phone. + We heat phone under the lamp. Hot phone shows errors faster.

I wish to test different configurations and report what fix is most efficient. But right now we have to add hack to kill last bug possibly related to denorms.

I expected to find silver bullet that will fix it but only -msoft-float with 10x performance degradation or running app on ARMv7 does it.


After I replaced previous fixDenorm function with new fixDenormE in spring/dumping code and applying the new function for ViewMatrix I get rid of last bug.

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;
        }
}

这篇关于Android的NDK:ARMv6的VFP +设备。计算错误,NaN的,非正规的数字,VFP11错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 07:18