gpt4 book ai didi

java - 奇怪的分支性能

转载 作者:IT老高 更新时间:2023-10-28 20:54:32 25 4
gpt4 key购买 nike

results我的benchmark表明当分支的概率为 15%(或 85%)而不是 50% 时,性能最差。

有什么解释吗?

img

代码太长,但相关部分在这里:

private int diff(char c) {
return TABLE[(145538857 * c) >>> 27] - c;
}

@Benchmark int timeBranching(int reps) {
int result = 0;
while (reps-->0) {
for (final char c : queries) {
if (diff(c) == 0) {
++result;
}
}
}
return result;
}

它计算BREAKING_WHITESPACE的数量给定字符串中的字符。结果显示,当分支概率达到约 0.20 时,时间突然下降(性能提高)。

更多 details关于下降。 Varying the seed显示更多奇怪的事情正在发生。请注意,表示最小值和最大值的黑线非常短,除非靠近悬崖。

cliff

最佳答案

它看起来像一个小的 JIT 错误。对于较小的分支概率,它会生成如下内容,只是由于展开而复杂得多(我正在简化很多):

movzwl 0x16(%r8,%r10,2),%r9d

获取字符:int r9d = queries[r10]

imul   $0x8acbf29,%r9d,%ebx

乘:ebx = 145538857 * r9d

shr    $0x1b,%ebx

类次:ebx >>>= 27

cmp    %edx,%ebx
jae somewhere

检查范围:if (ebx > edx || ebx < 0) goto somewhere (然后扔一个 IndexOutOfBoundsException

cmp    %r9d,%ebx
jne back

如果不相等则跳回循环开始:if (r9d != ebx) goto back

inc    %eax

增加结果:eax++

jne    back

只需 goto back

我们可以看到一件聪明的事情和一件愚蠢的事情:

  • 使用单个 unsigned comparison 即可以最佳方式完成边界检查。 .
  • 这是完全多余的,因为 x >>> 27 总是正数并且小于表长度 (32)。

对于20%以上的分支概率,这三个指令

cmp    %r9d,%ebx
jne back
inc %eax

换成类似的东西

mov    %eax,%ecx   // ecx = result
inc %ecx // ecx++
cmp %r9d,%ebx // if (r9b == index)
cmoveq %ecx,%ebx // result = ecx

使用 conditional move操作说明。这多了一条指令,但没有分支,因此没有分支预测错误的惩罚。

这解释了 20-80% 范围内的非常恒定的时间。低于 20% 的斜坡显然是由于分支预测错误造成的。

因此,使用大约 0.04 而不是 0.18 的适当阈值看起来像是 JIT 失败。

thr

关于java - 奇怪的分支性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19689214/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com