由MOVDQU实现的复制循环显示的大的运行间差异

时间:2015-06-03 22:21:43

标签: x86 x86-64 memcpy memory-bandwidth micro-architecture

我正在寻找一个结果的解释,我在循环中看到每次迭代64次移动,从一些源内存位置移动到某个目标内存位置,使用x86 movdqu指令(movdqu指令支持从/移动16byte数据)到xmm寄存器到/从未对齐的存储器位置寄存器)。这是实现类似于memcpy()/ java.lang.System.arraycopy()

的函数的代码的一部分

我尝试使用以下两种不同的模式实现副本:

型式1

0x30013f74: prefetchnta BYTE PTR [rsi]
0x30013f77: prefetchnta BYTE PTR [rdi]
0x30013f7a: movdqu xmm3, XMMWORD PTR [rsi+0x30]
0x30013f7f: movdqu xmm2, XMMWORD PTR [rsi+0x20]
0x30013f84: movdqu XMMWORD PTR [rdi+0x30],xmm3
0x30013f89: movdqu XMMWORD PTR [rdi+0x20],xmm2
0x30013f8e: movdqu xmm1, XMMWORD PTR [rsi+0x10]
0x30013f93: movdqu xmm0, XMMWORD PTR [rsi]
0x30013f97: movdqu XMMWORD PTR [rdi+0x10], xmm1
0x30013f9c: movdqu XMMWORD PTR [rdi], xmm0

在此模式中,rsi保存源(src)地址,rdi保存目标(dst)地址,xmm寄存器用作临时寄存器。此代码的迭代次数与copylen_in_bytes / 64相同。如您所见,此处遵循ld-ld-st-st-ld-ld-st-st加载存储模式。

PATTERN2

0x30013f74: prefetchnta BYTE PTR [rsi]
0x30013f77: prefetchnta BYTE PTR [rdi]
0x30013f7a: movdqu xmm3, XMMWORD PTR [rsi+0x30]
0x30013f7f: movdqu XMMWORD PTR [rdi+0x30], xmm3
0x30013f84: movdqu xmm2, XMMWORD PTR [rsi+0x20]
0x30013f89: movdqu XMMWORD PTR [rdi+0x20], xmm2
0x30013f8e: movdqu xmm1, XMMWORD PTR [rsi+0x10]
0x30013f93: movdqu XMMWORD PTR [rdi+0x10], xmm1
0x30013f98: movdqu xmm0, XMMWORD PTR [rsi]
0x30013f9c: movdqu XMMWORD PTR [rdi], xmm0

在pattern2中,遵循ld-st-ld-st-ld-st-ld-st模式。

观察

运行此代码几百次,其中src和dst在不同的8字节边界对齐,我观察到以下内容:

On Westmere(Xeon X5690)

Pattern1表现出非常高的运行间差异。

Pattern2几乎没有变化。

Pattern2上的最小时间(最快观察时间)比Pattern1上的最小时间更高(约8%)。

在Ivybridge(Xean E5-2697 v2)

Pattern1表现出非常高的运行间差异。

Pattern2几乎没有变化。

Pattern2上的最小时间比Pattern1上的最小时间高(~20%)。

Haswell(Core i7-4770)

Pattern1不会表现出非常高的逐次运行差异。

Pattern2几乎没有变化。

Pattern2上的最小时间比Pattern1上的最小时间高(~20%)。

奇怪的是,在Westmere和Ivybridge上,src / dest的对齐与坏结果之间似乎没有相关性(导致高方差)。我看到相同的src / dest对齐的好坏数字。

问题

据我所知,跨越高速缓存行的movdqu将比非高速缓存行跨越的movdqu表现更差,但我不明白以下内容:

1)为什么Pattern1在Westmere和Ivybridge上表现出很高的差异?装货商的订单如何产生差异?

2)为什么在不同的架构上,Pattern2上的最小时间比Pattern1慢?

感谢您花时间阅读这篇长篇文章。

Karthik

0 个答案:

没有答案