Stop the presses! The Android developers did something almost sane!
As of Android NDK revision 9c, the GCC and Clang included in the NDK can build programs for the hardware floating point ABI on ARM. This is basically a free performance boost for all floating point code.
Almost. There are some caveats that you need to be aware of. They didn’t add support for hard float by recompiling everything in user space; instead, hard float programs execute within a system that is technically soft float. What does that mean in practice?
First, to utilize the hard float ABI, you must either compile every last
component of your application as hard float (the
switch), or mark individual functions with the appropriate
indicate the desired ABI. For example, to mark a function so that it’s called
with the soft float ABI, stick
__attribute__((pcs("aapcs"))) on it.
Note that the NDK will link to a
libm which uses the aforementioned attribute
on all of its functions. This means that if you use
libm functions a lot,
you’re not likely to get much of a boost in those places. The way to fix this
is to add
-mhard-float -D_NDK_MATH_NO_SOFTFP=1 to your GCC/Clang command
line. Then add
-lm_hard to your linker command line (or
-Wl,-lm_hard if you
just invoke GCC/Clang to link). This will make your application link statically
libm compiled for the hard float ABI. The only downside of this is that
your application will increase somewhat in size.
You will want to pass
--no-warn-mismatch to the linker to silence all
warnings about mixed floating point ABIs in objects. This is not ideal since it
could actually be helpful in some cases, but it’s not great to see a ton of
useless warnings either.
If you interact with any kind of FFI at all, such as JNI or P/Invoke, you’re in
for a bad time. Due to the fact that user space is still technically soft
float, VMs like Dalvik and Mono have absolutely no way of knowing whether a
native function should be invoked as soft float or hard float. Dalvik ‘solves’
this by forcing all JNI functions to use soft float (ugh). Make sure to slap
JNICALL on your JNI functions so they are marked as soft float - it seems a
lot of code exists that doesn’t do this, and it will break if compiled for
Also, keep in mind that hard float (obviously) assumes the presence of an FPU.
As such, it will only work on ARM v7 (
armeabi-v7a in Android terms). It may
work by chance on some
armeabi devices, but don’t rely on that.
So what about Mono?
There’s no real story for Mono at the moment - we don’t have the liberty to
force all native libraries to be recompiled with annotations to use the soft
float ABI, and it would undermine the performance gain of the hard float ABI.
We also have no way for users to mark native methods as soft or hard float and,
besides, that would require recompiling a ton of code and adding special cases
for hard float on ARM - not really acceptable for users. To make matters even
worse, since the hard float support on Android isn’t a proper Android ABI (like
x86), we can’t ask the C compiler which
ABI we should be using when invoking native functions.
In short: We’re screwed.
If Mono is ever going to support hard float on Android, we need the Android developers to make it a first-class ABI, and not just a compatibility hack.
That being said, Mono does support hard float on regular Linux!