如果我逐行或逐列地遍历2D矩阵,性能会有什么区别。
例如
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}")
在上面的代码中,为什么列级迭代所花的时间大于行级迭代所花的时间?
我运行了两次,结果如下:
首次运行:
ROW WISE: 3.497559070587158
COLUMN WISE: 4.971074819564819
第二次运行:
ROW WISE: 3.638113021850586
COLUMN WISE: 4.855097055435181
答案 0 :(得分:0)
我得到的结果相距甚远:
明智的选择:11.901052713394165
怀斯(WISE):38.32502007484436
我怀疑这与行/列在内存中的布局以及缓存预取(“按行”按缓存预取机制期望的方式工作,“按列”回跳)有关。在内存页面之间来回切换。
我将尝试使用perf
来尝试更深入的了解...
编辑:好,我认为这可以确认:
按行
明智的选择:11.151209354400635
Performance counter stats for 'python3 by_row.py': 1,130,850,390 cache-misses 1,102,567,550 L1-dcache-load-misses 66,438,701 LLC-load-misses
按列
怀斯(WISE):39.6846444606781
Performance counter stats for 'python3 by_column.py': 2,842,000,454 cache-misses 1,544,974,094 L1-dcache-load-misses 305,823,025 LLC-load-misses
我们看到cache-misses
(实际上必须读到RAM的内存读取数量)显着增加(超过了2倍),这可以解释为什么分列需要更多时间。
L1-dcache和LLC可以为我们提供有关缓存成功完成的读取的更多信息(因此,不要算作缓存未命中),但仍可能会因使用了哪个缓存而导致差异(更接近L1越好)
答案 1 :(得分:0)
对我来说,差不多。
$path = $request->file('avatar')->store('avatars');
您是说为什么它不完全一样? ...是人类?
代码:
ROW WISE: 2.68672251701355
COLUMN WISE: 2.7386820316314697
答案 2 :(得分:0)
正如Adam.Er8所说,性能差异是由于矩阵在内存中的存储方式所致。根据语言标准,矩阵可以按行,按列或未指定的形式存储(取决于编译器的实现)。
对于矩阵
11, 12, 13
21, 22, 23
行存储将为[11, 12, 13, 21, 22, 23]
按列存储应为[11, 21, 12, 22, 13, 23]
根据访问索引的方式,可以有顺序访问或随机访问。顺序访问访问连续存储位置中的矩阵,而随机访问从一个位置跳转到另一个位置。因此,当矩阵足够大时,随机访问具有较高的高速缓存未命中频率和较高的页面错误频率。
了解语言(和编译器)如何访问矩阵对于软件性能至关重要。仅仅改变索引的访问方式就可以相差14倍! (编译器:g ++ o3,矩阵大小为500,带有2个索引)