gpt4 book ai didi

c++ - 缓存刷新例程之间的时间不一致

转载 作者:太空宇宙 更新时间:2023-11-04 02:57:34 26 4
gpt4 key购买 nike

我需要运行 DAXPY 的计时线性代数内核。天真地,我想尝试这样的事情:

fill(X,operand_size);
fill(Y,operand_size);
double seconds = timer();
daxpy(alpha,X,Y,operand_size);
seconds = timer() - seconds;

如果需要,完整的代码链接在最后。

问题是,填充操作数 x 和 y 的内存访问将导致它们被放置在处理器缓存中。因此,随后在 DAXPY 调用中访问内存比在生产运行中实际访问要快得多。

我比较了两种解决这个问题的方法。第一种方法是通过 clflush 刷新各级缓存中的操作数。操作说明。第二种方法是读取一个非常大的数组,直到操作数条目“自然地”从缓存中逐出。我测试了两者,这是使用大小为 2048 的操作数的单个 DAXPY 调用的运行时:

Without flush: time=2840 ns
With clflush: time=4090 ns
With copy flush: time=5919 ns

这是几秒钟后的另一次运行:

Without flush: time=2717 ns
With clflush: time=4121 ns
With copy flush: time=4796 ns

正如预期的那样,刷新会增加运行时间。但是,我不明白复制刷新如何导致 DAXPY 例程的运行时间大大延长。 clflush 指令应该从所有缓存中逐出操作数,因此 clflush 的时间应该是任何其他缓存刷新过程的执行时间的上限。不仅如此,刷新时间(对于两种方法)也有很大的反弹(数百纳秒与未刷新情况下的不到 10 纳秒)。有谁知道为什么手动刷新在运行时会有如此大的差异?

附录

包含所有计时例程和刷新例程的完整代码位于此处(194 行):

http://codepad.org/hNJpQxTv

这是我的 gcc 版本。代码是使用 -O3 选项编译的。 (我知道,它很旧;我必须构建的一些软件与较新的 gcc 不兼容)

使用内置规范。

Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5646.1~2/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5646) (dot 1)

我在 Mac OS X 10.6 上使用 Intel Xeon 5650 处理器。

最佳答案

CPU 实际为正常读取所做的(部分)伪代码(在您的基准测试中会经常发生)可能是:

if( cache line is not in cache ) {
if(cache is full) {
find cache line to evict
if( cache line to evict is in "modified" state ) {
write cache line to evict to slower RAM
}
set cache line to "free"
}
fetch the cache line from slower RAM
}
temp = extract whatever we're reading from the cache line

如果您使用 CLFLUSH 刷新缓存,则 if(cache is full) 将为 false,因为 CLFUSH 将缓存留空。

如果您使用复制来刷新缓存,那么 if(cache is full) 分支将为真,并且 if( cache line is modified ) 也将为一半时间为真(一半缓存将包含您在复制期间读取的数据,另一半将包含您在复制期间写入的数据)。这意味着有一半的时间您最终会执行写入缓存行以逐出较慢的 RAM

执行写入缓存行以逐出到 RAM 将消耗 RAM 芯片带宽并影响从较慢的 RAM 中获取缓存行 的性能。

关于c++ - 缓存刷新例程之间的时间不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15712491/

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