4

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

我在常春藤桥系统(具有 AVX)上运行。我有两个版本的函数做同样的事情。一个不使用 SSE/AVX。另一个版本使用 AVX。在 GCC 中,AVX 代码比标量代码快四倍。但是,使用英特尔 C++ 编译器时,性能要差得多。使用 GCC 我像这样编译

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

使用英特尔我这样编译

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

omp_get_wtime()在这一点上,我只使用 OpenMP 进行计时(使用)。奇怪的是,如果我将 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 区域只得到 4 倍。请注意,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
4

1 回答 1

1

两点:

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

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

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

似乎无论我尝试什么选项,它都可以编译,但没有充分利用 AVX 代码。

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

编辑(基于问题编辑):

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

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

于 2013-06-10T20:04:27.473 回答