【记录一个问题】prefetch 指令在golang中未见到明显效果
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!
偶尔了解到 DPDK 的代码中,使用 prefetch 指令可能让包处理速度加快 10% ~ 15%.
尝试在 golang 中引入 prefetch 指令,但是未简单明显的加速效果。
先说结论:
1 如果数据在一大块数据中,访问位置 N 之前,先 prefetch N+1 (以 cache line 为单位, 64字节)。这种情况下无明显提升,因为顺序的情况下,可能 CPU 内部已经是 prefetch 了。
2 如果在一个很长的链表中,访问节点 N 之前,先 prefetch N.Next。这种情况也无明显提升,因为把 prefetch 指令包装成函数后,可能函数调用的开销比 prefetch 带来的优化还要多。
3 CPU L1 cache 为 32kb, L2 cache 为 4MB, L3 cache 为 16MB。能不能把小于某一级cache 的 N 字节数据,通过 prefetch 指令全部加载到cpu cache 中? 实测发现完全没有优化效果。
猜测可能要极大计算量的场景,才能发现 prefetch 带来的微弱加速。
下面是 golang plan9 汇编实现的 prefetch 函数:
// func PrefetchL1(p uintptr)
// 把指针指向的 64 字节进行 prefetch
TEXT ·PrefetchL1(SB), NOSPLIT | RODATA | NOFRAME , $0-8
// 栈帧长度 0
// 参数 8 字节
// 返回值 0 字节
//
MOVQ ptr+0(FP), R11
PREFETCHT0 (R11) // 这里可以使用 PREFETCHT1, PREFETCHT2
RET
// func PrefetchT1(p uintptr, l uint64)
// 对指针 p,把 l 长度的内容连续调用 prefetch
TEXT ·PrefetchT1(SB), NOSPLIT | RODATA | NOFRAME , $0-16
// 栈帧长度 0
// 参数 16 字节
// 返回值 0 字节
//
MOVQ ptr+0(FP), R11
MOVQ len+8(FP), R12
ANDQ $0xFFFFFFFFFFFFFFC0, R12 // 按照 64 对齐
//
MOVQ R11, R13
ADDQ R12, R13 // r13 = end
start:
CMPQ R13, R11 // if ptr==end
JE done
// 循环体
PREFETCHT0 (R11)
ADDQ $64, R11
// 循环体结束
JMP start
done:
RET

浙公网安备 33010602011771号