首页/文章/ 详情

利用矩阵分块优化算法

7月前浏览4858

本文摘要(由AI生成):

文章探讨了存储系统对程序执行时间的影响,特别强调了CPU cache在提高处理器性能中的关键作用。由于CPU与内存性能差距,CPU内部引入多级cache以减少访存暂停时间。通过软件优化技术,如改善时间局部性,可减少cache失效次数,提升访问效率。文章以数组处理为例,分析了按行或按列存储的局限,提出分块算法优化时间局部性。文章还讨论了cache容量对性能的影响,提出基于子矩阵计算的代码改写方法,通过引入块参数和函数内联进一步优化性能。总之,文章强调了CPU cache的重要性,并详细阐述了分块算法如何通过挖掘程序局部性来减少cache失效,提高程序执行效率,对数值计算库性能优化具有重要意义。

存储系统对于程序执行时间有显著影响。处理器由于访存导致的暂停时间受到失效率和失效代价的影响。众所周知,为了弥补CPU与内存两者之间的性能差异,就在CPU内部引入了CPU cache,也称高速缓存。CPU cache通常分为大小不等的三级缓存,分别是L1 cache、L2 cache和L3 cache。如图1所示。

▲ 图1 三级cache

许多软件优化技术通过重用cache中的数据来大幅度提高处理器性能,通过改善程序的时间局部性来提升访问效率。换言之,不要频繁替换cache中的数据。

处理数组时,如果能将数组元素按照访问顺序存放在存储器中,则能够获得性能上的好处。但是,假设同时处理多个数组,一些数组按行访问,一些数组按列访问。按行存储(称为行优先)或者按列存储(称为列优先)数组都不能解决问题,这是因为在程序的每个循环体中行访问和列访问同时会被使用到。因而,分块算法针对子矩阵(submatrice)或者数据块来进行操作,并不针对数组中完整的一行或一列进行操作。它的目标是,在替换之前对已在cache中的数据进行尽可能多的访问,这就是说,提高程序的时间局部性以减少cache失效。例如,在数值计算库Lapack的DGEMM中的内层循环中

for (int j = 0; j < n; ++j) {
    double cij = C[i+j*n]; /* cij = C[i][j] */
    forint k = 0; k < n; k++ ) {
        cij += A[i+k*n] * B[k+j*n]; /* cij += A[i][k]*B[k][j] */
        C[i+j*n] = cij; /* C[i][j] = cij */
    }
}

首先读入数组B的所有    个元素,重复地读入数组A中某一行中的    个元素,最后将结果写入C数组某一行中对应的    个元素。图2给出了对这三个数组的访问快照,深色阴影部分表示最近被访问过,浅色阴影部分表示较早被访问过,白色表示还未被访问。

▲ 图2 三个数组 C、A和 B 的快照(N=6,i=1)。采用不同的阴影对各个数组元素的访问时机进行表示:白色表示尚未被访问过,浅色阴影表示较早被访问过,深色阴影表示最近被访问过。与图4 相比,数组 A和B的素被重复读入以计算数组 C的新元素。变量 i、j和 k 用来进行数组访问,对应行或者列的变化

容量失效的次数明显与    和cache的容量有关。如果cache中可以存入三个    的矩阵,假设没有其他冲突,那么一切完美。例如将矩阵大小设为32x32,那么情况正好如此。每个矩阵有32x32=1024个元素,每个元素的大小为8字节,三个矩阵的大小就为24KiB,这可以很容易存入的容量为32KiB的cache中。如果cache能够存入一个    的矩阵和一行    个元素,至少数组A中的第    行数据和数组B可以一直保留在cache中。如果cache容量小了,则数组B和数组C都可能发生失效。最坏情况下,    个操作需要访问    个存储字。

为保证需要访问的数组元素都尽可能在cache中,原始代码需要改写为基于子矩阵的计算方式。这样,我们需要调用图3中的DGEMM版本,该版本就是在大小为的矩阵上重复计算。    也被称为块参数。该函数增加了3个新参数 si、sj和sk用来描述数组A、B和C的子矩阵的起始点。函数doblock的两个内部循环以    为步长进行计算,并不是按照数组B和C的全长进行计算。gcc编译器通过函数内联(function inlining)消除了函数调用的所有开销。也就是说在程序中直接插入函数代码,以避免通常的参数传递和现场保存操作。

▲ 图3  DGEMM的cache分块版本。假设数组C初始化为0。函数doblock 以普通的DGEMM为基础,增加了新参数来描述BLOCKSIZE大小的子矩阵的起始位置。

图4给出使用分块思想对三个数组进行访问的示例。仅对于容量失效来说,需要访问的内存数据字总数为    。(相比未分块前)这个数据得到了改善,原因在于参数    。由此可见,分块思想挖掘出程序的时间局部性和空间局部性,比如数组A的访问得益于空间局部性,而数组B的访问得益于时间局部性。

▲ 图4  数组C、A和B的访问(BLOCKSIZE =3)。注意,与图2 相比,访问的元素数量变少

图5中给出了采用cache分块对未优化DGEMM性能的影响。矩阵规模最大时,未优化程序的性能折半。采用cache分块的版本,即使矩阵规模达到960x960=3232阵规模性能也仅仅降低了不到10%。

▲ 图5  未优化DGEMM与 cache 分块 DGEMM的性能比较,矩阵维度从32x32增加至960x960



来源:数值分析与有限元编程
科普
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2024-04-03
最近编辑:7月前
太白金星
本科 慢慢来
获赞 5粉丝 15文章 326课程 0
点赞
收藏
作者推荐

力学概念|订书钉的受力分析

力学概念|订书钉的受力分析▲ 图1 订书机底部凹槽订书机是一种常见的工具。如图1所示,在订书机底座前端有弧形的凹槽。图2所示为订书钉在订书机作用下的变形过程。最初订书钉看起来像是一个刚架,当压下订书钉时,相当于在横梁施加均布荷载,这些荷载推着钉子穿过一叠纸张,直至进入订书机的金属底座。当订书钉进人底座凹槽时,订书钉的末端同时受到竖向和水平力的作用(图 2a所示,具体分析见后面图3)。由弧形槽产生的水平力使订书钉的脚受弯向内运动(图2b)。当订书钉两个脚变形到一定程度时时,订书钉的端部脱离凹槽不受水平力的作用。在这种情况下,竖向力产生的附加弯矩足以使订书钉的竖向构件继续弯曲(图2c)。最终,订书钉到达图2d所示的形状。订书钉产生的大变形是塑性的、不可恢复的。▲ 图2 订书钉变形过程如图3所示,当订书钉刚接触到底座凹槽时,其一个脚的竖向力 分解为沿着凹槽法向分力 和径向分力 .同样,这两个力沿着水平方向的合力就是 ▲ 图3 订书钉刚接触到底座凹槽时受力分析来源:数值分析与有限元编程

未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习 福利任务 兑换礼品
下载APP
联系我们
帮助与反馈