行明智迭代与列明智迭代

时间:2019-06-10 11:39:28

标签: python python-3.x

如果我逐行或逐列地遍历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

3 个答案:

答案 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个索引)