性能比较:为什么复制整个numpy矩阵然后更改一列比只使用numpy.column\U堆栈更快?

2024-03-29 04:52:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图提高一些Python代码的性能。在该代码中,矩阵的一列(numpy数组)必须临时更改

给出的代码如下所示:

def get_Ai_copy(A, b, i):
    Ai = A.copy()
    Ai[:,i] = b[:,0]
    return Ai

现在,我认为不创建整个矩阵a的副本应该是一个很大的改进(在所使用的示例中,矩阵是500x500,所有条目都严格大于0),而只是使用np.column_stack()从我需要的列中创建一个新的临时矩阵,如下所示:

def get_Ai(A, b, i):
    return np.column_stack([A[:,:i], b, A[:,i+1:]])

我本以为这会大大提高性能,但事实证明,它实际上比给定的方法慢:

我以两种方式运行了100次,并比较了平均运行时间:

number_tests = 100

copy_times = np.empty(number_tests)
stacking_times = np.empty(number_tests)

for j in range(number_tests):
    t0 = time.time()
    for i in range(500):
        Ai = get_Ai_copy(A, b, i)
    t1 = time.time()
    copy_times[j] = t1 - t0
    # print(f'-- Run # {j}: CPU time for copying Ai = %g seconds'%(t1 - t0))

    t0 = time.time()
    for i in range(500):
        Ai = get_Ai(A, b, i)
    t1 = time.time()
    stacking_times[j] = t1 - t0
    # print(f'-- Run # {j}: CPU time for column stacking Ai = %g seconds'%(t1 - t0))
    # print()

print(f'Copying times average: {np.mean(copy_times)}')
print(f'Stacking times average: {np.mean(stacking_times)}')

结果是:

平均复印次数:0.19957998037338257

平均堆叠时间:0.22774386405944824

我不明白为什么会这样。

有什么解释我没看到吗?复制整个阵列是否比获取3个切片更方便缓存?如果是,有人知道原因吗

旁白: 我在一台Jupyter笔记本电脑上运行它,一台配备Intel i7 10750H(12mb缓存)和32GB Ram的笔记本电脑。 A始终是一个非奇异矩阵,如果这很重要的话


Tags: 代码numberforgettimenptests矩阵
1条回答
网友
1楼 · 发布于 2024-03-29 04:52:23

numpy数组的copy方法将触发代码,该代码将以最大CPU速度在所有数组数据上进行复制,使用本机代码-如果每个元素有500x500x8字节,我们所说的是约2MB的数据-即使在CPU的缓存中也非常适合。 numpy只需要为单个Python对象创建元数据

另一方面,column_stack运行一些Python代码(虽然不是在细粒度对象上运行,否则会更糟),并最终复制数组(它获取当前数组的片-不复制片,但在内部调用np.concatenate,从而触发复制)。因此,您只需增加部分复制数据的开销,以及在过程中创建10个Python级别的数组对象(在切片、连接等之间)所需的一些杂耍——这就弥补了您所获得的10%的额外时间

相关问题 更多 >