Позвольте мне предисловие к этому. У меня очень ограниченный опыт работы с ASM, а тем более с SIMD.Портирование инструкций MMX/SSE для AltiVec
Но бывает, что у меня есть следующий оптимизированный код MMX/SSE, который я хотел бы передать в инструкции AltiVec для использования на процессорах PPC/Cell.
Это, вероятно, большой вопрос. Даже если это всего лишь несколько строк кода, у меня не было никаких проблем, пытаясь понять, что здесь происходит.
Оригинальная функция:
static inline int convolve(const short *a, const short *b, int n)
{
int out = 0;
union {
__m64 m64;
int i32[2];
} tmp;
tmp.i32[0] = 0;
tmp.i32[1] = 0;
while (n >= 4) {
tmp.m64 = _mm_add_pi32(tmp.m64,
_mm_madd_pi16(*((__m64 *)a),
*((__m64 *)b)));
a += 4;
b += 4;
n -= 4;
}
out = tmp.i32[0] + tmp.i32[1];
_mm_empty();
while (n --)
out += (*(a++)) * (*(b++));
return out;
}
Любые советы о том, как я мог бы переписать, чтобы использовать инструкции Altivec?
Моя первая попытка (очень неправильная попытка) выглядит примерно так. Но это не совсем (или даже отдаленно) правильно.
static inline int convolve_altivec(const short *a, const short *b, int n)
{
int out = 0;
union {
vector unsigned int m128;
int i64[2];
} tmp;
vector unsigned int zero = {0, 0, 0, 0};
tmp.i64[0] = 0;
tmp.i64[1] = 0;
while (n >= 8) {
tmp.m128 = vec_add(tmp.m128,
vec_msum(*((vector unsigned short *)a),
*((vector unsigned short *)b), zero));
a += 8;
b += 8;
n -= 8;
}
out = tmp.i64[0] + tmp.i64[1];
#endif
while (n --)
out += (*(a++)) * (*(b++));
return out;
}
Brilliant. Спасибо, Пол. Мне пришлось модифицировать векторный тип массива «нуль», чтобы иметь тип подписанного типа (в соответствии с переменной m128), но в остальном он работал с абсолютным удовольствием (и прорывается с точки зрения производительности). Это заставляет меня больше узнать о расширениях SIMD. – 2010-12-05 11:09:59