Intel c++编译器ICC似乎忽略了SSE/AVX设置

Intel c++ compiler, ICC, seems to ingnore SSE/AVX seetings

本文关键字:SSE AVX 设置 编译器 c++ ICC Intel      更新时间:2023-10-16

我最近下载并安装了用于Linux的英特尔c++编译器Composer XE 2013,它可以免费用于非商业开发。http://software.intel.com/en-us/non-commercial-software-development

我在常春藤桥系统上运行(它有AVX)。我有两个版本的函数做同样的事情。一个不使用SSE/AVX。另一个版本使用AVX。在GCC中,AVX代码大约比标量代码快四倍。然而,使用Intel c++编译器,性能就差得多了。使用GCC,我像这样编译

gcc m6.cpp -o m6_gcc -O3 -mavx -fopenmp -Wall -pedantic

对于Intel,我像这样编译

icc m6.cpp -o m6_gcc -O3 -mavx -fopenmp -Wall -pedantic

在这一点上,我只使用OpenMP进行计时(与omp_get_wtime())。奇怪的是,如果我把avx选项改为说msse2,代码无法与GCC编译,但与ICC编译得很好。事实上,我可以把mavx全部放在一起,它仍然可以编译。似乎无论我尝试什么选项,它都可以编译,但不能最佳地使用AVX代码。所以我想知道我是否在使用ICC启用/禁用SSE/AVX方面做错了什么?

这是我使用的AVX函数。

inline void prod_block4_unroll2_AVX(double *x, double *M, double *y, double *result) {
    __m256d sum4_1 = _mm256_set1_pd(0.0f);
    __m256d sum4_2 = _mm256_set1_pd(0.0f);
    __m256d yrow[6];
    for(int i=0; i<6; i++) {
        yrow[i] = _mm256_load_pd(&y[4*i]);
    }
    for(int i=0; i<6; i++) {
        __m256d x4 = _mm256_load_pd(&x[4*i]);
        for(int j=0; j<6; j+=2) {
            __m256d brod1 = _mm256_set1_pd(M[i*6 + j]);
            sum4_1 = _mm256_add_pd(sum4_1, _mm256_mul_pd(_mm256_mul_pd(x4, brod1), yrow[j]));
            __m256d brod2 = _mm256_set1_pd(M[i*6 + j+1]);
            sum4_2 = _mm256_add_pd(sum4_2, _mm256_mul_pd(_mm256_mul_pd(x4, brod2), yrow[j+1]));
        }
    }
    sum4_1 = _mm256_add_pd(sum4_1, sum4_2);
    _mm256_store_pd(result, sum4_1);
}

这是以秒为单位的计时信息。我运行了对应于L1、L2和L3缓存范围的三个范围。在L1区域只得到4x。请注意,ICC有更快的标量代码,但更慢的AVX代码。

GCC:
nvec 2000, repeat 100000
time scalar 5.847293
time SIMD 1.463820
time scalar/SIMD 3.994543
nvec 32000, repeat 10000
time scalar 9.529597
time SIMD 2.616296
time scalar/SIMD 3.642400
difference 0.000000
nvec 5000000, repeat 100
time scalar 15.105612
time SIMD 4.530891
time scalar/SIMD 3.333917
difference -0.000000
ICC:
nvec 2000, repeat 100000
time scalar 3.715568
time SIMD 2.025883
time scalar/SIMD 1.834049
nvec 32000, repeat 10000
time scalar 6.128615
time SIMD 3.509130
time scalar/SIMD 1.746477
nvec 5000000, repeat 100
time scalar 9.844096
time SIMD 5.782332
time scalar/SIMD 1.702444

两点:

(1)似乎你在代码中使用英特尔的内在特性——g++和icpc不一定实现相同的内在特性(但它们中的大多数重叠)。检查需要导入的头文件(g++可能需要提示来为您定义非艺术性)。g++在失败时给出错误消息吗?

(2)编译器标志并不意味着将生成指令(从icpc——help):-msse3 May generate Intel(R) SSE3, SSE2, and SSE instructions

这些标志通常只是给编译器的提示。您可能需要查看-xHost和-fast。

似乎无论我尝试什么选项,它都可以编译,但不能最佳地使用AVX代码。

你是怎么检查的?如果存在其他瓶颈(如内存带宽),您可能看不到4倍的加速。

编辑(基于问题编辑):

看起来icc标量比gcc标量更快——可能icc正在向量化标量代码。如果是这种情况,我不希望在手动编码矢量化时icc有4倍的加速。

至于icc在5.782332秒和gcc在3.509130秒之间的差异(对于新5000000);这是出乎意料的。根据我所掌握的信息,我无法说明为什么这两个编译器的运行时存在差异。我建议查看两个编译器发出的代码(http://www.delorie.com/djgpp/v2faq/faq8_20.html)。此外,确保您的测量是可重复的(例如,多插槽机器上的内存布局,热/冷缓存,后台进程等)。