ijk矩阵乘法性能分析
文章目录
1. Problem description
- 利用文件模拟cache缓存机制读写数据,将二维数组存储到文件中,并模拟对矩阵进行读写操作。操作要求为读取矩阵A、B,并输出A、B的乘积C。
- 改变cache大小
- 改变读取数据的顺序,即ijk、ikj
- 分析cache miss的次数与cache大小、读取数据顺序之间的关系
2. Algorithom idea
为了简化思路,我们可以先想想若二维数组在内存中是如何计算的,显而易见,当计算C=A*B
以ikj
的顺序进行的时候,有:
for(int i=0;i<n;i++)
for(int k=0;k<n;k++)
for(int j=0;j<n;j++){
c[i][j] += a[i][k] * b[k][j];
}
我们可以在此基础上进行代理函数设计,将计算函数变为如下形式:
for(int i=0;i<n;i++)
for(int k=0;k<n;k++)
for(int j=0;j<n;j++){
C.set(i,j,B.get(k,j)*A.get(i,k)+ C.get(i,j));
}
因此我们要做的就是进行set、get函数的设计。
2.1 get函数设计思路
为了简化文件查找操作,我们在文件中没有必要以二维的形式存储数据,可以通过数学的方法将二维数组转换成一维数组,即:targetIndex = row * rowSize + col 。
我们只需要用两个变量记录目前 Cache 存储的下表范围( startIndex , endIndex )即可判断访存Cache访问是否命中——如果不在该范围内,直接去文件中读取 (targetIndex, targetIndex+cacheSize)对cache进行更新即可。
2.2 set函数设计思路
同get函数的实现思路类似,将二维下标变为一维记录。但是需要考虑脏位——当targetIndex不在cache中时,不能直接覆盖cache,而需要将在cache中已经被更改过的数据写回更新进外存,即文件中。
此处由于每次更新都是以一整个cache为单位,因此我们只为外存设置一个脏位,而不是为每个Unit设置。当dirty==true时,表明之前有一次 set 调用命中,对与外存映射的cache中数据进行修改。
3 Function model design
3.1 Matrix类实现
//缓存数组
int[] cache;
//矩阵的行数
int rowSize;
//矩阵列数
int colSize