问题描述

​ 使用文件和内存模拟系统缓存,并利用矩阵乘法验证实际和理论情况。

算法思想

设计一个Matrix类,其中Matrix是存在磁盘中的一个字符串,类通过保存的矩阵属性来读取磁盘。考虑到调试方便,该程序中以文本格式进行存储,方便调试过程中直接读取磁盘中的内容。具体的存储方式是将所有整数格式化成一个13位数字的字符串后以空格分隔。如下图所示:

Matrix中有一个cache成员为读取到的数据缓存,通过startRow,startCol,endRow,endCol四个属性来确定其在矩阵中的位置。其映射逻辑为matrix[row][col]=file[row∗rowSize+col]matrix[row][col] = file[row * rowSize + col]matrix[row][col]=file[row∗rowSize+col]。而缓存的管理模型则是模仿CPU的内存缓存模型,采用写回法。当读取矩阵中rowcol列时,判断逻辑如下。

#mermaid-svg-XmLNeWa1bGbyCUbN {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XmLNeWa1bGbyCUbN .error-icon{fill:#552222;}#mermaid-svg-XmLNeWa1bGbyCUbN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XmLNeWa1bGbyCUbN .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-XmLNeWa1bGbyCUbN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XmLNeWa1bGbyCUbN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XmLNeWa1bGbyCUbN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XmLNeWa1bGbyCUbN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XmLNeWa1bGbyCUbN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XmLNeWa1bGbyCUbN .marker.cross{stroke:#333333;}#mermaid-svg-XmLNeWa1bGbyCUbN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XmLNeWa1bGbyCUbN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XmLNeWa1bGbyCUbN .cluster-label text{fill:#333;}#mermaid-svg-XmLNeWa1bGbyCUbN .cluster-label span{color:#333;}#mermaid-svg-XmLNeWa1bGbyCUbN .label text,#mermaid-svg-XmLNeWa1bGbyCUbN span{fill:#333;color:#333;}#mermaid-svg-XmLNeWa1bGbyCUbN .node rect,#mermaid-svg-XmLNeWa1bGbyCUbN .node circle,#mermaid-svg-XmLNeWa1bGbyCUbN .node ellipse,#mermaid-svg-XmLNeWa1bGbyCUbN .node polygon,#mermaid-svg-XmLNeWa1bGbyCUbN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XmLNeWa1bGbyCUbN .node .label{text-align:center;}#mermaid-svg-XmLNeWa1bGbyCUbN .node.clickable{cursor:pointer;}#mermaid-svg-XmLNeWa1bGbyCUbN .arrowheadPath{fill:#333333;}#mermaid-svg-XmLNeWa1bGbyCUbN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XmLNeWa1bGbyCUbN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XmLNeWa1bGbyCUbN .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-XmLNeWa1bGbyCUbN .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-XmLNeWa1bGbyCUbN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XmLNeWa1bGbyCUbN .cluster text{fill:#333;}#mermaid-svg-XmLNeWa1bGbyCUbN .cluster span{color:#333;}#mermaid-svg-XmLNeWa1bGbyCUbN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XmLNeWa1bGbyCUbN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

在缓存内
不再缓存内
没有脏数据
有脏数据
接受row,col变量
判断所需变量是否在缓存内
读取数据
判断缓存内是否有脏数据
从磁盘内读取到缓存
写入脏数据

​ 完成磁盘交互后,其余操作即为正常的矩阵操作

功能模块设计

矩阵类的成员变量,:

    //缓存数组int* cache; //矩阵的行数int rowSize;//矩阵列数int colSize;//缓存开始的行数int startRow;//缓存开始的列数int startCol;//缓存结束的行数int endRow;//缓存结束的列数int endCol;//缓存大小int cacheSize;//cache miss 次数long cacheMissCount;//cache 访问次数long cacheCount;//矩阵在磁盘中的位置string matrixFilePath;//缓存是否被写入过bool dirty;//是否整个矩阵都在内存当中bool allInCache;

​ 矩阵值获取和修改的函数

    void set(int row, int col, int value){if (row > rowSize || col > this->colSize)throw "row > rowSize || col > this->colSize";if (currentIndex(startRow, startCol) <= currentIndex(row, col) && currentIndex(row, col) <= currentIndex(endRow, endCol))cache[currentIndex(row, col) - currentIndex(startRow, startCol)] = value;else{cacheMissCount++;readCache(row, col);cache[0] = value;}dirty = true;}int get(int row, int col){if (row > rowSize || col > this->colSize)throw "row > rowSize || col > this->colSize";cacheCount++;if (currentIndex(startRow, startCol) <= currentIndex(row, col) && currentIndex(row, col) <= currentIndex(endRow, endCol))return cache[currentIndex(row, col) - currentIndex(startRow, startCol)];else{cacheMissCount++;readCache(row, col);return cache[0];}}

​ 磁盘操作函数

    void readCache(int row, int col){if (dirty){writeCache();dirty = false;}ifstream fin;fin.open(matrixFilePath);int startIndex = currentIndex(row, col);fin.seekg(startIndex * 13, ios::beg);for (int i = 0; i < cacheSize; i++)fin >> cache[i];startRow = row;startCol = col;endRow = cacheSize / rowSize + startRow;if ((cacheSize % rowSize - 1 + startCol) > colSize){endRow++;endCol = cacheSize % rowSize - 1 + startCol - colSize;}else{endCol = cacheSize % rowSize - 1 + startCol;}}void writeCache(){ofstream fout;fout.open(matrixFilePath, ios::out | ios::in);//防止整数过大而溢出fout.seekp(static_cast<__int64>(currentIndex(startRow, startCol)) * 13, ios::beg);for (int i = 0; i < cacheSize; i++){string buffer = Matrix::formateInt(cache[i]).append(" ");fout.write(buffer.c_str(), 13);}fout.close();}

​ 矩阵乘法函数

    Matrix multiple_ijk(Matrix &right){Matrix t(right.colSize, rowSize, cacheSize, "mulTempMatrix.txt", false);int i, j, k;for (i = 0; i < rowSize; i++){for (j = 0; j < right.colSize; j++){for (k = 0; k < right.colSize; k++){t.set(i, j, get(i, j) + get(i, k) * right(k, j));}}}return t;}Matrix multiple_ikj(Matrix &right){Matrix t(right.colSize, rowSize, cacheSize, "mulTempMatrix.txt", false);int i, j, k;for (i = 0; i < rowSize; i++){for (k = 0; k < right.colSize; k++){int temp = 0;for (j = 0; j < right.colSize; j++){t.set(i, j, get(i, j) + get(i, k) * right(k, j));}}}return t;}

测试结果与分析

测试用例

class MatrixTest
{public:void test1(){Matrix m(10, 10, 3, "m.txt");cout << m << endl;cout << "cache miss:" << m.getCacheMissCount() << endl;Matrix m1(10, 10, 3, "m1.txt", false);cout << m1 << endl;cout << "cache miss:" << m.getCacheMissCount() << endl;}void test2(){Matrix m(10, 10, 3);//system("pause");cout << m << endl;//system("pause");m.set(0, 0, 9999);cout << m << endl;//system("pause");m.set(5, 0, 9999);cout << m << endl;}void test3(int n, int cacheSize){cout << "cache size is " << cacheSize << endl;Matrix m1(n, n, cacheSize, "m1.txt", 1000);cout << "initial m1(size is " << n << ")finished" << endl;Matrix m2(n, n, cacheSize, "m2.txt", 1000);cout << "initial m2(size is " << n << ")finished" << endl;Matrix m3 = m1.multiple_ijk(m2);cout << "m1 ijk m2 finished" << endl;cout << "cache coutnt of m1: " << m1.getCacheCount() << ", cache miss count of m1:" << m1.getCacheMissCount() << endl;cout << "cache coutnt of m2: " << m2.getCacheCount() << ", cache miss count of m2:" << m2.getCacheMissCount() << endl;cout << "cache coutnt of m3: " << m3.getCacheCount() << ", cache miss count of m3:" << m3.getCacheMissCount() << endl;cout << endl;}void test4(int n, int cacheSize){cout << "cache size is " << cacheSize << endl;Matrix m1(n, n, cacheSize, "m1.txt", 1000);cout << "initial m1(size is " << n << ")finished" << endl;Matrix m2(n, n, cacheSize, "m2.txt", 1000);cout << "initial m2 finished" << endl;Matrix m3 = m1.multiple_ikj(m2);cout << "m1 ijk m2(size is " << n << ")finished" << endl;cout << "cache coutnt of m1: " << m1.getCacheCount() << ",    cache miss count of m1:" << m1.getCacheMissCount() << endl;cout << "cache coutnt of m2: " << m2.getCacheCount() << ", cache miss count of m2:" << m2.getCacheMissCount() << endl;cout << "cache coutnt of m3: " << m3.getCacheCount() << ", cache miss count of m3:" << m3.getCacheMissCount() << endl;cout << endl;}void runTest(){for (int i = 5; i < 35; i += 5){for (int j = 1; j < 5; j++){test3(i, i / j);test4(i, i / j);}}}
};

实验测试

实验分析

假设矩阵为C=A×BC=A\times BC=A×B,且cache大小小于矩阵的一行或一列,且A、B、C都是大小为n的方阵

对于ijk的情况:

​ 每次读取时发生一次磁盘访问,而若cache当中有脏数据,则有另一次的写入访问。对于矩阵C,因为其作为操作矩阵*(总是进行+=操作)*,所以只要是C矩阵发生了cache miss其实是进行了两次磁盘访问,而对于AB矩阵,发生cache miss 时只发生一次磁盘访问。

​ cache miss 发生次数如下
Ccachemiss=n2cachesizeAcachemiss=n3cachesizeBcachemiss=n3C_{cache\ miss} = \frac{n^2}{cache\ size}\\ A_{cache\ miss} = \frac{n^3}{cache\ size}\\ B_{cache\ miss} = n^3 Ccache miss​=cache sizen2​Acache miss​=cache sizen3​Bcache miss​=n3
​ 所消耗的总时间
ttotal=2TdiskaccesstimeCcachemiss+TdiskaccesstimeAcachemiss+TdiskaccesstimeBcachemiss=n3Tdiskaccesstimecachesize(1+1n+cachesize)t_{total}=2T_{disk\ access\ time}C_{cache\ miss}+T_{disk\ access\ time}A_{cache\ miss}+T_{disk\ access\ time}B_{cache\ miss}\\ =\frac{n^3T_{disk\ access\ time}}{cache\ size(1+\frac{1}{n}+cache\ size)} ttotal​=2Tdisk access time​Ccache miss​+Tdisk access time​Acache miss​+Tdisk access time​Bcache miss​=cache size(1+n1​+cache size)n3Tdisk access time​​
​ 而当顺序化为ijk的时候,B矩阵的cache hit 率有所提高
Ccachemiss=n3cachesizeAcachemiss=n2cachesizeBcachemiss=n3cachesizeC_{cache\ miss} = \frac{n^3}{cache\ size}\\ A_{cache\ miss} = \frac{n^2}{cache\ size}\\ B_{cache\ miss} = \frac{n^3}{cache\ size} Ccache miss​=cache sizen3​Acache miss​=cache sizen2​Bcache miss​=cache sizen3​
所消耗的总时间变为了
ttotal=2TdiskaccesstimeCcachemiss+TdiskaccesstimeAcachemiss+TdiskaccesstimeBcachemiss=n3Tdiskaccesstimecachesize(2+1n)t_{total}=2T_{disk\ access\ time}C_{cache\ miss}+T_{disk\ access\ time}A_{cache\ miss}+T_{disk\ access\ time}B_{cache\ miss}\\ =\frac{n^3T_{disk\ access\ time}}{cache\ size(2+\frac{1}{n})} ttotal​=2Tdisk access time​Ccache miss​+Tdisk access time​Acache miss​+Tdisk access time​Bcache miss​=cache size(2+n1​)n3Tdisk access time​​

【矩阵乘法】外部矩阵乘法相关推荐

  1. 【Android 应用开发】Paint 滤镜原理 之 颜色矩阵 ( 颜色模式 | 颜色通道 | 颜色矩阵 | 矩阵运算 | 矩阵乘法 | 矩阵加法 | 颜色矩阵深入解析 )

    文章目录 颜色模式 颜色通道 Android 中的颜色矩阵 矩阵乘法运算 滤镜中的矩阵乘法运算 矩阵加法运算 滤镜中的矩阵乘法运算 滤镜运算原理 ( 总结 ) 实际滤镜理论示例 颜色模式 颜色模式 : ...

  2. 疯子的算法总结(五) 矩阵乘法 (矩阵快速幂)

    学过线性代数的都知道矩阵的乘法,矩阵乘法条件第为一个矩阵的行数等与第二个矩阵的列数,乘法为第一个矩阵的第一行乘以第二个矩阵的第一列的对应元素的和作为结果矩阵的第一行第一列的元素.(详解参见线性代数) ...

  3. Vijos 1603 ----迷宫(矩阵乘法,矩阵快速幂)

    描述 在某个神秘的星球上有一个游乐园 游乐园里有一个奇怪的迷宫,迷宫内有n个点,每个点之间都可能会有一条有向边(可能会有自环) 现在游乐园主有个问题想请你帮忙: 问:从s点走到f点,恰好走过m条边(边 ...

  4. 矩阵问题入门(矩阵乘法and矩阵快速幂)acm寒假集训日记22/1/15

    今天凌晨3点才睡,没想到通过看小说抑制玩游戏,反而看小说的时间更长. u1s1:那小说太刺激了,晚上看很有感觉,风吹草动我就会猛地看过去(类似茄子说柜子动了,哈哈),真TM(语气词)练胆量!!!..Q ...

  5. lu分解法matlab_MIT 18.065—机器学习中的矩阵方法02 矩阵乘法与矩阵分解

    数据分析.信号处理和机器学习中的矩阵方法 第02讲 矩阵乘法与矩阵分解 新MIT 线性代数|机器学习(中英机翻字幕)18.065 by Gilbert Strang_哔哩哔哩 (゜-゜)つロ 干杯~- ...

  6. 离散数学16__矩阵的加法、乘法

    常见的矩阵有 4*4 一 矩阵的加法,就是一个矩阵的第几行第几列,与 另一个矩阵相同的第几行第几列,相加. 也就是说,矩阵相加是相同位置加一下.   得到一个新矩阵. 二 矩阵的乘法 这里以矩阵的平方 ...

  7. Java实现矩阵运算——矩阵乘法、矩阵转置、自动填充矩阵行

    在做大数据或人工智能开发的过程做难免会遇到矩阵运算,本文在这里给大家实现一个简单的矩阵运算,请看下代码: package test;/*** 矩阵运算* * @author Administrator ...

  8. strassen矩阵乘法 java_矩阵乘法Strassen算法

    矩阵乘法是种极其耗时的运算.以 为例,其中 和 都是 矩阵.根据矩阵乘法的定义, 中的每个元素需要按照如下方式计算 式(4.8)包含一个 次的循环,因此计算 的时间复杂度为 .而 共有 个元素,因此总 ...

  9. python三维矩阵乘法_tensorflow 二维矩阵乘以三维矩阵,高维矩阵相乘

    最近看论文时看到了一个让我费解的操作. 二维矩阵 * 三维矩阵 * 二维矩阵 得到了一个二维矩阵. 即: (n * c1) x (m * c1 * c2) x (n * c2) 得 n * m 实现主 ...

  10. 二维矩阵乘法、矩阵转置、 矩阵与向量乘法(java实现)

    二维矩阵乘法.矩阵转置. 矩阵与向量乘法(java实现) 相关代码如下: package algorithms; //矩阵库 public class Matrisx { /***向量点相乘 doub ...

最新文章

  1. arch更新失败的办法
  2. 深拷贝(deep clone)与浅拷贝(shallow clone)
  3. HDU 4031 Attack (线段树)
  4. [工具]更新音乐下载软件工具音乐下载网站
  5. linux下cmake-gui的安装
  6. CC版本添加 LUCI
  7. 如何选择行业,让选择大于努力
  8. 别让for循环毁了你的程序(二)
  9. 构造函数和复制函数java_用Java复制构造函数
  10. Android之仿ele地图定位效果
  11. error: Zip file too big (greater than 4294959102 bytes)
  12. Procez One 快速入门(4)
  13. (一)VirtualBox安装增强功能
  14. ucloud的弹性计算
  15. IT是什么意思?什么是IT行业?
  16. linux Permission 0644 for are too open 错误解决方案
  17. 论文解读 | 百度 ERNIE: Enhanced Representation through Knowledge Integration
  18. wireshark使用Lua解析带有固定头和长度
  19. 2021年全球自动浓缩咖啡机行业调研及趋势分析报告
  20. 分享99个PHP源码,总有一款适合您

热门文章

  1. ewiews面板回归模型操作_Eviews常用面板回归模型案例实战
  2. 电子科技大学 计算机学院 夏令营,2018年电子科技大学全校各学院保研夏令营通知信息大汇总...
  3. 《电路》邱关源 思维导图 第三章 电阻电路的一般分析
  4. 【端口扫描工具】nmap核心使用方法
  5. checkIP——烂代码又堆了一个ip活性检测工具
  6. MATLAB2020b下载和安装
  7. 在MacOSX的Vmare Fusion中添加虚拟软驱和制作虚拟软盘
  8. java编码用gbk还是utf-8_utf-8还是GBK、java的编码问题
  9. nand flash与烧录器
  10. 数据分析最常用的excel函数公式大全