众所周知,以一种跨步方式访问内存最适合性能。
在
的情况下我应该更喜欢阅读一个步骤还是写一个步幅?
一个简单,具体的例子是类似BLAS的复制和置换操作,如y := P x
。置换矩阵P
完全由一些置换向量q(i)
定义。它具有相应的逆置换向量qinv(i)
。可以将所需的循环编码为y[qinv(i)] = x[i]
或y[i]=x[q(i)]
,其中前者从x
读取一个,后者写入y
一步。
理想情况下,人们总是可以编码两种可能性,在代表性条件下对其进行分析,并选择更快的版本。假设您只能编写一个版本 - 根据现代内存架构的行为,您总是期望哪种访问模式更快?在线程环境中工作是否会改变您的响应?
答案 0 :(得分:6)
您命名为“写一个跨步”(y[i]=x[q(i)]
)的访问模式通常更快。
如果内存被缓存且数据块小于缓存行,则此访问模式需要较少的内存带宽。
现代处理器通常拥有比存储单元更多的加载执行单元。下一个名为Haswell的英特尔架构仅支持GATHER指令,而SCATTER尚未纳入其计划。所有这些都支持“写一步”模式。
在线程环境中工作不会改变这种情况。
答案 1 :(得分:1)
我想分享我的简单基准测试的结果。假设我们有两个NxN
的{{1}}和A
的两个正方形B
矩阵,并且我们希望通过转置来执行复制:
double
算法:
A = transpose(B)
。不进行转置的副本用作基准。将mkl_domatcopy
的值设为N
,以减轻缓存的关联性影响。
具有GCC 8.3.0(2^K + 1
)和英特尔MKL 2019.0.1的英特尔酷睿i7-4770:
具有GCC 7.3.0(-O3 -m64 -march=native
)和英特尔MKL 2017.0.1的英特尔至强E5-2650 v3: