当我对大小为2 ^ n的矩阵应用简单算法(矩阵乘法,LU分解等)时,我可以观察到缓存抖动的影响:基本上,在大小为2 ^ k的矩阵中存在时间峰值。但是对于2 ^ n的增长值,这种现象不再得到验证(例如size = 2 ^ 14x2 ^ 14 = 16384x16384)。
这是什么原因
编辑
在matlab中运行一些非常简单的实验,我得到以下信息:
>> n = 1024;
>> AA = rand(n);
>> tic; lu(AA); toc;
Elapsed time is 0.163291 seconds.
>> n = 1025;
>> AA = rand(n);
>> tic; lu(AA); toc;
Elapsed time is 0.040935 seconds.
再次转到2的下一个幂,已验证了高速缓存抖动,但不那么明显了:
>> n = 4096;
>> AA = rand(n);
>> tic; lu(AA); toc;
Elapsed time is 1.208170 seconds.
>> n = 4097;
>> AA = rand(n);
>> tic; lu(AA); toc;
Elapsed time is 1.120656 seconds.
在此笔记本电脑上,不再针对矩阵大小= 2 ^ 13x2 ^ 13验证高速缓存的抖动:
>> n = 8192;
>> AA = rand(n);
>> tic; lu(AA); toc
Elapsed time is 8.586088 seconds.
>> n = 8193;
>> AA = rand(n);
>> tic; lu(AA); toc;
Elapsed time is 8.676817 seconds.
(我知道这些是随机矩阵,并且时间差很小,但是我观察到这种趋势在许多实验中都可以看到)。 对于C实现来说也是一样。
答案 0 :(得分:1)
造成高速缓存未命中(3C)的三个原因:强制性(当尚未将数据加载到高速缓存行中时),冲突(当高速缓存将数据映射到已经占用的行而高速缓存中存在一些可用空间时) )和容量(所有缓存均已满时)。
在高速缓存中映射数据依赖于地址的两次分解的幂,并解释了为什么大小为2 ^ k的矩阵将其行映射到相同的高速缓存块,从而导致冲突未命中。当前的计算机试图通过高关联性缓存来克服此问题,但是仍然会发生。使用不具有两个矩阵大小的幂的方法是一种在所有高速缓存块中扩展矩阵并避免此问题的方法。
当矩阵大小增加时,我们将遇到容量不足的情况。如果矩阵不适合缓存,则无论矩阵大小是否为2的幂,都需要弹出行以读取新行。这就是原因,无论矩阵大小超过某个阈值,您都具有类似的减慢速度。
对于lu分解,您将需要处理一些n ^ 2矩阵。如果算法写得很好,则将单个存储区存储在缓存中可以提高性能。但是,如果您的矩阵为8kx8k,则每个矩阵为512MB,这远远超出了当前计算机的缓存大小。对于4k矩阵(128MB),情况也完全相同,基准测试中的细微差别并不明显。由于当前计算机中的优化在某种程度上是统计的,因此多次运行 same 程序目前导致运行时间差异至少10-20%。
对于1k矩阵,情况有所不同。它只需要8M的存储空间,这是最近的奔腾微体系结构中L3缓存的大小。大多数未命中将是由于冲突而不是容量造成的,并且会发生2 ^ k矩阵的缓存破坏效应。
最后一句话。仅使用rand()时不应执行基准测试。这样就不会播种兰特,您的数据将实际上是随机的。但是数值算法的执行时间某种程度上取决于数据值,这将破坏基准的准确性。之前使用rng(seed)始终具有相同的序列,并进行几次测试。