основанный на SSE уменьшение вектора с плавающей точкой Я пытался суммировать массив без знака длинный длинный но, к сожалению, безуспешно.
uint64_t vsum_uint64 (uint64_t *a, int n)
{
uint64_t sum; // lets say sum fits
__m128 vsum = _mm_set1_ps(0);
for (int i = 0; i < n; i += 2) { // 2 unit64 in single __m128
__m128 v = _mm_loadl_epi64(&a[i]);
vsum = _mm_add_epi64(vsum, v);
}
_mm_store_ss(&sum, vsum);
uint64_t *p = &vsum;
sum+=*(p+1);
// vsum = _mm_hadd_ps(vsum, vsum);
// vsum = _mm_hadd_ps(vsum, vsum);
return sum;
}
Это должно быть совершенно правильно, но gcc все еще не может скомпилировать его. Я искал ответы, но не нашел ни одного.
Вот что говорит GCC:
main.cpp: In function ‘uint64_t vsum_uint64(const uint64_t*, int)’:
main.cpp:73:35: error: cannot convert ‘const uint64_t* {aka const long unsigned int*}’ to ‘const __m128i* {aka const __vector(2) long long int*}’ for argument ‘1’ to ‘__m128i _mm_loadl_epi64(const __m128i*)’
main.cpp:74:31: error: cannot convert ‘__m128 {aka __vector(4) float}’ to ‘__m128i {aka __vector(2) long long int}’ for argument ‘1’ to ‘__m128i _mm_add_epi64(__m128i, __m128i)’
main.cpp:77:25: error: cannot convert ‘uint64_t* {aka long unsigned int*}’ to ‘float*’ for argument ‘1’ to ‘void _mm_store_ss(float*, __m128)’
main.cpp:78:17: error: cannot convert ‘__m128* {aka __vector(4) float*}’ to ‘uint64_t* {aka long unsigned int*}’ in initialization
Можете ли вы помочь ми, пожалуйста? Я действительно ценю это
Спасибо
Вот несколько вещей:
использование __m128i
вместо __m128
Вы можете инициализировать нулями vsum
с помощью __m128i vsum = _mm_setzero_si128()
;
для загрузки данных приведите к нужному типу __m128i и используйте упакованную версию (_mm_loadl_epi64 загружает только одно 64-битное целое число). так что либо
for (int i = 0; i < n; i += 2) { // 2 uint64 in single __m128i
__m128i v = _mm_loadu_si128(reinterpret_cast<__m128i*>(&a[i]));
или же
__m128i* pa = reinterpret_cast<__m128i*>(a);
for (int i = 0; i < n; i += 2) { // 2 uint64 in single __m128i
__m128i v = _mm_loadu_si128(pa);
pa++;
наконец, вы можете назначить сумму с помощью sum = vsum.m128i_u64[0] + vsum.m128i_u64[1];
если для него определено объединение (есть в windows / Visual-Studio, но вы используете другую среду).
Других решений пока нет …