8

スマートフォンでのARM浮動小数点パフォーマンスをx86と比較するとどうなるのか疑問に思いました。この目的のために、私は次のコードを書きました:

#include "Linderdaum.h"
sEnvironment* Env = NULL;

volatile float af = 1.0f;
volatile float bf = 1.0f;
volatile int a = 1;
volatile int b = 1;

APPLICATION_ENTRY_POINT
{
    Env = new sEnvironment();

    Env->DeployDefaultEnvironment( "", "CommonMedia" );

    double Start = Env->GetSeconds();

    float Sum1 = 0.0f;

    for ( int i = 0; i != 200000000; i++ )    {        Sum1 += af + bf;    }

    double End = Env->GetSeconds();

    Env->Logger->Log( L_DEBUG, LStr::ToStr( Sum1, 4 ) );
    Env->Logger->Log( L_DEBUG, "Float: " + LStr::ToStr( End-Start, 5 ) );

    Start = Env->GetSeconds();

    int Sum2 = 0;

    for ( int i = 0; i != 200000000; i++ )    {       Sum2 += a + b;    }

    End = Env->GetSeconds();

    Env->Logger->Log( L_DEBUG, LStr::ToStr( Sum2, 4 ) );
    Env->Logger->Log( L_DEBUG, "Int: " + LStr::ToStr( End-Start, 5 ) );

    Env->RequestExit();

    APPLICATION_EXIT_POINT( Env );
}

APPLICATION_SHUTDOWN
{}

さまざまなターゲットとコンパイラの結果は次のとおりです。

1. Corei7920上のWindowsPC。

VS 2008、デバッグビルド、Win32 / x86

(Main):01:30:11.769   Float: 0.72119
(Main):01:30:12.347   Int: 0.57875

floatより遅いですint

VS 2008、デバッグビルド、Win64 / x86-64

(Main):01:43:39.468   Float: 0.72247
(Main):01:43:40.040   Int: 0.57212

VS 2008、リリースビルド、Win64 / x86-64

(Main):01:39:25.844   Float: 0.21671
(Main):01:39:26.060   Int: 0.21511

VS 2008、リリースビルド、Win32 / x86

(Main):01:33:27.603   Float: 0.70670
(Main):01:33:27.814   Int: 0.21130

intリードを獲得しています。

2.サムスンギャラクシーSスマートフォン。

GCC 4.3.4、armeabi-v7a、-mfpu = vfp -mfloat-abi = softfp -O3

01-27 01:31:01.171 I/LEngine (15364): (Main):01:31:01.177   Float: 6.47994
01-27 01:31:02.257 I/LEngine (15364): (Main):01:31:02.262   Int: 1.08442

floatよりも大幅に遅いですint

ループ内の乗算への加算を変更してみましょう。

float Sum1 = 2.0f;

for ( int i = 0; i != 200000000; i++ )
{
    Sum1 *= af * bf;
}
...
int Sum2 = 2;

for ( int i = 0; i != 200000000; i++ )
{
    Sum2 *= a * b;
}

VS 2008、デバッグビルド、Win32 / x86

(Main):02:00:39.977   Float: 0.87484
(Main):02:00:40.559   Int: 0.58221

VS 2008、デバッグビルド、Win64 / x86-64

(Main):01:59:27.175   Float: 0.77970
(Main):01:59:27.739   Int: 0.56328

VS 2008、リリースビルド、Win32 / x86

(Main):02:05:10.413   Float: 0.86724
(Main):02:05:10.631   Int: 0.21741

VS 2008、リリースビルド、Win64 / x86-64

(Main):02:09:58.355   Float: 0.29311
(Main):02:09:58.571   Int: 0.21595

GCC 4.3.4、armeabi-v7a、-mfpu = vfp -mfloat-abi = softfp -O3

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

問題は、何が欠けているのか(コンパイラオプション)?ARMデバイスでは、浮動小数点演算は(intと比較して)本当に遅いですか?

4

4 に答える 4

4

-mfloat-abi=softfpエミュレートされた浮動小数点を明示的に要求します。Galaxyの仕様を確認し、可能であればハードウェアFPでコンパイルしてください。

そもそも、すべてのARMCPUがハードウェア浮動小数点をサポートしているわけではありません。ただし、NDKのARMEABIのデフォルト設定では、エミュレートされたFPが必要です。これは、FPのないマシンと互換性があるはずです。せいぜい、CPU機能で実行時の分岐を行うことができます。

于 2012-09-10T13:30:12.690 に答える
4

@Seva Alekseyev-mfloat-abiフラグは、浮動小数点値が関数に渡される方法のみを制御します。使用softfp値は、通常のレジスタを使用して渡されます。使用hardfp値は、FPUレジスタを使用して渡されます。-mfloat-abiフラグは、使用されるハードウェア命令を制御しません。

基本的softfpには、FPUを備えていないデバイスとの下位互換性を維持するために使用されます。willを使用softfpすると、FPUを備えたデバイスに余分なオーバーヘッドが発生します。

@Sergey K x86とARMを比較することは、リンゴとオレンジを比較するようなものです。これらは2つの非常に異なるプラットフォームです。ARMの主な設計目標は、速度ではなく低電力です。を使用すると、パフォーマンスがいくらか向上することがわかりますhardfp。利用可能なコンパイラの4.6バージョンもあります。アーキテクチャの違いを考えると、あなたの結果はもっともらしいと思います。

于 2012-09-10T13:52:44.523 に答える
4

これらの結果は信頼できます。

Exynos 3 SoCで使用されるCortex-A8コアには、パイプライン化されていないVFP実装があります。頭のてっぺんから正確な数値を覚えていませんが、VFPの加算と乗算のスループットは、そのコアで8サイクルごとにopのオーダーであるということを思い出します。

良いニュース:これは本当に古いSoCであり、新しいARM SoCにはより強力なVFP実装があります。add、sub、multiplyは完全にパイプライン化されており、スループットが大幅に向上しています。また、一部の(すべてではない)Cortex-A8 SoCはNEONをサポートしており、完全にパイプライン化された単精度浮動小数点を提供します。

于 2012-09-10T14:06:26.873 に答える
3

http://github.com/dwelch67/stm32f4dを参照 してください。float03ディレクトリを参照してください。

テストでは、これら2つの関数を固定と浮動小数点で比較します

.thumb_func
.globl add
add:
    mov r3,#0
loop:
    add r3,r0,r1
    sub r2,#1
    bne loop
    mov r0,r3
    bx lr

.thumb_func
.globl m4add
m4add:
    vmov s0,r0
    vmov s1,r1
m4loop:
    vadd.f32 s2,s0,s1
    sub r2,#1
    bne m4loop
    vmov r0,s2
    bx lr

結果はそれほど驚くべきことではありません。0x4E2C時間は固定小数点で、0x4E2Eは浮動小数点です。フロートテスト関数には、違いを説明する可能性のあるいくつかの追加の命令があります。

00004E2C                                                                        
00004E2C                                                                        
00004E2E                                                                        
00004E2E                                                                        
00004E2C                                                                        
00004E2E    

stm32f4のfpuは、その兄妹に見られるvfpの単精度バージョンに限定されています。上記のテストは、vfpハードウェアを備えた任意のarmv7で実行できるはずです。

__aeabi_fadd関数をリンクし、ループを介して毎回追加の呼び出しを行うことで、メモリアクセスの追加のタイミング、ライブラリ関数の外部または内部(vmov)での変換などを追加して、表示内容を増やすことができます。もちろん、答えは分解にあります。

于 2012-09-10T15:25:45.720 に答える