标签: cpu-architecture

如何安排x86 uops?

现代x86 CPU将传入的指令流分解为微操作(uops 1),然后在输入准备就绪时将这些uop 无序调度.虽然基本思路很清楚,但我想了解准备好指令的具体细节,因为它会影响微优化决策.

例如,采取以下玩具循环2:

top:
lea eax, [ecx + 5]
popcnt eax, eax
add edi, eax
dec ecx
jnz top
Run Code Online (Sandbox Code Playgroud)

这基本上实现了循环(具有以下对应关系:) eax -> total, c -> ecx:

do {
  total += popcnt(c + 5);
} while (--c > 0);
Run Code Online (Sandbox Code Playgroud)

通过查看uop细分,依赖链延迟等,我熟悉优化任何小循环的过程.在上面的循环中,我们只有一个携带的依赖链:dec ecx.环路(前三指令lea,imul,add)是开始新鲜每个环一个依赖关系链的一部分.

决赛decjne融合.因此,我们总共有4个融合域uop,以及一个仅循环携带的依赖链,延迟为1个周期.因此,基于该标准,似乎循环可以在1个周期/迭代时执行.

但是,我们也应该关注港口压力:

  • lea能够在端口1和5执行
  • popcnt可以在端口1上执行
  • add可以在端口0,1,5和6执行
  • 预测采用jnz在端口6上执行

因此,要进行1次循环/迭代,您几乎需要执行以下操作:

  • popcnt 必须在端口1上执行(它可以执行的唯一端口)
  • lea 必须 …

optimization performance x86 intel cpu-architecture

32
推荐指数
2
解决办法
2907
查看次数

为什么Linux(x86)的页面大小为4 KB,如何计算?

x86架构上的Linux内核的默认内存页面大小是4 KB,我想知道这是如何计算的,为什么?

linux x86 kernel cpu-architecture

31
推荐指数
4
解决办法
3万
查看次数

CPU架构演变如何影响虚拟函数调用性能?

几年前,我正在学习x86汇编程序,CPU流水线,缓存未命中,分支预测以及所有爵士乐.

这是两个半的故事.我在处理器viz指令重新排序,缓存预加载,依赖性交错等方面阅读了冗长流水线的所有优点.

缺点是规范的任何偏差都是非常昂贵的.例如,IIRC在早期千兆赫时代的某个AMD处理器每次通过指针(!)调用函数时都会有40个周期的惩罚,这显然是正常的.

这不是一个可以忽略不计的"别担心"号码!请记住,"良好设计"通常意味着"尽可能地考虑您的功能"和"在数据类型中编码语义",这通常意味着虚拟接口.

权衡是不执行此类操作的代码每个周期可能获得两个以上的指令.这些是在编写高性能C++代码时需要担心的数字,这些代码在对象设计上很重要并且可以解决数字运算问题.

据我所知,随着我们进入低功耗时代,长CPU流水线趋势已经逆转.这是我的问题:

最新一代x86兼容处理器是否仍然遭受虚拟功能调用,坏分支预测等的严重处罚?

cpu instruction-set cpu-architecture cpu-speed

30
推荐指数
1
解决办法
3917
查看次数

双问题处理器究竟是什么?

我遇到了几个关于双问题处理器概念的引用(我希望这句话在一个句子中有意义).我无法找到究竟是什么双重问题的任何解释.Google为我提供了微控制器规范的链接,但这个概念在任何地方都没有解释.这是这种参考的一个例子.我在找错了地方吗?关于它是什么的简短段落将非常有帮助.

embedded arm pipeline cpu-architecture

30
推荐指数
1
解决办法
1万
查看次数

Haswell/Skylake的部分寄存器究竟如何表现?写AL似乎对RAX有假依赖,而AH是不一致的

此循环在英特尔Conroe/Merom上每3个周期运行一次,imul按预期方式在吞吐量方面存在瓶颈.但是在Haswell/Skylake上,它每11个循环运行一次,显然是因为setnz al它依赖于最后一个循环imul.

; synthetic micro-benchmark to test partial-register renaming
    mov     ecx, 1000000000
.loop:                 ; do{
    imul    eax, eax     ; a dep chain with high latency but also high throughput
    imul    eax, eax
    imul    eax, eax

    dec     ecx          ; set ZF, independent of old ZF.  (Use sub ecx,1 on Silvermont/KNL or P4)
    setnz   al           ; ****** Does this depend on RAX as well as ZF?
    movzx   eax, al
    jnz  .loop         ; }while(ecx);
Run Code Online (Sandbox Code Playgroud)

如果setnz al …

x86 assembly intel cpu-architecture micro-optimization

30
推荐指数
2
解决办法
1537
查看次数

29
推荐指数
3
解决办法
2万
查看次数

旋转指令的目的是什么(ROL,x86上的RCL)?

我总是想知道一些CPU具有旋转指令的目的是什么(例如,ROL,x86上的RCL).什么样的软件使用这些说明?我首先想到它们可能用于加密/计算哈希码,但这些库通常用C编写,它没有映射到这些指令的运算符.
有没有人找到他们的用途?为什么他们在指令集中添加了哪些内容?

x86 assembly cpu-architecture machine-instruction

29
推荐指数
3
解决办法
3万
查看次数

分支预测和除零

我写的代码看起来像以下......

if(denominator == 0){
    return false;
}
int result = value / denominator;
Run Code Online (Sandbox Code Playgroud)

...当我考虑CPU中的分支行为时.

/sf/answers/785953171/ 这个答案说CPU将尝试正确猜测分支将走向哪个方向,并且如果发现分支错误地猜测分支,那么只停下该分支停止.

但是如果CPU预测上面的分支不正确,它将在以下指令中除以零.虽然这不会发生,我想知道为什么?CPU是否实际执行除零并在执行任何操作之前等待分支是否正确,还是可以告诉它在这些情况下不应该继续?这是怎么回事?

c++ error-handling optimization cpu-architecture branch-prediction

28
推荐指数
2
解决办法
1707
查看次数

L1缓存命中的周期/成本与x86上的Register相比?

我记得假设在我的架构类中L1缓存命中是1个周期(即与寄存器访问时间相同),但在现代x86处理器上实际上是这样吗?

L1缓存命中多少个周期?它与寄存器访问相比如何?

performance x86 cpu-architecture micro-optimization cpu-cache

27
推荐指数
2
解决办法
2万
查看次数

英特尔失去了周期?rdtsc和CPU_CLK_UNHALTED.REF_TSC之间的不一致

在最近的CPU上(至少在过去十年左右),除了各种可配置的性能计数器之外,英特尔还提供了三个固定功能硬件性能计数器.三个固定柜台是:

INST_RETIRED.ANY
CPU_CLK_UNHALTED.THREAD
CPU_CLK_UNHALTED.REF_TSC
Run Code Online (Sandbox Code Playgroud)

第一个计算退役指令,第二个计算实际周期,最后一个是我们感兴趣的."英特尔软件开发人员手册"第3卷的描述如下:

当核心未处于暂停状态而不处于TM停止时钟状态时,此事件计算TSC速率下的参考周期数.核心在运行HLT指令或MWAIT指令时进入暂停状态.此事件不受核心频率变化(例如,P状态)的影响,但计数与时间戳计数器的频率相同.当核心未处于暂停状态而不处于TM stopclock状态时,此事件可以估计经过的时间.

因此,对于CPU绑定循环,我希望该值与从中读取的自由运行TSC值相同rdstc,因为它们应该仅针对暂停的循环指令或"TM stopclock state"是什么发散.

我使用以下循环测试它(整个独立演示在github上可用):

for (int i = 0; i < 100; i++) {
    PFC_CNT cnt[7] = {};

    int64_t start = nanos();
    PFCSTART(cnt);
    int64_t tsc =__rdtsc();
    busy_loop(CALIBRATION_LOOPS);
    PFCEND(cnt);
    int64_t tsc_delta   = __rdtsc() - tsc;
    int64_t nanos_delta = nanos() - start;

    printf(CPU_W "d" REF_W ".2f" TSC_W ".2f" MHZ_W ".2f" RAT_W ".6f\n",
            sched_getcpu(),
            1000.0 * cnt[PFC_FIXEDCNT_CPU_CLK_REF_TSC] / nanos_delta,
            1000.0 * tsc_delta / nanos_delta,
            1000.0 * CALIBRATION_LOOPS / nanos_delta,
            1.0 * cnt[PFC_FIXEDCNT_CPU_CLK_REF_TSC]/tsc_delta); …
Run Code Online (Sandbox Code Playgroud)

performance x86 x86-64 cpu-architecture rdtsc

27
推荐指数
1
解决办法
1300
查看次数