为什么使用SIMD指令时,这个简单的C ++ SIMD基准测试运行速度较慢?

问题描述 投票:0回答:1

我正在考虑编写SIMD向量数学库,因此,作为一个快速的基准测试,我编写了一个程序,该程序执行1亿个(按4个浮点数)矢量逐元素乘法,并将它们相加为累加总数。对于我的经典非SIMD变体,我只是制作了一个具有4个浮点数的结构,并编写了自己的乘法函数“ multiplyTwo”,该函数将两个这样的结构元素明智地相乘并返回另一个结构。对于我的SIMD版本,我使用了“ immintrin.h”以及__m128,_mm_set_ps和_mm_mul_ps。我正在i7-8565U处理器(威士忌湖)上运行,并使用以下命令编译:g++ main.cpp -mavx -o test.exe以在GCC中启用AVX扩展指令。

奇怪的是,SIMD版本大约需要1.4秒,而非SIMD版本只需要1秒。我觉得好像做错了什么,因为我认为SIMD版本的运行速度应该快4倍。感谢您的帮助,代码如下。我已经在注释中放置了非SIMD代码,当前形式的代码是SIMD版本。

#include "immintrin.h" // for AVX 
#include <iostream>

struct NonSIMDVec {
    float x, y, z, w;
};

NonSIMDVec multiplyTwo(const NonSIMDVec& a, const NonSIMDVec& b);

int main() {
    union { __m128 result; float res[4]; };
    // union { NonSIMDVec result; float res[4]; };

    float total = 0; 
    for(unsigned i = 0; i < 100000000; ++i) {
        __m128 a4 = _mm_set_ps(0.0000002f, 1.23f, 2.0f, (float)i);
        __m128 b4 = _mm_set_ps((float)i, 1.3f, 2.0f, 0.000001f);
        // NonSIMDVec a4 = {0.0000002f, 1.23f, 2.0f, (float)i}; 
        // NonSIMDVec b4 = {(float)i, 1.3f, 2.0f, 0.000001f};

        result = _mm_mul_ps(a4, b4); 
        // result = multiplyTwo(a4, b4);

        total += res[0];
        total += res[1];
        total += res[2];
        total += res[3];
    }

    std::cout << total << '\n';
}

NonSIMDVec multiplyTwo(const NonSIMDVec& a, const NonSIMDVec& b)
{ return {a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w}; }

c++ performance simd intrinsics avx
1个回答
0
投票

禁用优化功能(gcc的默认值为-O0),内在函数通常很糟糕。内在函数的Anti-optimized -O0 code-gen通常会带来很多伤害(甚至比标量更大),并且某些类似于函数的内在函数会带来额外的存储/重载开销。加上-O0的额外存储转发延迟往往会受到更大的损害,因为使用1个矢量而不是4个标量执行操作时,ILP会更少。

使用-O0

© www.soinside.com 2019 - 2024. All rights reserved.