Question

based on SSE reduction of float vector I tried to sum the array of unsigned long long but unfortunatelly without any success.

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;
}

This should be quite right, but gcc still can't compile it. I searched for answers, but haven't found any.

This is what gcc says:

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

Can you help mi please? I'd really appreciate it

Thanks

Était-ce utile?

La solution

Here are a few things:

  1. use __m128i instead of __m128

  2. you can zero-initialize vsum using __m128i vsum = _mm_setzero_si128();

  3. for data load, cast to the proper __m128i type and use the packed-load version (_mm_loadl_epi64 only loads one 64-bits integer). so, either

    for (int i = 0; i < n; i += 2) {    // 2 uint64 in single __m128i
        __m128i v = _mm_loadu_si128(reinterpret_cast<__m128i*>(&a[i]));
    

    or

    __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++;
    
  4. finally you may be able to assign to sum using sum = vsum.m128i_u64[0] + vsum.m128i_u64[1]; if there's a union defined for it (there is under windows/Visual-Studio, but you are using a different environment).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top