Этот код в том виде, в котором он написан, совершенно не подходит для SPE, так как он очень тяжелый.Кроме того, информация о типах вовлеченных переменных могла бы помочь;тест, как написано, кажется довольно неясным (даже с исправлением >0
), но код выглядит так, как будто это C ++, использующий некоторый векторный класс, который перегружает operator -
для обозначения векторного вычитания и operator *
двух векторов для вычисленияскалярное произведение.
Первое, что нужно сделать с такими простыми циклами в SPE, - это освободить их от разветвлений (по крайней мере, внутреннего цикла; т.е. развернуть пару раз и проверять только ранний выход через каждые N итераций).) и используйте инструкции SIMD: SPE имеют только инструкции SIMD , поэтому, если вы не используете обработку SIMD в своих циклах, вы сразу же теряете 75% доступного пространства регистров и вычислительной мощности.Точно так же SPE могут загружать только выровненные qwords (16 байтов) за раз, использование меньших типов данных требует дополнительной работы, чтобы перетасовать содержимое регистров вокруг так, чтобы значение, которое вы пытаетесь загрузить, попало в «предпочтительный слот».
Вы избавляетесь от if (k == i || k == j)
, переписывая первую часть цикла, используя следующую форму без ветвей (это псевдокод. Он незамедлительно применим для целых чисел, но вам нужно использовать встроенные методы, чтобы получить побитовую)ops on float):
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
, неотрицательны (это будет иметь место, если ваш тип - целые числа, числа с плавающей запятой или вещественный векторный класс), вы можете еще больше упростить это.Просто сделайте:
a |= d2;
В конце концов, a
будет ненулевым, только если все отдельные термины отличны от нуля.Но будьте осторожны с целочисленными переполнениями (если вы используете целые числа) и NaN (если вы используете числа с плавающей запятой).Если вам придется обрабатывать эти случаи, приведенное выше упрощение нарушит код.