7

ARM NEON組み込み関数(llvm、iOS)を使用して内部ループをベクトル化しています。私は一般的にfloat32x4_tsを使用しています。私の計算は、このベクトルの4つのフロートのうち3つを合計する必要があることで終了します。

この時点でCフロートに戻りvst1q_f32、4つの値を取得して、必要な3つを合計することができます。しかし、1つまたは2つの命令でベクトルを使用して直接実行し、1つのレーンの結果を取得する方法があると、より効果的であると思いますが、これを実行するための明確なパスを見つけることができませんでした。

私はNEONプログラミングに不慣れであり、既存の「ドキュメント」はかなり恐ろしいものです。何か案は?ありがとう!

4

3 に答える 3

5

このようなタスクにはVFPユニットを使用できるはずです。NEONとVFPは同じレジスタバンクを共有します。つまり、1つのユニットを利用するためにレジスタをシャッフルする必要はなく、同じレジスタビットの異なるビューを持つこともできます。

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204j/ch05s03s02.html

あなたfloat32x4_tは128ビットなので、クアッド(Q)レジスタに配置する必要があります。アームイントリンシブのみを使用している場合は、どちらを使用しているかわかりません。問題は、4より上にある場合、VFPはそれを単精度として認識できないことです(好奇心旺盛な読者の場合:VFPバージョン間に違いがあり、これが最低限の要件であるため、これを単純に保ちました)。したがって、float32x4_tのような固定レジスタに移動するのが最善Q0です。この後、S0、S1、S2などのレジスタを合計しvadd.f32て、結果をARMレジスタに戻すことができます。

いくつかの警告...VFPとNEONは、理論的には同じレジスタバンクとパイプラインを共有する異なる実行ユニットです。このアプローチが他のアプローチよりも優れているかどうかはわかりません。言う必要はありませんが、繰り返しになりますが、ベンチマークを実行する必要があります。また、このアプローチはネオン組み込みでは合理化されていないため、インラインアセンブリを使用してコードを作成する必要があります。

これがどのように見えるかを確認するために簡単なスニペットを作成し、これを思いつきました。

#include "arm_neon.h"

float32_t sum3() {           
        register float32x4_t v asm ("q0");
        float32_t ret;

        asm volatile(
        "vadd.f32       s0, s1\n"
        "vadd.f32       s0, s2\n"
        "vmov           %[ret], s0\n"
        : [ret] "=r" (ret)
        :
        :);

        return ret;
}

objdumpのように見えます(gcc -O3 -mfpu = neon -mfloat-abi = softfpでコンパイル)

00000000 <sum3>:
   0:   ee30 0a20   vadd.f32    s0, s0, s1
   4:   ee30 0a01   vadd.f32    s0, s0, s2
   8:   ee10 3a10   vmov    r0, s0
   c:   4770        bx  lr
   e:   bf00        nop

これをやってみたら、本当に感動を聞きたいです!

于 2012-12-14T09:17:15.517 に答える
3

4 番目の要素をゼロにできますか? おそらくそれをコピーして使用するだけでvset_lane_f32

その場合、次のようなNEON を使用した ARM アセンブリのクワッドワード ベクトル内のすべての要素の合計からの回答を使用できます。

float32x2_t r = vadd_f32(vget_high_f32(input), vget_low_f32(input));
return vget_lane_f32(vpadd_f32(r, r), 0); // vpadd adds adjacent elements

これは実際には必要以上の作業を行うため、3 つの float を抽出しvget_lane_f32て追加する方が速い場合があります。

于 2012-12-14T01:23:38.823 に答える
2

(あるバージョンの) VLD1 を使用して追加のレーンにゼロをロードし (すでにゼロになるように調整できない場合)、続いて 2 つの VPADL 命令を使用して、4 つのレーンを 2 つ、次に 2 つのレーンにペアワイズ合計する必要があるようです。 1つに。

于 2012-12-14T01:22:56.970 に答える