【问题标题】:Intel SIMD instructions speedup英特尔 SIMD 指令加速
【发布时间】:2023-03-06 14:49:01
【问题描述】:

我有以下代码:

long a[1000];
long b[1000];
long c[1000];
long d[1000];
long e[10000000];

double start, end;
for(int i = 0; i < 1000; i++){
    a[i] = i;
    b[i] = i*2;
    c[i] = i%13;
}
start = clock();
for(int k = 0; k < 10; k++){
    for(int j = 0; j < 1000000; j++){
        for(int i = 0; i < 1000; i++){
            a[i] *= a[i];
            b[i] *= b[i];
            c[i] = a[i] + b[i];
            d[i] = a[i] * c[i];
        }

    }
    e[0] += a[k];
}
end = clock();
cout << end-start <<"\t"<< e[0];

测试配置:intel core i7-4702MQ CPU,Haswell(据我所知,我的处理器支持AVX-II),intel c++ compiler v.14,visual studio 2013,Windows 8.1。

当我运行显示的代码时,我得到了 3403 毫秒的时间,如果我添加#pragma novetor,那么时间是 6934 毫秒,即加速只有 2 倍。但是如果我将所有数组的类型更改为 double,那么时间分别为 2067 ms 和 7479 ms,即 SIMD-speedup 超过 3.5 倍。为什么会这样?为什么整数类型的加速比这么小?

【问题讨论】:

  • 您使用什么编译器选项?您实际上需要告诉 ICC 使用 AVX2。 (或主机)
  • 哦,这可能是因为整数版本矢量化为 vpmulld,这在 Haswell 上很慢。 Haswell 每两个周期只能运行 1 个vpmulld,但它可以每个周期运行 2 个vmulpd

标签: c++ performance intel simd


【解决方案1】:

因为向量运算(#pragma novector 排除)是为浮点值设计的。如果使用整数,则添加两种类型之间的转换步骤。

【讨论】:

  • 对不起,我不明白。这是 AVX-2 指令software.intel.com/sites/landingpage/IntrinsicsGuide 的列表,其中包括带有压缩整数的操作(_mm256_add_epi32、__m256i _mm256_mul_epi32 等)。
  • 并不是它们不能处理整数,而是它们处理浮点值的效果更好。
【解决方案2】:

当允许向量化时,双精度实现使用 fma 指令和 vmulpd,其吞吐量为 0.5。

当使用整数运算时,它使用 vpmulld,其吞吐量为 1(性能的一半)。

但是,我无法重现你提到的表演。

  • 矢量化 - 双倍:4.76 秒;整数:3.04 秒
  • 没有矢量化 - 双倍:18.2 秒;整数:17.8 秒

由于编译器使用相同指令的标量版本,标量性能下降可以很容易地解释为双倍,但是对于整数,它使用imul 指令。

在 i7-4712MQ 上使用 Intel C++ 16.0、x64 编译获得的结果。 单线程

你可能会说它只是对 int 的 x6 改进,为什么不是 x8。嗯,在多线程中,int 版本的性能比双精度高 2.6 倍。由于超线程或大小不同的缓存行为,处理器可能更好地覆盖各种指令的延迟。

【讨论】:

    猜你喜欢
    • 2015-10-30
    • 2016-05-03
    • 1970-01-01
    • 2020-05-12
    • 2012-11-13
    • 1970-01-01
    • 2016-07-04
    • 1970-01-01
    • 2019-08-02
    相关资源
    最近更新 更多