VFP Unit Matrix Проблема умножения на iPhone - PullRequest
1 голос
/ 26 апреля 2010

Я пытаюсь написать умножение Matrix3x3, используя Vector Floating Point на iPhone, однако я сталкиваюсь с некоторыми проблемами. Это моя первая попытка написания любой сборки 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 кажется NULL, когда код asm был достигнут, несмотря на то, что он установлен pC = &C. Я предполагаю, что это из-за того, что компилятор переставил код в усадьбе, которая его сломала? Я пробовал различные методы, которые я видел, чтобы остановить это (например, добавление всего подходящего в список ввода - думал, что это даже не нужно, так как я перечисляю «память» в списке клоббера), и я все еще получаю те же проблемы.

Редактирование # 2: Правильно, проблема с памятью, по-видимому, была вызвана мной, не включив "r0" в список clobber, однако исправление этого (если оно действительно исправлено), похоже, не устранило проблему. Я заметил, что умножение матрицы вращения на единичную матрицу не работает правильно и вместо этого дает 0,88 в качестве последней записи в матрице вместо 1:

| 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? (P.S извините за то, что теперь стало действительно длинным вопросом :-P)

1 Ответ

0 голосов
/ 29 апреля 2010

Решил проблему! я не знал, что банки векторов были "круглыми".

Банки 0-7, 8-15, 16-23 и 24-31 могут содержать векторы длиной до 8 и могут использоваться в качестве векторов, просто указав, что вы используете s16 длиной 4 для пример. Тем не менее, в моем случае я использовал s14 с длиной 3, предполагая, что это даст мне s14, s15 и s16, но вместо этого, потому что это округло, он откатится к s8 - другими словами, я использовал s14, s15 и s8 .

Мне потребовалось много времени, чтобы увидеть это, так что, надеюсь, если у кого-то еще возникнет подобная проблема, он найдет это: -)

...