Je me demandais comment les performances des points flottants sur les smartphones sont comparées à X86. Pour cette fin, j'ai écrit le code suivant:
01-27 02:02:20.152 I/LEngine (15809): (Main):02:02:20.156 Float: 6.97402 01-27 02:02:22.765 I/LEngine (15809): (Main):02:02:22.769 Int: 2.61264
4 Réponses :
Tous les protocoles de la CPU ne sont pas tous des moyens de support de matériel de la CPU pour commencer. Les paramètres par défaut de l'appel d'ARMEBI de NDK pour EMOLE PF Cependant, il est censé être compatible avec les machines FP-MOINS. Au mieux, vous pouvez faire une ramification de temps d'exécution sur les capacités de la CPU. P> -mfloat-abi = softfp code> appelle explicitement pour un point flottant émulé. Vérifiez les spécifications de votre galaxie et compilez avec le matériel FP si possible. P>
Non, softfp code> permet la génération de code à l'aide des instructions du point de flottabilité matérielles, mais utilise toujours les conventions d'appel à flotteur. gcc.gnu.org/onlinedocs/gcc/arm-opptions.htmlled/a >
Utilisant un point flottant dur, mais peut éviter les couches supplémentaires d'appels de fonction.
@ezeva alekseyev Le Fondamentalement @Sergey K comparer x86 et bras est comme comparer des pommes aux oranges. Ce sont deux plates-formes très différentes. Le but principal de la conception du bras est faible, pas de vitesse. Vous pouvez voir une certaine amélioration de la performance en utilisant -mfloat-abi code> Le drapeau ne contrôle que la manière dont les valeurs de point flottant sont transmises à des fonctions. Utilisation des valeurs code> softfp code> sont passées à l'aide de registres normaux. Utilisation des valeurs code> Hardfp CODE> sont transmises à l'aide de registres FPU. Le drapeau
-mfloat-abi code> ne contrôle pas les instructions matérielles sont utilisées. P>
softfp code> est utilisé pour maintenir la compatibilité reculée avec des périphériques qui n'ont pas de FPU. Utilisation de
softfp code> résultera d'une surcharge supplémentaire pour les appareils avec FPU. P>
hardfp code>. Il existe également une version 4.6 du compilateur disponible. Je pense que vos résultats sont plausibles compte tenu des différences d'architecture. P>
Quels sont les pièges de hardfp code>?
Votre binaire ne sera pas exécuté sur un appareil qui n'a pas de FPU. La plupart des nouveaux téléphones les ont.
Est-ce qu'il fonctionnera sur n'importe quelle puce compatible ARMV7?
Je ne sais pas. Malheureusement, il existe de nombreuses variantes sur des chipsets utilisant l'ensemble d'instructions de l'AMPV7. Ma meilleure hypothèse est non.
Dans ce cas, c'est un problème et je ne peux pas utiliser le mode dur code>.
Vous pouvez utiliser android_getcpufeatures () code> pour déterminer si un FPU est disponible. On dirait que tous les armv7 ont un FPU. De DOCS:
Android_CPU_ARM_FEATURE_VFPV3 CODE> indique que la CPU du périphérique prend en charge l'extension d'instructions du matériel FPU du matériel VFPV3. En raison de la définition de 'armée-v7a', ce sera toujours le cas si Android_CPU_ARM_FEATURE_ARMV7` est retourné.
Ces résultats sont crédibles. P>
Le noyau Cortex-A8 utilisé dans l'exynos 3 SOC a une implémentation VFP non pompette. Je ne me souviens pas des chiffres exacts du sommet de ma tête, mais mon souvenir est que le débit pour VFP Ajouter et Multiplier est de l'ordre d'un OP tous les 8 cycles sur ce noyau. P>
La bonne nouvelle: c'est un SOC vraiment ancien et le SOC plus récent des SOC d'ARM ont des implémentations de VFP plus fortes - Ajouter, SUB et Multiplier sont entièrement pipelinées et le débit est très amélioré. En outre, certains (mais pas tous) SOCS CORTEX-A8 SOCS SOCS NEON, qui vous donne un point flottant à une précision unique entièrement pipeline. P>
Bon point avec le néon. Il y a une page sur l'utilisation du néon dans le NDK. Voir: Docs / CPU-ARM-NEON.HTML
Voir http://github.com/dwelch67/stm32f4d Voir le répertoire flottant03
le test compare ces deux fonctions fixes vs float p> Les résultats ne sont pas trop surprenants, le temps 0x4E2C est un point fixe et 0x4e2e est float, il y a quelques instructions supplémentaires dans le flotteur Fonction de test qui représente probablement la différence: p> 00004E2C
00004E2C
00004E2E
00004E2E
00004E2C
00004E2E
Il est donc probable que __aeabi_fadd ou quelle que soit votre GCC utilise, a les opérandes dans les registres à usage général, de sorte que le point flottant ajoutez-vous contient trois instructions VMOV par opération que vous mesurez, vous essayez donc de comparer une instruction ajouter à six : BL, VMOV, VMOV, VADD, VMOV, BX par rapport à cette manière, peu importe la rapidité avec laquelle l'instruction de point flottant est-elle toujours plus lente que l'instruction de point fixe unique. Si vous pouvez obtenir le compilateur pour effectuer une comparaison équitable sans appels de bibliothèque, vous verrez le match de vitesse.
Pour clarifier mes résultats, les chiffres de HEX sont le nombre d'horloges système (éventuellement prescatées) pour 10000 boucles fixes et flottantes. Il n'y a pas de différence entre l'ajout du point fixe et le point flottant ajout. Il existe très clairement plusieurs fois plus d'instructions surhead la manière dont l'OP utilise le FPU qui expliquera la majorité de la différence d'exécution. Un test d'oranges de pommes vs, ce qui précède est un test de pommes de pépendant.
Changez l'ordre des tests: INT en premier, flottez plus tard. puis vérifiez si c'est sa même
@ Tuğrul Büyükışıık: Dois-je besoin de commutateurs de compilation supplémentaires?
Non, je voulais dire l'état d'échauffement de la CPU. Vous faites des tests entre Int-Float séparément ou dans le même rôle principal?
@ Tuğrul Büyükışışıe: Dans le même rôle principal () - J'utilise le code spécifié ci-dessus. J'ai changé l'ordre des boucles INT / Float - les résultats restent les mêmes.
Utilisez volatile sur vos variables de temps (début, fin)
Retirez la volatilité sur les variables AF / BF A / B et passez-les, vous mesurez des performances de mémoire ici plus que des performances de point flottant (naturellement, vous ne pouvez pas définir A / B comme des constantes ici, l'optimiseur les supprimera et publiera simplement la réponse).
Examinez le démontage pour le code de flotteur VS fixe.
@DWELCH: J'ai ajouté
volatile code> exactement pour empêcher l'optimiseur de calculer le résultat.
Je sais, c'est ce que j'ai dit. Qu'advient-il des résultats si vous retirez les cycles de mémoire et le temps de la mémoire. Examinez le code produit.
À partir d'une perspective matérielle, il s'agit d'ajouter ou de multiplier, il est plus impliqué dans le point flottant que le point fixe. Tous deux utilisent un point fixe alu (additionneur, multiplicateur, etc.), le flotteur doit bien préparer la valeur à l'avant et normaliser la valeur sur le backend. Idéalement, c'est un cycle d'horloge unique, mais pas toujours. Le FPU au bras (Eh bien, il y a plus d'un) Synchronise sur le backend, vous pouvez aller faire d'autres choses puis revenir et demander la réponse, puis il stands jusqu'à ce que la réponse soit faite si elle n'est pas terminée. Je ne sais pas comment fonctionne X86 FPUS. Puisque vous ajoutez un petit nombre, il devrait être très rapide.
D'accord avec @DWelch, retirez volatile de A / B, AF / BF. Si vous utilisez simplement la variable après la boucle qui suffira à garder l'optimiseur enlever le calcul.
Si vous pouvez ajouter un code source complet pour le bras avec des commutateurs de compilation que vous utilisez et publiez le résultat, je peux l'exécuter sur un autre noyau de bras et poster les résultats.