对于矩阵向量乘法,行优先排序是否更有效?

2023-12-21

If M是一个 n x m 矩阵并且v and u是向量,那么就索引而言,矩阵向量乘法看起来像u[i] = sum(M[i,j] v_j, 1 <= j <= m). Since v是一个向量,对于面向数值计算的语言,其元素可能存储在连续的内存位置中。如果M按行优先顺序存储(如 C、Mathematica 和 Pascal 中),然后是后续的M[i,j]总和也存储在连续的内存位置中j递增,使得迭代非常高效。如果它以列优先顺序存储(如 Fortran、Matlab、R 和 Julia),则递增j需要移动等于外部矩阵步长的内存位置数,在本例中等于n。对于具有许多行的矩阵来说,这似乎效率较低。 (对于矩阵-矩阵乘法,这个问题不会出现,因为在任何一种排序约定下,增加求和索引都需要在一个矩阵的内存或另一个矩阵的内存中移动一大步。)

与乘法和加法运算相比,在大多数计算机体系结构中,在内存中移动一个单位和移动多个单位之间的差异是明显还是可以忽略不计? (我猜“可以忽略不计”,因为实际上 Fortran 通常至少与 C 一样快,但谁能详细说明原因吗?)


在大多数计算机架构中,这种差异预计会很大,至少在原则上是这样。

矩阵向量乘法是一种受内存限制的计算,因为内存的重用率很低。 v 的所有 (N) 个分量都被重用来计算 u 的每个元素,但矩阵 (N^2) 的每个元素仅使用一次。如果我们考虑典型内存的延迟(例如,https://gist.github.com/hellerbarde/2843375 https://gist.github.com/hellerbarde/2843375)(小于)100ns 与执行浮点运算所需的时间(小于 1ns)相比,我们看到大部分时间都花在从数组加载和存储值上。

我们仍然可以实现缓存友好的,即尽可能具有数据局部性。由于内存是以行的形式加载到缓存中的,因此我们必须尽可能地使用已加载的缓存行。这就是为什么访问连续的内存区域可以减少从内存加载数据所花费的时间。

为了支持这一点,让我们尝试一个非常简单的代码:

program mv
integer, parameter :: n=10000
real, allocatable :: M(:,:), v(:), u(:)
real :: start, finish
integer :: i, j
allocate(M(n,n),v(n),u(n))
call random_number(M)
call random_number(v)
u(:)=0.
call cpu_time(start)
do i=1,n
do j=1,n
    ! non-contiguous order
    u(i)=u(i)+M(i,j)*v(j)
    ! contiguous order
    ! u(i)=u(i)+M(j,i)*v(j)
enddo
enddo
call cpu_time(finish)
print*,'elapsed time: ',finish-start
end program mv

一些结果:

               non-contiguous order   contiguous order
gfortran -O0            1.                 0.5
gfortran -O3           0.3                 0.1
ifort -O0              1.5                0.85
ifort -O3            0.037               0.035

正如您所看到的,差异是在没有优化的情况下编译的显着差异。启用优化 gfortran 仍然显示出显着差异,而使用 ifort 则只有很小的差异。查看编译器报告,编译器似乎交换了循环,从而导致内部循环的连续访问。

然而,我们是否可以说具有行优先排序的语言对于矩阵向量计算更有效?不,我不能这么说。不仅因为编译器可以补偿差异。代码本身并不知道 M 的行和列的所有信息:它基本上知道 M 有两个索引,其中一个(取决于语言)在内存中是连续的。对于矩阵向量,数据局部性的最佳方法是将“快速”索引映射到矩阵行索引。您可以使用“行优先”和“列优先”语言来实现此目的。您只需根据此存储 M 的值即可。举个例子,如果你有“代数”矩阵

     [ M11 M12 ]
M =  [         ]
     [ M21 M22 ]

您将其存储为“计算矩阵”

C       ==> M[1,1] = M11 ; M[1,2] = M12 ; M[2,1] = M21 ; M[2,2] = M22 
Fortran ==> M[1,1] = M11 ; M[2,1] = M12 ; M[1,2] = M21 ; M[2,2] = M22 

这样你就总是在“代数矩阵”行中连续。计算机对初始矩阵一无所知,但我们知道计算矩阵是代数矩阵的转置版本。在这两种情况下,我都会让内部循环迭代连续索引,最终结果将是相同的向量。

在复杂的代码中,如果我已经分配了矩阵并用值填充了矩阵,并且无法决定存储转置矩阵,则“行优先”语言可能会提供最佳性能。但是,交换循环(参见https://en.wikipedia.org/wiki/Loop_interchange https://en.wikipedia.org/wiki/Loop_interchange)由英特尔编译器自动完成,并由 BLAS 实现完成(请参阅http://www.netlib.org/lapack/explore-html/db/d58/sgemv_8f_source.html http://www.netlib.org/lapack/explore-html/db/d58/sgemv_8f_source.html),将差异减少到非常小的差异值。因此,使用 Fortran 您可以选择:

do j=1,n
    do i=1,n
        u(i)=u(i)+M(i,j)*v(j)
    enddo
enddo
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对于矩阵向量乘法,行优先排序是否更有效? 的相关文章

  • 多维数组(如 C/C++ 中的数组)是不规则数组的特殊情况吗? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我和一个哥们讨论了C 和C多维数组是否是不规则数组的特例 一种观点是 多维数组不是参差不齐的数组 因为多维数组的每个元素具有相同的大小 在参差不齐的数
  • Java俄罗斯方块旋转

    我知道这个问题已经被问了很多 但我想知道如何旋转俄罗斯方块 我已经做了一个又长又糟糕的解决方案 大约 170 行代码 但应该有更简单的方法来做到这一点 我的俄罗斯方块由 4 个块组成 它们都知道它们在矩阵中的位置 行和列 Matrix本身是
  • 哪种数据聚类算法适合检测时间序列事件中未知数量的聚类?

    这是我的场景 考虑在不同地点和时间发生的一组事件 例如 考虑有人在高空记录暴风雨期间城市中的雷击 就我的目的而言 闪电是瞬时的 只能击中某些位置 例如高层建筑 还可以想象每次雷击都有一个唯一的 ID 以便以后可以参考该雷击 这个城市大约有1
  • 使用 OpenGL 着色器进行数学计算 (C++)

    我有一个矩阵 例如 100x100 尺寸 我需要对每个元素进行计算 matrix i j tt 8 5例如 我有一个巨大的矩阵 我想使用 OpenGL 着色器来实现该算法 我想使用着色器 例如 uniform float val unifo
  • 将 mat3 转换为 mat4 的最简单方法

    我提取了 mat4 的左上角 3x3 旋转矩阵 glm mat4 model glm mat3 rot glm mat3 model 现在我想要单位矩阵 左上角是我的新 mat3 最简单的方法是什么 glm mat4 result resu
  • 使用 SqlBulkCopy 和 F# 在 SQL 中导出矩阵

    我想将大量数据从 F 传输到 SQL 表 基本上我的 F 代码创建了一个三列矩阵 UserID ProductID and price 和N行 我想将其 复制 粘贴 到数据库中 我尝试了多种选择 但最终 从 F 传输数据非常慢 10000
  • 线性代数如何在算法中使用?

    我的几个同行都提到 学习算法时 线性代数 非常重要 我研究了各种算法并学习了一些线性代数课程 但我没有看到其中的联系 那么线性代数如何应用在算法中呢 例如 图的连接矩阵可以带来哪些有趣的事情 三个具体例子 线性代数是现代 3D 图形的基础
  • 使用 R2010b 中的符号工具箱来求解和/或 linsolve

    我前几天问了一个问题here https stackoverflow com questions 20317038 matlab linear congruence solver that supports a non prime modu
  • Python中矩阵元素的双重求和

    基于下面的简化示例 我想在我的代码中 from sympy import import numpy as np init printing x y symbols x y mat Matrix x 1 1 y X 1 2 3 Y 10 20
  • 获取所有矩阵列逐元素乘积对的快速方法

    假设我有一个数字matrix set seed 1 mat lt matrix rnorm 1000 ncol 100 我想生成所有向量 它们是中所有唯一向量对的逐元素乘积的结果mat 我们如何改进下面的代码 all pairs lt t
  • 快速约会算法

    我在一家咨询公司工作 大部分时间都在客户所在地 正因为如此 我很少见到同事 为了更好地了解彼此 我们将安排一个晚宴 会有很多小桌子 方便人们聊天 为了在聚会期间与尽可能多的不同的人交谈 每个人都必须每隔一段时间 比如每小时 换一张桌子 如何
  • 组和平均 NumPy 矩阵

    假设我有一个任意的 numpy 矩阵 如下所示 arr 6 0 12 0 1 0 7 0 9 0 1 0 8 0 7 0 1 0 4 0 3 0 2 0 6 0 1 0 2 0 2 0 5 0 2 0 9 0 4 0 3 0 2 0 1 0
  • 负整数的基数排序

    我正在尝试对整数 包括负整数 实现基数排序 对于非负整数 我计划为数字0 9创建一个10个队列的队列 并实现LSD算法 但我对负整数有点困惑 我现在的想法是继续为它们创建另一个包含 10 个队列的队列 并分别对它们进行排序 然后在最后 我将
  • numpy python 中的“AttributeError:'matrix'对象没有属性'strftime'”错误

    我有一个维度为 72000 1 的矩阵 该矩阵涉及时间戳 我想使用 strftime 如下所示 strftime d m y 为了得到像这样的输出 11 03 02 我有这样一个矩阵 M np matrix timestamps 我使用了
  • 融化R中的下半矩阵

    如何融化下半三角形加对角矩阵 11 NA NA NA NA 12 22 NA NA NA 13 23 33 NA NA 14 24 34 44 NA 15 25 35 45 55 A lt t matrix c 11 NA NA NA NA
  • R、Rcpp 与 Armadillo 中矩阵 rowSums() 与 colSums() 的效率

    背景 来自 R 编程 我正在扩展到 C C 形式的编译代码Rcpp 作为循环交换 以及一般的 C C 效果的实践练习 我实现了 R 的等效项rowSums and colSums 矩阵的函数Rcpp 我知道它们以 Rcpp 糖的形式存在 并
  • 在 RcppArmadillo 中将列向量乘以数值标量

    我在编译这个简单的程序时遇到一些麻烦c 代码使用Rcpp和RcppArmadillo包裹 采用以下简单示例 将矩阵的每一列乘以数值标量 code lt arma mat out Rcpp as
  • 使用面向对象的分析和设计对电梯进行建模[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 当涉及到面向对象的设计和分析时 有一组问题似乎在面试和课堂上很常见 这是其中之一 不幸的是 我在大学的 OOP 教授从未真正给出过答案 所以我一
  • 使用简单矩阵乘法时出错

    我在一次简单的乘法运算中偶然发现了一个错误 这让我感到非常惊讶 我一直以为这里发生了什么 只为矩阵乘法 http www mathworks nl help matlab matlab prog operators html x 2 y z
  • 优雅降级 - 何时考虑

    在为使用 AJAX 的应用程序设计和构建 UI 时 您何时考虑优雅降级 对于禁用 JavaScript 或正在使用屏幕阅读器的用户 最后 网站的 AJAX 版本完全完成后 在每个发展阶段 I don t 还有别的事 这些日子 渐进增强 ht

随机推荐

  • 在 VSTS 中设置 GitFlow - 最佳实践?

    有没有关于如何使用 Visual Studio TeamServices 设置 GitFlow 的建议 我们来自 BitBucket 那里只是一个简单的初始化 但在VSTS中我们找不到任何脚手架 看来我们必须进行很多手动设置 对吗 那么如何
  • 捕获滚动​​溢出:隐藏元素

    假设您有一个隐藏了溢出的元素 是否可以在不滚动的情况下捕获该元素上的鼠标滚动 我问这个的原因是 我有一个单页设计的网站 我编写了一个脚本 当您向下或向上滚动时 该脚本会自动滚动到下一个位置 但有一些我不想要的东西 当他们尝试滚动时 页面实际
  • 共同的初始序列和比对

    在思考反例时这个问题 https stackoverflow com q 21499120 420683 我想出了 struct A alignas 2 char byte 但如果这是合法和标准布局 它的布局是否与此兼容struct B s
  • Linux 中 C++ 的低级磁盘操作

    linux中有哪些方法可以用C 进行低级磁盘操作 我正在尝试在磁盘上编写自己的数据管理器 例如 我想在Linux环境中创建一个C 程序 在磁盘上分配一定数量 连续 的数据 然后自由地允许我读 写该数据块 我认为我不想使用该标准fstream
  • 将独立的 aspx/asmx 页面添加到 DotNetNuke 中

    你好 我刚刚在我的服务器上安装了 dotnetnuke 5 06 比如说 路径是 mydomain com dnn 我有一个独立于 dotnetnuke 的库 我必须运行它 它包含 Web 服务和各种其他 httphandlers 所以我还
  • Excel Range 奇怪行为的 SpecialCells 方法

    我编写了一个宏 使用 Excel 范围对象的 SpecialCells 方法从某个范围中查找空白单元格 当我尝试执行以下代码时 出现 未找到单元格 的异常 Sub test Debug Print Sheet1 Range A1 D4 Sp
  • 无法找到组合@Published - Xcode11 Beta 5(11M382q)

    我正在尝试使用以下内容运行一个简单的项目 Published var currentPlacemark CLPlacemark nil XCode 11 Beta 5 11M382q iOS13 17A5556d 出现以下错误 dyld S
  • azure辅助角色中的异步/等待导致角色回收

    我正在我的 WorkerRole RoleEntryPoint 中使用任务 异步和等待 我有一些无法解释的回收 现在我发现 如果等待调用中的某些内容运行时间过长 则角色会回收 要重现它 只需在 Run 方法中执行 await Task De
  • Jquery UI 可调整大小 - 调整放置在 iframe 上的 div 的大小

    如果你查看这个 jsbin http jsbin com efosed 5 edit http jsbin com efosed 5 edit然后你按 Run with JS 就会出现一个可以用 jquery ui 调整大小的 div 一切
  • Azure Functions 部署时无法运行

    我是新来的 如果帖子不完整 抱歉 我正在尝试在 azure 上部署一个与 blob 交互的 python 脚本 该脚本在本地运行良好 我可以与我的存储帐户交互 上传和下载 blob 但是当我在 azure 上部署我的函数时 它不会运行 日志
  • bash 使用序列号批量重命名文件夹和子文件夹中的文件

    我需要一个 bash 脚本来执行以下操作 对于文件夹及其子文件夹中存在的特定类型的每个文件 它都会在前面添加一个序列号 4 位数字 后跟一个分隔符 例如我有 Queen 1986 A Kind of Magic 01 One vision
  • 流程图 - 动态更改 y 轴

    我是飞行新手 但很快就设置了我的时间图 这是我基于时间的情节 plot placeholder d xaxis mode time minTickSize 1 month min new Date 2008 05 20 getTime ma
  • 为什么我需要将“get”包装在 J“lapply”调用中的虚拟函数中?

    我希望通过类或常见模式匹配等标准来处理列grep 我的第一次尝试没有成功 require data table test table lt data table a 1 10 ab 1 10 b 101 110 this does not
  • 在 Netbeans 内运行时停止 Tomcat

    我使用 NetBeans 运行 Apache Tomcat 6 当我的代码出现故障 例如 NullPointerException 时 tomcat 会失败并且不会运行任何其他请求 我的问题是我无法让 tomcat 停止 我必须重新启动整个
  • 查找 Java 应用程序中的连接泄漏

    我有一个应用程序在一段时间后开始出现内部服务器错误 我询问的一些人告诉我 这可能是因为我的应用程序中的连接泄漏 我开始搜索并发现这个查询来模拟连接泄漏 select LAST CALL ET SQL TEXT username machin
  • 堆积条形图未正确更新 d3js

    In this https plnkr co edit X7JYRLCKgBnasP86FRgQ p preview堆积条形图我添加了一个平分线和一个自定义x invert函数 以便您可以读取每个月的值 问题是 当我添加此自定义函数时 团队
  • OpenXML SDK 2.0 与 Aspose 在 .NET 中生成服务器端 Word 2007 文档

    我将在 Net 中启动一个服务器端办公自动化项目 以下是计划的主要活动 创建一个word文档 使用现有的包含封面 页眉 页脚 目录的 Word 文档模板 保存存档 嵌入文件并调整大小 HTML 图像 Word Excel TOC 生成和格式
  • 我无法从数据库 PostgreSQL 生成 Hibernate 映射文件和 POJO?

    已经在数据库 PostgreSQL 中创建了表和关系 但是当我想生成 Hibernate 映射文件和 POJO 时 它们没有生成 我应用了所有适当的步骤hibernate cfg xml一代和hibernate reveng xml 我认为
  • 如何在没有数据库的情况下配置 Ruby on Rails?

    对于当前不需要数据库的小型网站项目来说 使用 Ruby on Rails 会很方便 我知道我可以在 MySQL 中创建一个空数据库并从那里开始 但是有人知道在没有数据库的情况下运行 Rails 的更好方法吗 Thanks For Rails
  • 对于矩阵向量乘法,行优先排序是否更有效?

    If M是一个 n x m 矩阵并且v and u是向量 那么就索引而言 矩阵向量乘法看起来像u i sum M i j v j 1 lt j lt m Since v是一个向量 对于面向数值计算的语言 其元素可能存储在连续的内存位置中 如