Intel c++编译器ICC似乎忽略了SSE/AVX设置
Intel c++ compiler, ICC, seems to ingnore SSE/AVX seetings
我最近下载并安装了用于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)。此外,确保您的测量是可重复的(例如,多插槽机器上的内存布局,热/冷缓存,后台进程等)。
- 单精度矩阵运算的特征性能 AVX 与 SSE 没有区别?
- 编写 std::copysign 的可移植 SSE/AVX 版本
- 使用 SSE/AVX 获取存储在__m256d中的值的总和
- 如何检查编译的代码是否使用了 SSE 和 AVX 指令?
- 如何在Windows上使用SSE和AVX说明来编译张量流
- 我可以将 AVX/SSE 与旋转功能用于 AoS 布局,而不是 SoA 吗?
- AVX,SSE总和比gcc自动矢量化慢
- AVX/SSE 回合向下浮动并返回整数向量
- 性能 AVX/SSE 程序集与内部函数
- AVX 中的矩阵向量乘法不成比例地比 SSE 中快
- SSE/AVX 寄存器的非零字节索引
- 是阻塞xmm/ymm寄存器的静态/静态本地SSE/AVX变量
- SSE拷贝、AVX拷贝和std::拷贝性能
- 将SSE矩阵矢量乘法代码转换为AVX
- 使用SSE和AVX查找矩阵中最大的元素及其列和行索引
- 强制AVX内部函数使用SSE指令
- Intel c++编译器ICC似乎忽略了SSE/AVX设置
- 传递包含SSE/AVX值的类型
- Ivy Bridge上使用SSE/AVX的最大SIMD整数乘法
- 快速点积使用SSE/AVX intrinsic