标签: micro-optimization

为什么n ++的执行速度比n = n + 1快?

在C语言中,为什么n++执行速度比n=n+1

(int n=...;  n++;)
(int n=...;  n=n+1;)
Run Code Online (Sandbox Code Playgroud)

我们的老师在今天的班上问了这个问题.(这不是作业)

c optimization performance micro-optimization

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

为什么mulss在Haswell上只用了3个周期,与Agner的指令表不同?

我是指令优化的新手.

我对一个简单的函数dotp进行了简单的分析,该函数用于获取两个浮点数组的点积.

C代码如下:

float dotp(               
    const float  x[],   
    const float  y[],     
    const short  n      
)
{
    short i;
    float suma;
    suma = 0.0f;

    for(i=0; i<n; i++) 
    {    
        suma += x[i] * y[i];
    } 
    return suma;
}
Run Code Online (Sandbox Code Playgroud)

我用昂纳雾在网络上提供的测试框架testp.

在这种情况下使用的数组是对齐的:

int n = 2048;
float* z2 = (float*)_mm_malloc(sizeof(float)*n, 64);
char *mem = (char*)_mm_malloc(1<<18,4096);
char *a = mem;
char *b = a+n*sizeof(float);
char *c = b+n*sizeof(float);

float *x = (float*)a;
float *y = (float*)b;
float *z = (float*)c;
Run Code Online (Sandbox Code Playgroud)

然后我调用函数dotp,n = 2048,repeat …

c optimization assembly sse micro-optimization

31
推荐指数
1
解决办法
1471
查看次数

现代x86成本模型

我正在编写一个带有x86后端的JIT编译器,并且随时学习x86汇编器和机器代码.大约20年前我使用ARM汇编程序,并对这些体系结构之间的成本模型差异感到惊讶.

具体来说,内存访问和分支在ARM上很昂贵,但在x86上等效的堆栈操作和跳转很便宜.我相信现代x86 CPU比ARM内核做更多的动态优化,我发现很难预测它们的影响.

编写x86汇编程序时要记住什么是好的成本模型?哪些指令组合便宜又昂贵?

例如,如果它总是生成用于加载整数或跳转到偏移的长格式,即使整数很小或偏移量接近但这会影响性能,我的编译器会更简单吗?

我还没有做任何浮动点,但我很快就会接受它.普通代码和浮动代码之间的相互作用有什么不明显的吗?

我知道有很多关于x86优化的参考文献(例如Michael Abrash),但我有一个预感,而不是几年前的任何东西都不适用于现代的x86 CPU,因为它们最近发生了很大的变化.我对么?

floating-point performance x86 assembly micro-optimization

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

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
查看次数

在 x86 汇编中取两个有符号整数的平均值的最快方法?

假设我们有两个寄存器长度为 2有符号1 的整数,例如ab。我们想要计算值(a + b) / 2,向上舍入、向下舍入、向零舍入或远离零舍入,无论哪种方式更容易(即我们不关心舍入方向)。

\n

结果是另一个寄存器长度有符号整数(很明显,平均值必须在寄存器长度有符号整数的范围内)。

\n

执行此计算最快的方法是什么?

\n

您可以选择两个整数最初位于哪个寄存器中,以及平均值最终位于哪个寄存器中。

\n
\n

脚注1:对于无符号整数,我们可以用两条指令来完成。尽管循环进位在 Intel CPU 上超过 1 uop,但这可能是最快的方法。但当计数仅为 1 时,只有一对。 关于无符号均值的问答中的答案讨论了效率。

\n
add rdi, rsi\nrcr rdi, 1\n
Run Code Online (Sandbox Code Playgroud)\n

rdi这两个数字以和开始rsi,平均值以 结束rdi。但对于有符号数,-1 + 3将设置 CF,并将 a 旋转1到符号位。没有给出正确答案+1

\n

脚注 2:我指定了寄存器长度的有符号整数,这样我们就不能简单地用movsxdorcdqe指令对整数进行符号扩展。

\n
\n

我得到的最接近的解决方案使用四个指令,其中一个rcr在 Intel 上为 3 uops,在 AMD …

optimization x86 assembly average micro-optimization

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

array_push()与$ array [] = ....哪个最快?

我需要将从MySQL接收的值添加到数组[PHP]中,这是我得到的:

$players = array();

while ($homePlayerRow = mysql_fetch_array($homePlayerResult)) {
    $players[] = $homePlayerRow['player_id'];
}
Run Code Online (Sandbox Code Playgroud)

这是唯一的方法吗?此外,以下更快/更好?

$players = array();

while ($homePlayerRow = mysql_fetch_array($homePlayerResult)) {
    array_push($players, $homePlayerRow['player_id']);
}
Run Code Online (Sandbox Code Playgroud)

提前致谢

php mysql micro-optimization

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

Java:if-return-if-return vs if-return-elseif-return

问一个无关的问题,我有这样的代码:

public boolean equals(Object obj)
{
    if (this == obj)
        return true;

    if (obj == null)
        return false;

    if (getClass() != obj.getClass())
        return false;

    // Check property values
}
Run Code Online (Sandbox Code Playgroud)

我得到了一条评论,声称这不是最优的,相反(如果我理解正确的话)应该这样做:

public boolean equals(Object obj)
{
    if (this == obj)
        return true;

    else if (obj == null)
        return false;

    else if (getClass() != obj.getClass())
        return false;

    // Check property values
}
Run Code Online (Sandbox Code Playgroud)

由于返回语句,我无法真正理解为什么它们中的任何一个应该比另一个更高效或更快.鉴于某个对象,就我所见,这两种方法都必须进行相同数量的检查.并且由于返回语句,不会在其中任何一个中运行额外的代码.

我在这里错过了什么吗?有东西吗?是否有一些编译器优化或正在发生的事情或其他什么?

我知道这是微优化,我很可能会坚持第一种方式,因为我认为它看起来比较清晰,所有的ifs都在同一个位置上.但我无能为力; 我很好奇!

java if-statement micro-optimization

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

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

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

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

performance x86 cpu-architecture micro-optimization cpu-cache

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

INC指令与ADD 1:重要吗?

来自Ira Baxter回答,为什么INC和DEC指令不会影响进位标志(CF)?

大多数情况下,我远离INCDEC现在,因为他们做的部分条件代码更新,这样就可以在管道中引起滑稽的摊位,和ADD/ SUB没有.因此,无关紧要(大多数地方),我使用ADD/ SUB避免失速.我使用INC/ DEC仅在保持代码较小的情况下,例如,适合高速缓存行,其中一个或两个指令的大小产生足够的差异.这可能是毫无意义的纳米[字面意思!] - 优化,但我在编码习惯上相当老派.

我想问一下为什么它会导致管道中的停顿,而添加不会?毕竟,无论是ADDINC更新标志寄存器.唯一的区别是INC不更新CF.但为什么重要呢?

performance x86 assembly increment micro-optimization

26
推荐指数
2
解决办法
4234
查看次数

为什么循环总是被编译成"do ... while"样式(尾部跳转)?

当试图理解汇编(启用编译器优化)时,我看到这种行为:

这样一个非常基本的循环

outside_loop;
while (condition) {
     statements;
}
Run Code Online (Sandbox Code Playgroud)

经常被编译成(伪代码)

    ; outside_loop
    jmp loop_condition    ; unconditional
loop_start:
    loop_statements
loop_condition:
    condition_check
    jmp_if_true loop_start
    ; outside_loop
Run Code Online (Sandbox Code Playgroud)

但是,如果未打开优化,则会编译为通常可理解的代码:

loop_condition:
    condition_check
    jmp_if_false loop_end
    loop_statements
    jmp loop_condition  ; unconditional
loop_end:
Run Code Online (Sandbox Code Playgroud)

根据我的理解,编译后的代码更像是这样的:

goto condition;
do {
    statements;
    condition:
}
while (condition_check);
Run Code Online (Sandbox Code Playgroud)

我看不到巨大的性能提升或代码可读性提升,为什么经常出现这种情况呢?是否有此循环样式的名称,例如"尾随条件检查"?

optimization performance assembly loops micro-optimization

26
推荐指数
1
解决办法
1675
查看次数