这是一段看似非常特殊的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) 我从各种来源(虽然大多数来自我的同事)中听到过,-O3用g ++ 的优化级别进行编译在某种程度上是"危险的",并且除非被证明是必要的,否则应该避免.
这是真的,如果是的话,为什么?我应该坚持-O2吗?
我发现了这个流行的大约 9 岁的SO 问题,并决定仔细检查其结果。
所以,我有 AMD Ryzen 9 5950X、clang++ 10 和 Linux,我从问题中复制粘贴了代码,这是我得到的:
排序 - 0.549702s:
~/d/so_sorting_faster$ cat main.cpp | grep "std::sort" && clang++ -O3 main.cpp && ./a.out
std::sort(data, data + arraySize);
0.549702
sum = 314931600000
Run Code Online (Sandbox Code Playgroud)
未分类 - 0.546554s:
~/d/so_sorting_faster $ cat main.cpp | grep "std::sort" && clang++ -O3 main.cpp && ./a.out
// std::sort(data, data + arraySize);
0.546554
sum = 314931600000
Run Code Online (Sandbox Code Playgroud)
我很确定 unsorted 版本比 3ms 快的事实只是噪音,但它似乎不再慢了。
那么,CPU 的架构发生了什么变化(使其不再慢一个数量级)?
以下是多次运行的结果:
Unsorted: 0.543557 0.551147 0.541722 0.555599
Sorted: …Run Code Online (Sandbox Code Playgroud) 我用 C 语言实现了一个冒泡排序,并在测试其性能时发现该-O3标志使其运行速度甚至比没有标志时还要慢!与此同时-O2,它的运行速度比预期的要快得多。
没有优化:
time ./sort 30000
./sort 30000 1.82s user 0.00s system 99% cpu 1.816 total
Run Code Online (Sandbox Code Playgroud)
-O2:
time ./sort 30000
./sort 30000 1.00s user 0.00s system 99% cpu 1.005 total
Run Code Online (Sandbox Code Playgroud)
-O3:
time ./sort 30000
./sort 30000 2.01s user 0.00s system 99% cpu 2.007 total
Run Code Online (Sandbox Code Playgroud)
代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
int n;
void bubblesort(int *buf)
{
bool changed = true;
for (int i = n; changed == true; …Run Code Online (Sandbox Code Playgroud) 在我的生活中,我不能记住那天老师说的话,我希望你可能知道.
该模块是"数据结构和算法",他告诉我们的一些事情:
该
if声明是最昂贵的[东西.[东西]注册[东西].
是的,我确实有一个可怕的记忆,我真的很抱歉,但我一直在谷歌搜索几个小时,没有任何事情发生.有任何想法吗?
哪个是实现返回数字绝对值的操作的最快方法?
x=root(x²)
Run Code Online (Sandbox Code Playgroud)
要么
if !isPositive(x):
x=x*(-1)
Run Code Online (Sandbox Code Playgroud)
实际上这个问题可以翻译为,有多快if(为什么请).
我的大学程序教授总是告诉我要避免使用ifs,因为它们非常慢,但我总是忘记问多慢和为什么.这里有人知道吗?
我正在阅读那个分支错误预测可能是应用程序性能的热门瓶颈.正如我所看到的,人们经常会显示汇编代码来揭示问题,并指出程序员通常可以预测分支在大多数时间内的位置并避免分支错误预测.
我的问题是:
1-是否可以使用某种高级编程技术(即无汇编)来避免分支错误预测?
2-我应该记住用高级编程语言生成分支友好的代码(我最感兴趣的是C和C++)?
欢迎使用代码示例和基准测试!
我需要一个程序来获取两个数字中较小的一个,我想知道是否使用标准"如果x小于y"
int a, b, low;
if (a < b) low = a;
else low = b;
Run Code Online (Sandbox Code Playgroud)
或多或少效率高于此:
int a, b, low;
low = b + ((a - b) & ((a - b) >> 31));
Run Code Online (Sandbox Code Playgroud)
(或者放在int delta = a - b顶部并随之重新放置实例的变化a - b).
我只是想知道哪一个更有效(或者如果差异太小而不相关),以及if-else语句与一般的替代方案的效率.
我想知道各种大小的循环如何在最近的x86处理器上执行,作为uop数的函数.
以下是彼得·科德斯(Peter Cordes)的一句话,他在另一个问题中提出了非多数的问题:
我还发现,如果循环不是4 uop的倍数,则循环缓冲区中的uop带宽不是每个循环的常数4.(即它是abc,abc,......;不是abca,bcab,......).遗憾的是,Agner Fog的microarch doc对循环缓冲区的这种限制并不清楚.
问题是关于循环是否需要是N uop的倍数才能以最大uop吞吐量执行,其中N是处理器的宽度.(即最近的英特尔处理器为4).在谈论"宽度"和计算微动时,有很多复杂因素,但我大多想忽略这些因素.特别是,假设没有微观或宏观融合.
Peter给出了以下一个循环,其中包含7个uop的循环:
一个7-uop循环将发出4 | 3 | 4 | 3 | ...的组我没有测试更大的循环(不适合循环缓冲区),看看是否有可能从下一个指令开始迭代发布在与其分支相同的组中,但我不假设.
更一般地说,声称是x在其体内具有uops 的循环的每次迭代将至少进行ceil(x / 4)迭代,而不是简单地迭代x / 4.
对于部分或全部最新的x86兼容处理器,这是真的吗?
performance x86 assembly cpu-architecture micro-optimization
C ++ 20引入的属性[[likely]]和[[unlikely]]该语言,其可以被用于允许编译器优化为的情况下一个执行路径或者多更容易或远小于可能比其他的。
考虑到错误分支预测的成本,这似乎是一个在代码的性能关键部分可能非常有用的功能,但我不知道它实际上会导致编译器做什么。
是否有一段简单的代码可以添加[[likely]]和[[unlikely]]属性更改编译器的程序集输出?也许更重要的是,这些变化有什么作用?
我为自己的理解创建了一个简单的示例,以查看程序集是否有任何差异,但似乎这个示例太简单了,无法实际显示对程序集的任何更改:
void true_path();
void false_path();
void foo(int i) {
if(i) {
true_path();
} else {
false_path();
}
}
void bar(int i) {
if(i) [[likely]] {
true_path();
} else [[unlikely]] {
false_path();
}
}
Run Code Online (Sandbox Code Playgroud)
c++ ×6
performance ×5
c ×3
optimization ×3
assembly ×2
gcc ×2
if-statement ×2
algorithm ×1
c++20 ×1
clang ×1
g++ ×1
java ×1
theory ×1
x86 ×1
x86-64 ×1