使用 memoryview (Python 3.5.0) 切片分配较慢
slice assignment slower using memoryview (Python 3.5.0)
我有一个大的字节数组 x,想将它的一部分分配给另一个字节数组 y 的一部分
x = bytearray(10**7) #something else in practice
y = bytearray(6*10**6)
y[::6] = x[:2*10**6:2]
我认为使用 memoryview 会更快,确实如此
memoryview(x)[:2*10**6:2]
速度非常快。然而,
y[::6] = memoryview(x)[:2*10**6:2]
花费的时间是y[::6] = x[:2*10**6:2]
的5倍
- 我是不是遗漏了什么,或者这种减速是 Python 中的错误?
- 在 Python (a) 如果我想重复分配已知数量的 0,以及 (b) 通常情况下,最快的方法是什么?
减速并不是一个错误,而是 memoryview
和缓冲协议仍然相对较新并且优化不佳。 y[::6] = memoryview(x)[:2*10**6:2]
的底层代码在复制之前创建 bytearray
的连续副本。这意味着它比直接创建和分配 bytearray
的普通切片要慢。事实上,在这个特定的例子中(在我的机器上),使用 memoryview
比直接赋值更接近使用 y[::6] = islice(x, None, 2*10**6, 2)
的速度。
numpy
已经存在了很长时间,并且针对您感兴趣的操作类型进行了更好的优化。
使用ipython:
In [1]: import numpy as np; from itertools import islice
In [2]: x = bytearray(10**7)
In [3]: y = bytearray(6*10**6)
In [4]: x_np = np.array(x)
In [5]: y_np = np.array(y)
In [6]: %timeit y[::6] = memoryview(x)[:2*10**6:2]
100 loops, best of 3: 10.9 ms per loop
In [7]: %timeit y[::6] = x[:2*10**6:2]
1000 loops, best of 3: 1.65 ms per loop
In [8]: %timeit y[::6] = islice(x, None, 2*10**6, 2)
10 loops, best of 3: 22.9 ms per loop
In [9]: %timeit y_np[::6] = x_np[:2*10**6:2]
1000 loops, best of 3: 911 µs per loop
最后两个的额外好处是内存开销很小。
我有一个大的字节数组 x,想将它的一部分分配给另一个字节数组 y 的一部分
x = bytearray(10**7) #something else in practice
y = bytearray(6*10**6)
y[::6] = x[:2*10**6:2]
我认为使用 memoryview 会更快,确实如此
memoryview(x)[:2*10**6:2]
速度非常快。然而,
y[::6] = memoryview(x)[:2*10**6:2]
花费的时间是y[::6] = x[:2*10**6:2]
- 我是不是遗漏了什么,或者这种减速是 Python 中的错误?
- 在 Python (a) 如果我想重复分配已知数量的 0,以及 (b) 通常情况下,最快的方法是什么?
减速并不是一个错误,而是 memoryview
和缓冲协议仍然相对较新并且优化不佳。 y[::6] = memoryview(x)[:2*10**6:2]
的底层代码在复制之前创建 bytearray
的连续副本。这意味着它比直接创建和分配 bytearray
的普通切片要慢。事实上,在这个特定的例子中(在我的机器上),使用 memoryview
比直接赋值更接近使用 y[::6] = islice(x, None, 2*10**6, 2)
的速度。
numpy
已经存在了很长时间,并且针对您感兴趣的操作类型进行了更好的优化。
使用ipython:
In [1]: import numpy as np; from itertools import islice
In [2]: x = bytearray(10**7)
In [3]: y = bytearray(6*10**6)
In [4]: x_np = np.array(x)
In [5]: y_np = np.array(y)
In [6]: %timeit y[::6] = memoryview(x)[:2*10**6:2]
100 loops, best of 3: 10.9 ms per loop
In [7]: %timeit y[::6] = x[:2*10**6:2]
1000 loops, best of 3: 1.65 ms per loop
In [8]: %timeit y[::6] = islice(x, None, 2*10**6, 2)
10 loops, best of 3: 22.9 ms per loop
In [9]: %timeit y_np[::6] = x_np[:2*10**6:2]
1000 loops, best of 3: 911 µs per loop
最后两个的额外好处是内存开销很小。