测试代码
// filename: test.cpp
#include <iostream>
#include <stdint.h>
#include <sys/time.h>
#include <ctime>
using namespace std;
int main(int argc, char *argv[]) {
struct timespec time_start={0, 0},time_end={0, 0};
uint8_t bitmap[20240];
int cost;
clock_gettime(CLOCK_REALTIME, &time_start);
for (int i = 0; i < 20240; ++i) {
bitmap[i >> 3] |= 1 << (i&7);
}
clock_gettime(CLOCK_REALTIME, &time_end);
cost = time_end.tv_nsec - time_start.tv_nsec;
cout << "case COST: " << cost << endl;
clock_gettime(CLOCK_REALTIME, &time_start);
for (int i = 0; i < 20240; ++i) {
bitmap[i >> 3] &= 1 << (i&7);
}
clock_gettime(CLOCK_REALTIME, &time_end);
cost = time_end.tv_nsec - time_start.tv_nsec;
cout << "case COST: " << cost << endl;
int a = bitmap[1];
// 下面这句话不注释会导致自动向量化失败,最终导致耗时增长100倍
// std::cout << "TEST: " << a << endl;
}
编译环境
gcc 4.8.2 + CentOS release 4.3。
编译命令
gcc -lstdc++ -std=c++11 -O2 test.cpp
产出结果为a.out
结果
执行./a.out,COST在200纳秒以内。但是如果加上cout,COST在20~30微妙之间。
简单分析
cout函数涉及到了ostream,使用cout对数组bitmap的值进行输出,涉及到了io控制流,将使得编译器不会对其进行优化(及向量化执行)。
自动向量化(Auto Vectorization)条件
翻译自
- 循环次数是可计算的
- 没有反向循环承载依赖
- 没有函数调用(除非是可向量化的数学函数,如sin,sqrt)
- 线性的代码(仅有一个控制流:没有switch;但是if条件是可以的,如果它可以是现成masked assignments)
- 如果是嵌套循环,向量化的一定是最内层的循环
自动向量化的常见技巧
例举了一些常用技巧,英文版貌似比中文版的内容多
自动向量化的编程指南
详细介绍了自动向量化成功和失败的各种情况。
实际应用
在实际的工作中,使用gcc自动向量化是最方便的方法,但是自动向量化的条件其实是很苛刻的。尽管在demo代码上,可以很容易地做到向量化,但是在工作上要进行向量化,目前还没有做到。