このようなタスクにはVFPユニットを使用できるはずです。NEONとVFPは同じレジスタバンクを共有します。つまり、1つのユニットを利用するためにレジスタをシャッフルする必要はなく、同じレジスタビットの異なるビューを持つこともできます。
あなた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
これをやってみたら、本当に感動を聞きたいです!