这是一段看似非常特殊的C++代码.出于某种奇怪的原因,奇迹般地对数据进行排序使得代码几乎快了六倍.
#include <algorithm>
#include <ctime>
#include <iostream>
int main()
{
// Generate data
const unsigned arraySize = 32768;
int data[arraySize];
for (unsigned c = 0; c < arraySize; ++c)
data[c] = std::rand() % 256;
// !!! With this, the next loop runs faster.
std::sort(data, data + arraySize);
// Test
clock_t start = clock();
long long sum = 0;
for (unsigned i = 0; i < 100000; ++i)
{
// Primary loop
for (unsigned c = 0; c < arraySize; ++c) …Run Code Online (Sandbox Code Playgroud) 我有一个看起来像这样的功能(只显示重要部分):
double CompareShifted(const std::vector<uint16_t>& l, const std::vector<uint16_t> &curr, int shift, int shiftY) {
...
for(std::size_t i=std::max(0,-shift);i<max;i++) {
if ((curr[i] < 479) && (l[i + shift] < 479)) {
nontopOverlap++;
}
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
写得这样,我的机器上的功能耗时约34ms.将条件更改为bool乘法后(使代码看起来像这样):
double CompareShifted(const std::vector<uint16_t>& l, const std::vector<uint16_t> &curr, int shift, int shiftY) {
...
for(std::size_t i=std::max(0,-shift);i<max;i++) {
if ((curr[i] < 479) * (l[i + shift] < 479)) {
nontopOverlap++;
}
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
执行时间减少到~19ms.
使用的编译器是带有-O3的GCC 5.4.0,在使用godbolt.org检查生成的asm代码后,我发现第一个示例生成跳转,而第二个示例没有生成跳转.我决定尝试GCC 6.2.0,它在使用第一个例子时也生成一个跳转指令,但GCC 7似乎不再生成一个.
找到这种加速代码的方式是相当可怕的,花了很长时间.为什么编译器会以这种方式运行?这是程序员应该注意的吗?还有更类似的东西吗?
编辑:链接到godbolt https://godbolt.org/g/5lKPF3
我正在读Fedor Pikus 的这本书,他有一些非常非常有趣的例子,对我来说是一个惊喜。
特别是这个基准测试吸引了我,唯一的区别是在其中一个我们使用 || 在 if 和另一个中我们使用 |。
void BM_misspredict(benchmark::State& state)
{
std::srand(1);
const unsigned int N = 10000;;
std::vector<unsigned long> v1(N), v2(N);
std::vector<int> c1(N), c2(N);
for (int i = 0; i < N; ++i)
{
v1[i] = rand();
v2[i] = rand();
c1[i] = rand() & 0x1;
c2[i] = !c1[i];
}
unsigned long* p1 = v1.data();
unsigned long* p2 = v2.data();
int* b1 = c1.data();
int* b2 = c2.data();
for (auto _ : state)
{
unsigned long a1 …Run Code Online (Sandbox Code Playgroud) [简答:糟糕的基准测试方法.你觉得我现在已经想到了.]
问题表现为"找到一种快速计算x ^ y的方法,其中x和y是正整数".典型的"快速"算法如下所示:
public long fastPower(int x, int y) {
// Replaced my code with the "better" version described below,
// but this version isn't measurably faster than what I had before
long base = x; // otherwise, we may overflow at x *= x.
long result = y % 2 == 1 ? x : 1;
while (y > 1) {
base *= base;
y >>= 1;
if (y % 2 == 1) result *= base;
}
return …Run Code Online (Sandbox Code Playgroud) c++ ×3
java ×3
benchmarking ×2
optimization ×2
performance ×2
algorithm ×1
gcc ×1
jvm ×1
jvm-hotspot ×1