使用“,”对切片 numpy 数组进行广播比较比“][”慢很多
Broadcast comparison on sliced numpy array using "," is a lot slower than "]["
我不确定为什么使用 ,
比较切片的 numpy 数组比 ][
慢很多。例如:
start = time.time()
a = np.zeros((100,100))
for _ in range(1000000):
a[1:99][1:99] == 1
print(time.time() - start)
start = time.time()
a = np.zeros((100,100))
for _ in range(1000000):
a[1:99, 1:99] == 1
print(time.time() - start)
3.2756259441375732
11.044903039932251
差了 3 倍多。
使用 timeit
.
的时间测量值大致相同
我正在研究递归算法(我打算这样做),这些问题使我的程序 运行 慢了很多,从大约 1 秒增加到 10 秒。我只想知道他们背后的原因。可能这是一个错误。我正在使用 Python 3.9.9。谢谢。
第一个与a[2:99]==1
相同。 (98,100) 切片后跟 (97,100),然后是 == 测试。
In [177]: timeit (a[1:99][1:99]==1)
8.51 µs ± 16.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [178]: timeit (a[1:99][1:99])
383 ns ± 5.73 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [179]: timeit (a[1:99])
208 ns ± 10.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
大部分时间是测试,而不是切片。
In [180]: a[1:99,1:99].shape
Out[180]: (98, 98)
In [181]: timeit a[1:99,1:99]==1
32.2 µs ± 12.9 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [182]: timeit a[1:99,1:99]
301 ns ± 3.61 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
同样,切片是计时的一小部分,但 ==
测试明显更慢。在第一种情况下,我们 select 编辑了行的子集,因此测试是在数据缓冲区的连续块上进行的。在第二个中,我们 select 行和列的子集。通过数据缓冲区的迭代更复杂。
我们可以通过测试一段列与一段行来简化比较:
In [183]: timeit a[:,2:99]==1
32.3 µs ± 13.8 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [184]: timeit a[2:99,:]==1
8.58 µs ± 10.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
作为进一步的测试,使用 'F' 顺序创建一个新数组。现在“行”是慢切片
In [189]: b = np.array(a, order='F')
In [190]: timeit b[:,2:99]==1
8.83 µs ± 20.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [191]: timeit b[2:99,:]==1
32.8 µs ± 31.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
===
但是你为什么要比较这两个切片,一个是 (97,100) 数组,另一个是 (98,98)。他们正在挑选 a
.
的不同部分
我想知道您是否真的打算测试连续的行、列切片,而不是两个行切片。
In [193]: timeit (a[1:99][:,1:99]==1)
32.6 µs ± 92.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
仅比较切片,我们发现顺序切片要慢一点点。
In [194]: timeit (a[1:99][:,1:99])
472 ns ± 3.76 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [195]: timeit (a[1:99,1:99])
306 ns ± 3.19 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
===
a
的数据实际上存储在1d c
数组中。 numpy 代码在执行 a[...] == 1
.
之类的操作时使用步幅和形状对其进行迭代
想象一下 (3,6) 数据缓冲区看起来像
[0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5]
用[1:3]
切片,它将使用
[_ _ _ _ _ _ 0 1 2 3 4 5 0 1 2 3 4 5]
切片 [:,1:4]
它将使用
[_ 1 2 3 _ _ _ 1 2 3 _ _ _ 1 2 3 _ _]
不管处理器缓存细节如何,通过 2 的迭代更复杂。
我不确定为什么使用 ,
比较切片的 numpy 数组比 ][
慢很多。例如:
start = time.time()
a = np.zeros((100,100))
for _ in range(1000000):
a[1:99][1:99] == 1
print(time.time() - start)
start = time.time()
a = np.zeros((100,100))
for _ in range(1000000):
a[1:99, 1:99] == 1
print(time.time() - start)
3.2756259441375732
11.044903039932251
差了 3 倍多。
使用 timeit
.
我正在研究递归算法(我打算这样做),这些问题使我的程序 运行 慢了很多,从大约 1 秒增加到 10 秒。我只想知道他们背后的原因。可能这是一个错误。我正在使用 Python 3.9.9。谢谢。
第一个与a[2:99]==1
相同。 (98,100) 切片后跟 (97,100),然后是 == 测试。
In [177]: timeit (a[1:99][1:99]==1)
8.51 µs ± 16.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [178]: timeit (a[1:99][1:99])
383 ns ± 5.73 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [179]: timeit (a[1:99])
208 ns ± 10.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
大部分时间是测试,而不是切片。
In [180]: a[1:99,1:99].shape
Out[180]: (98, 98)
In [181]: timeit a[1:99,1:99]==1
32.2 µs ± 12.9 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [182]: timeit a[1:99,1:99]
301 ns ± 3.61 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
同样,切片是计时的一小部分,但 ==
测试明显更慢。在第一种情况下,我们 select 编辑了行的子集,因此测试是在数据缓冲区的连续块上进行的。在第二个中,我们 select 行和列的子集。通过数据缓冲区的迭代更复杂。
我们可以通过测试一段列与一段行来简化比较:
In [183]: timeit a[:,2:99]==1
32.3 µs ± 13.8 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [184]: timeit a[2:99,:]==1
8.58 µs ± 10.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
作为进一步的测试,使用 'F' 顺序创建一个新数组。现在“行”是慢切片
In [189]: b = np.array(a, order='F')
In [190]: timeit b[:,2:99]==1
8.83 µs ± 20.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [191]: timeit b[2:99,:]==1
32.8 µs ± 31.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
===
但是你为什么要比较这两个切片,一个是 (97,100) 数组,另一个是 (98,98)。他们正在挑选 a
.
我想知道您是否真的打算测试连续的行、列切片,而不是两个行切片。
In [193]: timeit (a[1:99][:,1:99]==1)
32.6 µs ± 92.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
仅比较切片,我们发现顺序切片要慢一点点。
In [194]: timeit (a[1:99][:,1:99])
472 ns ± 3.76 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [195]: timeit (a[1:99,1:99])
306 ns ± 3.19 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
===
a
的数据实际上存储在1d c
数组中。 numpy 代码在执行 a[...] == 1
.
想象一下 (3,6) 数据缓冲区看起来像
[0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5]
用[1:3]
切片,它将使用
[_ _ _ _ _ _ 0 1 2 3 4 5 0 1 2 3 4 5]
切片 [:,1:4]
它将使用
[_ 1 2 3 _ _ _ 1 2 3 _ _ _ 1 2 3 _ _]
不管处理器缓存细节如何,通过 2 的迭代更复杂。