c++ - unsigned long long 数组的 sse 总和

标签 c++ sum sse simd uint64

基于 SSE reduction of float vector我试图对 unsigned long long 数组求和,但不幸的是没有成功。

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

你能帮我吗?我真的很感激

谢谢

最佳答案

这里有一些事情:

  1. 使用 __m128i 而不是 __m128

  2. 您可以使用 __m128i vsum = _mm_setzero_si128()vsum 进行零初始化;

  3. 对于数据加载,转换为正确的 __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++;
    
  4. 最后,如果为它定义了一个 union (下面是windows/Visual-Studio,但您使用的是不同的环境)。

关于c++ - unsigned long long 数组的 sse 总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22440536/

相关文章:

c++ - g++ -O2 错误地优化了 SIMD 变量赋值

c++ - Boost 的属性树 : deleting a child knowing its path

c++ - 如何在linux中重复一个进程(或设置一段进程)?

python - 在两个列表中查找匹配组件的总和

arrays - 分区求和算法

MYSQL创建一个触发器来汇总插入和更新的总金额

c++ - 如何在不使用任何 SSE 指令的情况下设置 __m128i?

c++ - 我如何使用 X11 获取当前光标位于其顶部的窗口?

c++ - 防止 C 预处理器执行特定的宏替换

c - 使用 SSE/AVX 的第 n 个根查找器的 FLT_EPSILON