Этот код, как написано довольно неподходящими для ПСН, так как это так ветка тяжелый. Кроме того, информация о типах задействованных переменных помогла бы; тест, как написано, кажется довольно неясным (даже с исправлением >0
), но код выглядит так, что может быть C++, используя какой-то векторный класс, который перегружает operator -
, чтобы означать вычитание векторов и operator *
двух векторов для вычисления точечного продукта.
Первое, что нужно сделать с такими простыми циклами на SPE, - это получить их без ветвей (по крайней мере, внутренний цикл, т. Е. Развернуть пару раз и только проверить на ранний выход каждые N итераций) и использовать инструкции SIMD: У SPEs есть только инструкции SIMD, поэтому без использования SIMD-обработки в ваших циклах мгновенно тратится 75% вашего доступного пространства регистров и вычислительной мощности. Точно так же SPE могут загружать только согласованные qwords (16 байт) за раз, используя меньшие типы данных, требует дополнительной работы для перетасовки содержимого регистров, чтобы значение, которое вы пытаетесь загрузить, попадает в «предпочтительный слот».
Вы освобождаетесь от if (k == i || k == j)
, переписывая первую часть цикла, используя следующую форму без ветвей (это псевдокод. Это немедленно применимо для ints, но вам нужно использовать intrinsics для получения побитовых операций на поплавках):
dd = q2_vect[k] - q1_vect;
d2 = dd * dd;
d2 &= ~(cmp_equal(k, i) | cmp_equal(k, j));
Здесь cmp_equal
соответствует соответствующей SPE (семантика встроенных функций: cmp_equal(a,b) == (a == b) ? ~0u : 0
). Это заставляет d2
к нулю, когда k == i
или k == j
.
Чтобы избежать if (d2 > 0)
ветви во внутреннем контуре, сделайте следующее:
a |= cmp_greater(d2, 0);
и только проверить, если a
отличен от нуля (для раннего отъезда) каждые несколько итераций цикла. Если все значения, рассчитанные для d2
, являются неотрицательными (будет иметь место, если ваш тип - это ints, float или real-value vector class), вы можете упростить это дальше. Вобще:
a |= d2;
В конце концов, a
будет только отличен от нуля, если все индивидуальные условия были отличны от нуля. Но будьте осторожны с целыми переполнениями (если вы используете ints) и NaNs (если вы используете float). Если вам придется обрабатывать эти случаи, вышеуказанное упрощение нарушит код.
Последовательность `if d2 <0` недействительна C. – SingleNegationElimination 2010-11-28 18:22:27
И даже если вы добавите необходимые скобки, хороший компилятор оптимизирует весь оператор if, потому что язык C не определяет условия, при которых он может быть правдой. (Код, похоже, пытается полагаться на неопределенное поведение.) – 2010-11-28 18:24:14
не правильно: `dd == _Imaginary_I` ->` dd * dd == -1.0`, и это действительно C. – Vovanium 2010-11-28 19:22:36