我希望使用VFP Android设备定位ARMv6。
我的Android.mk
文件中有以下行以启用VFP
LOCAL_CFLAGS := -marm -mfloat-abi=softfp -mfpu=vfp -Wmultichar
我相信我使用ARMv5
定位VFP
。
我修改了android-ndk-r8b\toolchains\arm-linux-androideabi-4.6\setup.mk
以删除-msoft-float
。我还尝试使用原始setup.mk
我的代码工作正常99.99%,但有些时候在ARMv6设备上疯狂。 我有特殊的代码来检测它什么时候发疯。
代码
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上。
我认为它应该是与编译器设置或版本相关的一些常见的已知错误。可能是代码缺少内存障碍。
我想看到一些类似错误的参考。解决方法。或者关于bug的性质。
当ARMv7上的相同代码没有给出NaN时,我也常常在ARMv6上获得NaN值。
我已经调试了2周的代码并在网上搜索。如果有人可以分享类似问题的链接,那将是一个很大的帮助!
PS。这是一个编译命令的示例。我已经尝试了很多不同的设置。
编译器设置
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
更新2
所有这些设备都配有Qualcomm MSM7227A 它有ARM1136JF-S
到目前为止我学到的是这个bug可能与de-norms
有关
我读到ARMv7与ARMv6的差异,默认情况下denorms
刷新为零,ARM1136SF-S可选。
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0211k/DDI0211K_arm1136_r1p5_trm.pdf
尚不确定如何验证ARM上的Flush-To-ZERO标志。
更新3
此CPU的VFP称为VFP11
我找到了--vfp11-denorm-fix
选项。
还有--vfp-denorm-fix
他们纠正了VFP11
cpus中的错误。看起来像我的目标问题。
找到关于VFP11错误的一些帖子。希望它能修复代码。
答案 0 :(得分:2)
好像我发现了bug。
这是VFP11(ARMv6协处理器)denorm bug中的错误。 denormal numbers数字很小。
我在使用转储实现spring的物理代码中得到了这个数字
force1 = (Center - P1) * k1 // force1 directed to center
force2 = - Velocity * k2 // force2 directed against velocity
Object->applyForce(force1)
Object->applyForce(force2)
当物品进入Center
并且最后得到denormal
值时,两种力都变得非常小。
我可以重写sring和dumping但是我不能重新编写一个BulletPhysics洞或所有数学代码并预测每个(甚至内部)非正规数的出现。
链接器已修复代码选项--vfp11-denorm-fix
和--vfp-denorm-fix
http://sourceware.org/binutils/docs-2.19/ld/ARM.html
NDK链接器--vfp11-denorm-fix
这个选项有帮助。代码看起来更可重复,但它不能解决100%的问题。
我现在看到了更少的错误。
如果我等待sping稳定物体然后我终于得到denorm - &gt;为NaN
我必须等待更长时间,但同样的问题到了。
如果您知道解决方案会修复像--vfp11-denorm-fix
这样的代码,那么我会给您赏金。
我尝试了--vfp11-denorm-fix=scalar
和--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
中需要Android.mk
{1}}可能需要-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分钟后,只显示了一个可能与此错误有关的问题。
参考bug和修复 http://sourceware.org/ml/binutils/2006-12/msg00196.html
他们说GCC
仅使用scalr代码而--vfp11-denorm-fix=scalar
就足够了。
它增加了1个额外的命令来减速。但即使增加2个额外命令的--vfp11-denorm-fix=vector
也是不够的。
问题不易重新制作。在频率较高的800Mhz的手机上,我会更频繁地看到它,然后在较慢的600Mhz上。当市场上没有快速CPU时,可能会进行修复。
项目中有很多文件,每个配置编辑大约需要10分钟。 使用当前的修复状态进行测试需要大约10分钟才能在手机上播放。 +我们在灯下加热手机。热门手机可以更快地显示错误。
我希望测试不同的配置并报告最有效的修复方法。但是现在我们必须添加hack来杀死可能与denorms有关的最后一个bug。
我希望找到可以修复它的银弹,但只有-msoft-float
性能下降10倍或在ARMv7上运行应用程序就可以了。
在Spring / dumping代码中用新的fixDenorm
替换之前的fixDenormE
函数并为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;
}
}
答案 1 :(得分:0)
此页面讨论了ARM FPU选项:VfpComparison
我认为如果你想为ARM v6构建,你可以这样做:-march=armv6 -mcpu=generic-armv6 -mfloat-abi=softfp
(并省略-mfpu选项)。如果您没有专门针对上面提到的处理器,通用armv6没有保证的fpu。
另一种选择是尝试-mfloat-abi=hard
,基于softfp周围存在编译器错误的理论。
同时检查代码中是否存在任何堆栈损坏等,有可能在传递浮点值时会破坏它们。
P.S。您可能还想尝试一个浮点测试器,例如TestFloat或古老的netlib paranoia。虽然您在此特定处理器上有一个浮点失败的示例,并且使用这些编译器选项,但您不知道问题的普遍程度。它可能比你想象的更糟糕:)