c++ - 使用 SSE 和 STL vector 计算平均值

标签 c++ math sse

我正在尝试学习矢量化,而不是重新安装我正在使用的轮子 Agner Fog's vector library

这是我的原始 C++/STL 代码

#include <vector>
#include <vectorclass.h>   
template<typename T>
double mean_v1(T begin,T end) {
        float mean = 0;
        std::for_each(begin,end,[&mean](const double& d) { mean+=d; });

    return mean / std::distance(begin,end);
}

double mean_v2(T begin,T end) {
    float mean = 0;
    const int distance = std::distance(begin,end); // This is expensive
    const int loop = ( distance >> 2)+1; // divide by 4
    const int partial = distance & 2; // remainder 4
    Vec4d vec;
    for(int i = 0; i < loop;++i) {
        if(i == (loop-1)) {
            vec.load_partial(partial,&*begin);
            mean = horizontal_add(vec);
        }
        else  {
            vec.load(&*begin);
            mean = horizontal_add(vec);
            begin+=4; // This is expensive
        }
    }
    return mean / distance;
}

int main(int argc,char**argv) {
    using namespace boost::assign;
    std::vector<float> numbers;
    // Note 13 numbers, which won't fit into a sse register perfectly
    numbers+=39.57,39.57,39.604,39.58,39.61,31.669,31.669,31.669,31.65,32.09,33.54,32.46,33.45;

    const float mean1 = mean_v1(numbers.begin(),numbers.end());
    const float mean2 = mean_v2(numbers.begin(),numbers.end());


    return 0;
}

v1 和 v2 都可以正常工作,而且它们花费的时间大致相同。然而,分析它显示了 std::distance() 并且移动迭代器花费了将近 45% 的总时间。 vector 相加仅为 0.8%,明显快于 v1。

在网络上搜索,所有示例似乎都处理了恰好适合 SSE 寄存器的完美数量的值。人们如何处理奇数个值,例如在这个例子中,设置循环比计算花费的时间长得多。

我认为必须有关于如何处理这种情况的最佳实践或想法。

假设我无法更改 mean() 的接口(interface)以采用 float[],但必须使用迭代器

最佳答案

你不必要地混合了 float 和 double,特别是当你不让你的累加器加倍时,你的精度被完全破坏并且对于更大的系列来说不会接近令人满意。

由于算法是超轻量级的,因此这里破坏性能的最有可能是内存访问,请阅读内存缓存行及其工作方式。基本上你需要在这里做的是提前探测,一些处理器有明确的指令将东西拉到你的缓存中,否则你可以提前在内存位置执行加载。在您的循环中创建另一层嵌套,并定期使用您知道将在几次迭代中获得的数据填充缓存。

人们为最大限度地提高性能所做的是,他们花费大量时间实际设计数据布局。您不需要对数据进行中间转换。因此,人们所做的是分配对齐内存(大多数 SIMD 指令集要求或对读取/写入未对齐内存施加严重惩罚),然后他们尝试以适合指令集的方式聚合数据。事实上,将数据填充到指令集支持的任何寄存器大小通常是一个胜利。因此,如果假设您要处理 3 维 vector ,用一个未使用的额外元素填充几乎总是一个大赢家。

关于c++ - 使用 SSE 和 STL vector 计算平均值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17424037/

相关文章:

c++ - fstream 不读取所有整数

c++ - 如何在 C++ 中将包含复制构造函数的类的参数构造函数调用为私有(private)?

c++ - VS2010 SP1是否只支持部分AVX指令集?

image-processing - SIMD 像素对比度 : sum of differences between a pixel and its neighbors (uint16_t color components, 浮点总和)?

使用 url :port/url in getaddrinfo 的 c++ 套接字编程

c++ - 在一个类中创建一个线程并让它在 c++ (cpp) 中的类中的一个函数上执行

java - Math.pow 奇怪的结果

java - Lambert W 函数在 Java 中的实现

math - DSP方法来检测可能不是当前声音中最主要的特定频率

clang - Clang 的 '_mm256_pow_ps' 内在函数在哪里?