亲爱的地球人问候!
这是概述:
我正在进行稀疏矩阵乘法,其中我有两个密集矩阵,但我只对输出的某些元素感兴趣。我有两个矩阵和一个2d索引数组:
float * A:[M*K]
float * B:[N*K]
int [][] idx: [M][nSelection] (that is there are nselection rows in B, per row in matrix A that I want to multiply)
我想计算:
out=A*B' // but of course only for the indices i,j where idx[i][k]=j for some k.
这是问题的重点: 我希望将这些东西保存在cpu缓存中,而我乘以一次乘以16个浮点数:
for (int kk = 0; kk < K; kk+=KK){
int begin = 0;
int end = M;
for (int i = begin; i < end; i++){
for (int j = 0; j < numberToAccept; j++){
int theid = idx[i * numberToAccept + j];
tempOut[i*numberToAccept+j] += blas_function_for_dotProduct(KK, A+i*K + kk, 1, B+theid*K + kk, 1);
}
}
}
我正在使用的数字是:
M = 2048; N=10240; K=4096; nSelection=100;
所以我的想法是,如果我按小部分解析矩阵(在16个浮点数= 1个高速缓存行的KK方向上),我将只能加载两个矩阵。也就是说,矩阵A是按顺序加载的,因此除了每行的第一次加载之外,所有其他加载都应该是命中。矩阵B以随机顺序加载,但因为我以64字节(16个浮点数)的块处理整个事件,所以它应该需要640KB。我有6 MB的L1,所以如果CPU使用LRU,它应该留在那里。
我使用valgrind来查看缓存未命中,这就是我得到的:
==3264== D refs: 2,383,524,642 (2,272,927,073 rd + 110,597,569 wr)
==3264== D1 misses: 114,096,428 ( 113,982,278 rd + 114,150 wr)
==3264== LLd misses: 95,822,173 ( 95,736,938 rd + 85,235 wr)
==3264== D1 miss rate: 4.7% ( 5.0% + 0.1% )
==3264== LLd miss rate: 4.0% ( 4.2% + 0.0% )
如果访问是可预测的(向上计数),我也会得到相同的结果。
我得到的结果与N = 512相同。但是在N = 256时,我突然得到缓存命中(随机访问):
==16546== D refs: 2,383,525,914 (2,272,928,002 rd + 110,597,912 wr)
==16546== D1 misses: 114,096,557 ( 113,982,392 rd + 114,165 wr)
==16546== LLd misses: 1,372,862 ( 1,287,624 rd + 85,238 wr)
==16546== D1 miss rate: 4.7% ( 5.0% + 0.1% )
==16546== LLd miss rate: 0.0% ( 0.0% + 0.0% )
问题是我的移动核心i7上有6MB缓存。并且512 * 16 *浮点大小为23 KB。那么为什么我会得到这么多的失误呢? (我昨晚写了大部分内容,今天我找到了答案。
答案 0 :(得分:1)
它是缓存的关联性。我的l3是12路关联的,我还没有完成计算,但是将K改为4 * 1024 + 16让我一路打击!