首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >行明智迭代Vs列明智迭代

行明智迭代Vs列明智迭代
EN

Stack Overflow用户
提问于 2019-06-10 19:39:29
回答 3查看 191关注 0票数 1

如果我按行或按列遍历2D矩阵,是否有任何性能差异。

例如:

代码语言:javascript
运行
复制
import random
import time

l = []

for i in range(1000000):
    temp = [random.random() for x in range(10)]
    l.append(temp)

start_time = time.time()

for i in range(1000000):
    for j in range(10):
        l[i][j] -= 0

end_time = time.time()
time_taken_row_wise = end_time - start_time

start_time = time.time()

for i in range(10):
    for j in range(1000000):
        l[j][i] -= 0

end_time = time.time()
time_taken_column_wise = end_time - start_time

print(f"ROW WISE: {time_taken_row_wise}")
print(f"COLUMN WISE: {time_taken_column_wise}")

在上面的代码中,为什么按列迭代所需的时间比按行迭代所用的时间要长?

我运行了两次,得到了以下结果:

第一次运行:

代码语言:javascript
运行
复制
ROW WISE: 3.497559070587158
COLUMN WISE: 4.971074819564819

第二次运行:

代码语言:javascript
运行
复制
ROW WISE: 3.638113021850586
COLUMN WISE: 4.855097055435181
EN

回答 3

Stack Overflow用户

发布于 2019-06-10 20:04:41

我得到的结果相距更远:

行数: 11.901052713394165

按列排列: 38.32502007484436

我怀疑这与行/列在内存中的布局以及缓存预取有关(“按行”按照缓存预取机制的预期工作,“按列”在内存页之间来回跳转)。

我将尝试使用perf来尝试更深入地了解……

编辑: OK,我认为这证实了这一点:

按行的

行数: 11.151209354400635

'python3 by_row.py‘的性能计数器统计信息: 1,130,850,390个缓存-未命中1,102,567,550 L1-dcache-加载-未命中66,438,701 LLC-加载-未命中

按列列出的

列: 39.6846444606781

'python3 by_column.py n.py‘的性能计数器统计信息: 2,842,000,454缓存-未命中1,544,974,094 L1-dcache-加载-未命中305,823,025 LLC-加载未命中

我们看到cache-misses (必须实际进入内存的内存读取数量)显著增加(比x2更多),这可以解释为什么按列需要更多时间。

L1-dcache和LLC可以为我们提供更多关于缓存成功服务的读取的信息(因此,不计入缓存未命中),但仍然可能导致差异,基于使用的缓存(越接近L1越好)

票数 1
EN

Stack Overflow用户

发布于 2019-06-10 20:10:23

对我来说,也是一样的。

代码语言:javascript
运行
复制
ROW WISE: 2.68672251701355
COLUMN WISE: 2.7386820316314697

你的意思是为什么它不完全一样?enthropy?

代码:

代码语言:javascript
运行
复制
import random
import time

l = []

for i in range(1000000):
    temp = [random.random() for x in range(10)]
    l.append(temp)

start_time = time.time()

for i in range(1000000):
    for j in range(10):
        l[i][j] -= 0

end_time = time.time()
time_taken_row_wise = end_time - start_time

start_time = time.time()

for i in range(10):
    for j in range(1000000):
        l[j][i] -= 0

end_time = time.time()
time_taken_column_wise = end_time - start_time

print("ROW WISE: %s" % time_taken_row_wise)
print("COLUMN WISE: %s" % time_taken_column_wise)
票数 0
EN

Stack Overflow用户

发布于 2020-10-05 12:51:23

正如Adam.Er8所说,性能差异是由于矩阵存储在内存中的方式造成的。根据语言标准的不同,矩阵既可以按行、按列存储,也可以不指定(取决于编译器实现)。

矩阵的

代码语言:javascript
运行
复制
11, 12, 13
21, 22, 23

行式存储将为[11, 12, 13, 21, 22, 23]

按列存储的存储应为[11, 21, 12, 22, 13, 23]

根据您访问索引的方式,您可以进行顺序访问或随机访问。顺序访问在连续的存储器位置中访问矩阵,而随机访问从一个位置跳到另一个位置。因此,当矩阵变得足够大时,随机访问具有高高速缓存未命中频率和高页面故障频率。

了解一种语言(和编译器)如何访问矩阵对软件性能至关重要。简单地改变访问索引的方式可能会有高达14倍的差异!(编译器: g++ o3,矩阵大小为500,有2个索引)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56525661

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档