Python矩阵乘法中map比普通for循环运行慢的原因是什么
两种实现耗时差异的核心原因
- 访存模式差异
第一种实现提前对B做了一次转置,后续所有操作都是读取两个矩阵的行数据。绝大多数矩阵实现都是行优先存储,读取行是连续内存访问,缓存命中率极高;而第二种实现每次循环都调用B.column(c+1)读取列数据,行优先存储下取列需要跨地址跳转访问,缓存命中率极低,还需要额外的逻辑拼接列元素,这是最大的性能差距来源。 - 函数调用与额外开销差异
第二种实现内层使用map+lambda实现元素相乘,lambda属于Python级别的函数调用,每次调用都有额外的栈开销,远低于第一种实现中直接在循环内计算乘积的执行效率;同时sum(list(map(...)))多了一步将map对象转为列表的操作,相当于对乘积序列多遍历了一次,还额外产生了临时列表的内存分配和回收开销。 - 重复对象创建开销
第二种实现每次循环都调用A.row(r+1)和B.column(c+1),如果这两个方法每次调用都会生成新的列表对象存储行/列数据,那么整个计算过程会产生大量临时对象,增加了内存分配和垃圾回收的负担;第一种实现直接操作已经存在的A的行和转置后B的行,全程没有额外的临时行/列对象创建。 - 补充说明:列表推导本身确实比显式append的for循环执行效率更高,但这个优势是建立在两者逻辑完全等价的前提下,第二种实现的内层逻辑开销远大于第一种,列表推导的那点性能优势完全抵消不了额外引入的开销,所以最终表现更慢。
内容的提问来源于stack exchange,提问作者pytherhub
相关产品推荐
相关产品推荐

