我正在阅读Agner Fog的优化手册,并且遇到了这个例子:
double data[LEN];
void compute()
{
const double A = 1.1, B = 2.2, C = 3.3;
int i;
for(i=0; i<LEN; i++) {
data[i] = A*i*i + B*i + C;
}
}
Run Code Online (Sandbox Code Playgroud)
Agner 指出,有一种方法可以优化此代码 - 通过认识到循环可以避免使用昂贵的乘法,而是使用每次迭代应用的“增量”。
我用一张纸来证实这个理论,首先......
...当然,他是对的 - 在每次循环迭代中,我们可以通过添加“增量”,基于旧结果计算新结果。该增量从值“A+B”开始,然后每一步增加“2*A”。
所以我们将代码更新为如下所示:
void compute()
{
const double A = 1.1, B = 2.2, C = 3.3;
const double A2 = A+A;
double Z = A+B;
double Y = C;
int i;
for(i=0; i<LEN; i++) {
data[i] …
Run Code Online (Sandbox Code Playgroud) 我一直在绞尽脑汁想要完成这项任务一周,我希望有人能带领我走向正确的道路.让我从教师的指示开始:
您的作业与我们的第一个实验作业相反,即优化素数计划.你在这个任务中的目的是使程序失望,即让它运行得更慢.这两个都是CPU密集型程序.他们需要几秒钟才能在我们的实验室电脑上运行.您可能无法更改算法.
要取消优化程序,请使用您对英特尔i7管道如何运行的了解.想象一下重新排序指令路径以引入WAR,RAW和其他危险的方法.想一想最小化缓存有效性的方法.恶魔无能.
该作业选择了Whetstone或Monte-Carlo程序.缓存有效性评论大多只适用于Whetstone,但我选择了Monte-Carlo模拟程序:
// Un-modified baseline for pessimization, as given in the assignment
#include <algorithm> // Needed for the "max" function
#include <cmath>
#include <iostream>
// A simple implementation of the Box-Muller algorithm, used to generate
// gaussian random numbers - necessary for the Monte Carlo method below
// Note that C++11 actually provides std::normal_distribution<> in
// the <random> library, which can be used instead of this function
double gaussian_box_muller() {
double x = 0.0;
double y = 0.0; …
Run Code Online (Sandbox Code Playgroud) 为了减轻内核或跨进程内存泄露(Spectre攻击),Linux内核1将使用新选项进行编译,-mindirect-branch=thunk-extern
引入以gcc
通过所谓的retpoline执行间接调用.
这似乎是一个新发明的术语,因为Google搜索仅在最近的使用中出现(通常都是在2018年).
什么是retpoline?它如何防止最近的内核信息泄露攻击?
1然而,它不是特定于Linux的 - 类似或相同的构造似乎被用作其他操作系统的缓解策略的一部分.
我不清楚编译器在需要时如何自动知道编译为64位.它如何知道什么时候可以自信地针对32位?
我很好奇编译器在编译时如何知道要定位的架构.它是否分析代码并根据它发现的内容做出决定?
核心和处理器之间有什么区别?
我已经在谷歌上找了它,但我只是有多核和多处理器的定义,但它与我想要的并不匹配.
我发现了这个流行的大约 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) 陷阱和中断有什么区别?
如果不同系统的术语不同,那么它们在x86上意味着什么?
我找不到足够的信息来决定我应该使用哪个编译器来编译我的项目.模拟一个过程的不同计算机上有几个程序.在Linux上,我正在使用GCC.一切都很棒.我可以优化代码,它可以快速编译并使用不那么多的内存.
我用MSVC和GCC编译器做自己的基准测试.后来一个产生稍快的二进制文件(对于每个子体系结构).虽然编译时间远远超过MSVC.
所以我决定使用MinGW.但是在MinGW中找不到有关异常处理方法及其实现的任何解释.我可以为不同的操作系统和体系结构使用不同的发行版.
注意事项: