python - 为什么对 numpy 数组的就地修改性能与被修改的维度顺序有关?

标签 python numpy numpy-ndarray numpy-slicing

import numpy as np
a = np.random.random((500, 500, 500))
b = np.random.random((500, 500))

%timeit a[250, :, :] = b
%timeit a[:, 250, :] = b
%timeit a[:, :, 250] = b

107 µs ± 2.76 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
52 µs ± 88.1 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
1.59 ms ± 4.45 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
观察:
  • 上述三个运行的性能不同:修改第 1 和第 3 维(切片第 2 维)是三者中最快的,而修改第 1 和第 2 维(切片第 3 维)是最慢的。
  • 速度 w.r.t. 似乎没有单调性。被切片的维度。

  • 问题是:
  • numpy 背后的什么机制引起了我的观察?
  • 考虑到第一个问题的答案,如何通过正确排列尺寸来加速我的代码,因为一些尺寸被批量修改而其余的只是被切片?
  • 最佳答案

    正如几条评论所指出的,这完全是关于 locality of reference .想一想 numpy 在低级必须做什么,以及在第 3 种情况下连续左值在内存中彼此相距多远。
    另请注意,当数组不是 C 连续而是 F 连续时,计时结果如何变化:

    a = np.asfortranarray(a)
    b = np.asfortranarray(b)
    
    %timeit a[250, :, :] = b
    %timeit a[:, 250, :] = b
    %timeit a[:, :, 250] = b
    
    892 µs ± 22 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    169 µs ± 66.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    158 µs ± 24.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    (非常小的旁注:出于同样的原因,有时在对组进行 DataFrame 和一系列重复操作之前对 groupby 进行排序是有利的,这有点违反直觉,因为排序本身需要 O(nlogn) )。

    关于python - 为什么对 numpy 数组的就地修改性能与被修改的维度顺序有关?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65454168/

    相关文章:

    python - 使用日期作为索引合并 Pandas 数据框

    python - 我如何通过单行或命令行选项获得我的 Python 解释器的详细版本?

    python-3.x - 连接两个数组作为坐标对

    python - 将对称矩阵(二维数组)的上/下三角部分转换为一维数组并将其返回为二维格式

    python - 使用相同掩码的 bool 掩码 ndarray 的内部尺寸

    python - numpy - 制作重复的随机数 block (噪声图像)

    python - 列表和 numpy 数组之间的比较

    python - 测试用户输入 - Python

    python - 抑制 numpy 异常消息

    python - 通过广播逐元素添加稀疏 scipy 矩阵向量