iPhone で Vector Floating Point を使用して Matrix3x3 乗算を書き込もうとしていますが、いくつか問題が発生しています。これは、ARMアセンブリを作成する最初の試みであるため、私が見ていない簡単な解決策ではない可能性があります。
私は現在、私が書いた数学ライブラリを使用して小さなアプリケーションを実行しています。ベクトル浮動小数点ユニットが提供する利点を調査しているので、行列を乗算してasmに変換しました。以前はアプリケーションは問題なく実行されていましたが、現在はオブジェクトがすべてランダムに消えます。これは、ある時点で行列乗算の結果が NAN になることが原因のようです。
コードはこちら
IMatrix3x3 operator*(IMatrix3x3 & _A, IMatrix3x3 & _B)
{
IMatrix3x3 C;
//C++ code for the simulator
#if TARGET_IPHONE_SIMULATOR == true
C.A0 = _A.A0 * _B.A0 + _A.A1 * _B.B0 + _A.A2 * _B.C0;
C.A1 = _A.A0 * _B.A1 + _A.A1 * _B.B1 + _A.A2 * _B.C1;
C.A2 = _A.A0 * _B.A2 + _A.A1 * _B.B2 + _A.A2 * _B.C2;
C.B0 = _A.B0 * _B.A0 + _A.B1 * _B.B0 + _A.B2 * _B.C0;
C.B1 = _A.B0 * _B.A1 + _A.B1 * _B.B1 + _A.B2 * _B.C1;
C.B2 = _A.B0 * _B.A2 + _A.B1 * _B.B2 + _A.B2 * _B.C2;
C.C0 = _A.C0 * _B.A0 + _A.C1 * _B.B0 + _A.C2 * _B.C0;
C.C1 = _A.C0 * _B.A1 + _A.C1 * _B.B1 + _A.C2 * _B.C1;
C.C2 = _A.C0 * _B.A2 + _A.C1 * _B.B2 + _A.C2 * _B.C2;
//VPU ARM asm for the device
#else
//create a pointer to the Matrices
IMatrix3x3 * pA = &_A;
IMatrix3x3 * pB = &_B;
IMatrix3x3 * pC = &C;
//asm code
asm volatile(
//turn on a vector depth of 3
"fmrx r0, fpscr \n\t"
"bic r0, r0, #0x00370000 \n\t"
"orr r0, r0, #0x00020000 \n\t"
"fmxr fpscr, r0 \n\t"
//load matrix B into the vector bank
"fldmias %1, {s8-s16} \n\t"
//load the first row of A into the scalar bank
"fldmias %0!, {s0-s2} \n\t"
//calulate C.A0, C.A1 and C.A2
"fmuls s17, s8, s0 \n\t"
"fmacs s17, s11, s1 \n\t"
"fmacs s17, s14, s2 \n\t"
//save this into the output
"fstmias %2!, {s17-s19} \n\t"
//load the second row of A into the scalar bank
"fldmias %0!, {s0-s2} \n\t"
//calulate C.B0, C.B1 and C.B2
"fmuls s17, s8, s0 \n\t"
"fmacs s17, s11, s1 \n\t"
"fmacs s17, s14, s2 \n\t"
//save this into the output
"fstmias %2!, {s17-s19} \n\t"
//load the third row of A into the scalar bank
"fldmias %0!, {s0-s2} \n\t"
//calulate C.C0, C.C1 and C.C2
"fmuls s17, s8, s0 \n\t"
"fmacs s17, s11, s1 \n\t"
"fmacs s17, s14, s2 \n\t"
//save this into the output
"fstmias %2!, {s17-s19} \n\t"
//set the vector depth back to 1
"fmrx r0, fpscr \n\t"
"bic r0, r0, #0x00370000 \n\t"
"orr r0, r0, #0x00000000 \n\t"
"fmxr fpscr, r0 \n\t"
//pass the inputs and set the clobber list
: "+r"(pA), "+r"(pB), "+r" (pC) :
:"cc", "memory","s0", "s1", "s2", "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19"
);
#endif
return C;
}
私が見る限り、それは理にかなっています。_A = C
デバッグ中に、返品の前と ASM の後に言うと、_A
必ずしも同じであるとは限らないことに気付きましたC
。どちらが混乱を招くだけでした。おそらく、VFPU に与えているポインターが次のような行によって増分されているためだと思っていましたが"fldmias %0!, {s0-s2} \n\t"
、asm の理解は、問題を適切に理解するのにも、そのコード行への代替アプローチを確認するのにも十分ではありません。
とにかく、私よりも理解のある人が解決策を見ることができることを望んでいました。どんな助けでも大歓迎です、ありがとう:-)
pC
編集: asm コードが設定されているにもかかわらずヒットすると、それが NULL のように見えることがわかりましたpC = &C
。これは、コンパイラがコードを壊すマナーでコードを再配置したためだと思いますか? 私はこれを止めるために私が見たさまざまな方法を試しました(入力リストに関連するすべてのものを追加するなど-クロバーリストに「メモリ」をリストしているので、これは必要ではないと思いました)そして私はまだ得ています同じ問題。
編集#2:そうです、メモリの問題は"r0"
、クロバーリストに含めていないことが原因のようですが、それを修正しても(実際に修正された場合)、問題は修正されていないようです。回転行列に恒等行列を掛けても正しく機能せず、行列の最後のエントリとして 1 ではなく 0.88 が返されることに気付きました。
| 0.88 0.48 0 | | 1 0 0 | | 0.88 0.48 0 |
|-0.48 0.88 0 | * | 0 1 0 | = |-0.48 0.88 0 |
| 0 0 1 | | 0 0 1 | | 0 0 0.88|
そのとき、私の論理がどこかで間違っているに違いないと考えたので、アセンブリをステップ実行しました。最後の "fmacs s17, s14, s2 \n\t" までは問題ないようです。
s0 = 0 s14 = 0 s17 = 0
s1 = 0 s15 = 0 s18 = 0
s2 = 1 s16 = 1 s19 = 0
確かにfmacs
は操作を実行しています:
s17 = s17 + s14 * s2 = 0 + 0 * 1 = 0
s18 = s18 + s15 * s2 = 0 + 0 * 1 = 0
s19 = s19 + s16 * s2 = 0 + 1 * 1 = 1
しかし、結果はs19 = 0.88
私をさらに混乱させたfmacs
. (PS 申し訳ありませんが、今では本当に長い質問になりました:-P)