C中实现矩阵乘法的一种高效的方法

2016-02-19 09:52 5 1 收藏

今天图老师小编要跟大家分享C中实现矩阵乘法的一种高效的方法,精心挑选的过程简单易学,喜欢的朋友一起来学习吧!

【 tulaoshi.com - 编程语言 】

如何计算矩阵乘法,这个大家都知道。通常情况下,我们都是用以下代码实现的
代码如下:

for(i=0;in;++i)
    for(j=0;jn;++j){
        sum=0;
        for(k=0;kn;++k)
            sum+=A[i][k]*B[k][j];
        C[i][j]+=sum;
}

但是考虑了高速缓存的问题后,其实有一种更好的实现方式:
代码如下:

for(i=0;in;++i)
    for(k=0;kn;++k){
        r=A[i][k];
        for(j=0;jn;++j)
            C[i][j]+=r*B[k][j];
}


细看一番就会发现这两种实现语义是等价的,但是后者的实际运行效率却比前者高。

那为什么会如此呢?

那是因为CPU读数据时,并不是直接访问内存,而是先查看缓存中是否有数据,有的话直接从缓存读取。而从缓存读取数据比从内存读数据快很多。

当数据不在缓存中时,CPU会将包含数据在内的一个数据块读到缓存,如果程序具有良好空间局部性,那么第一次cache miss后,之后的几次数据访问就可以直接在缓存中完成。除了空间局部性(程序倾向于引用与当前数据邻近的数据)之外,还有时间局部性(程序倾向于引用最近被引用过的数据)。

回到矩阵乘法。(我们只考虑内循环)

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

前者对矩阵A,有良好的空间局部性,假设一次能缓存四个元素,则每次迭代对于A只有0.25次miss,但是对于B,则不然,因此B是按列访问的,每次访问都会miss,因此每次迭代总的miss数是1.25。

后者对于矩阵C和矩阵B都有良好的局部性,每次迭代都只有0.25词miss,因此总的miss数是0.5。后者每次迭代多了一次存储(对C[i][j]写入),但是即便如此,后者的运行效率也比前者高。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

总而言之,要想程序跑得快,就要在程序中多利用局部性,让缓存hold住你的数据,减少访存次数。要知道CPU可以在3个时钟周期内访问到L1 cache,10个时钟周期左右的时间访问到L2 cache。访问内存却要上百个时钟周期,孰快孰慢,很清楚了吧?

来源:http://www.tulaoshi.com/n/20160219/1592479.html

延伸阅读
在.Net 中 DataGrid 虽然有排序的功能,但并不支持双向的排序。用到了,看了些相关的帖子,自己尝试了一种方法,竟然也行得通,呵呵 主要是用DataGrid.Attributes 存了一个参数,同时在onSortCommand中修改了DataGridColumn的SortExpression. 代码如下: private void BindData() { DataTable dt = .......; if(dt != null) { DataView dv = d...
标签: 电脑入门
一块型号为P41BMD的845主板,能点亮,但有一些毛病。板子本身很脏,用洗衣粉洗了一下,烘干,结果点不亮了,诊断卡跑C0。 寻寻觅觅开始寻找原因。大约几十分钟之后,开机后居然跳过了C0,一路跑码亮了,之后一直正常了。 分析原因: 应该就是CPU座里面针脚有水分,造成针脚短路,水分干了之后就好了。也就是说,CPU座针脚短路是跑C0的原因...
在建设网站的过程中,经常要处理一些数据的导入及导出。在mysql数据库中,有两种方法来处理数据的导出(一般)。 1. 使用select * from table_name into outfile "file_name"; 2. 使用mysqldump实用程序 下面我们来举例说明: 假设我们的数据库中有一个库为samp_db,一个表为samp_table。现在要把samp_table的数据导出。则我们可以利用以...
标签: Web开发
C#实现文件拖放并打开文件 需要知道的ListBox的两个事件:当您在控件的边界内拖动对象时,便会发生 DragEnter 事件;该事件用于确 定当前拖动的对象是不是您要放到控件上的对象。 在将一个或多个文件拖到控件上时,需要处理此事件。 这使 得在将对象拖到控件上方时,能够根据所拖动的对象显示相应的图标。 将拖动的对象释放到控件上时,...
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click             Dim G As Graphics           G = PictureBox1.CreateGraphics() ...

经验教程

144

收藏

6
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部