标签: memoryview

Python中的memoryview究竟是什么意思

检查内存视图上的文档:

memoryview对象允许Python代码访问支持缓冲区协议的对象的内部数据而无需复制.

class memoryview(obj)

创建一个引用obj的内存视图.obj必须支持缓冲协议.支持缓冲区协议的内置对象包括bytes和bytearray.

然后我们给出示例代码:

>>> v = memoryview(b'abcefg')
>>> v[1]
98
>>> v[-1]
103
>>> v[1:4]
<memory at 0x7f3ddc9f4350>
>>> bytes(v[1:4])
b'bce'
Run Code Online (Sandbox Code Playgroud)

报价结束,现在让我们仔细看看:

>>> b = b'long bytes stream'
>>> b.startswith(b'long')
True
>>> v = memoryview(b)
>>> vsub = v[5:]
>>> vsub.startswith(b'bytes')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'memoryview' object has no attribute 'startswith'
>>> bytes(vsub).startswith(b'bytes')
True
>>> 
Run Code Online (Sandbox Code Playgroud)

所以我从上面收集的内容:

我们创建一个memoryview对象来公开缓冲区对象的内部数据而不进行复制,但是,为了对对象做任何有用的事情(通过调用对象提供的方法),我们必须创建一个副本!

当我们有一个大对象时,通常需要memoryview(或旧的缓冲区对象),并且切片也可能很大.如果我们正在制作大切片,或者制作小切片但需要很多次,则需要提高效率.

有了上述方案,我看不出它对两种情况都有用,除非有人能向我解释我在这里缺少的东西.

EDIT1:

我们有大量数据,我们希望通过从头到尾推进它来处理它,例如从字符串缓冲区的开头提取标记,直到缓冲区被消耗.在C语言中,这是推进指针通过缓冲区,指针可以传递给任何期望缓冲区类型的函数.如何在python中完成类似的事情?

人们建议使用变通方法,例如许多字符串和正则表达式函数采用可用于模拟推进指针的位置参数.这有两个问题:首先是一个解决方法,你被迫改变你的编码风格来克服缺点,第二个:并非所有函数都有位置参数,例如正则表达式函数和startswithdo,encode()/ …

python buffer memoryview

68
推荐指数
3
解决办法
3万
查看次数

使用MemoryView时,有关NPY_NO_DEPRECATED_API的Cython Numpy警告

我正在将Cython内存视图转换为numpy数组(以便能够在纯Python代码中使用它):

from libc.stdlib cimport realloc
cimport numpy as np

DTYPE = np.float64
ctypedef np.float64_t DTYPE_t

cpdef np.ndarray[DTYPE_t] compute(DTYPE_t[:,::1] data):
    cdef unsigned int Nchannels = data.shape[0]
    cdef unsigned int Ndata = data.shape[1]
    cdef DTYPE_t* output = NULL
    cdef DTYPE_t[::1] mv

    output = <DTYPE_t*>realloc(output, Ndata*sizeof(output))
    if not output:
        raise MemoryError()
    mv = <DTYPE_t[:Ndata]>output
    mv[10:Ndata-10] = 0.0
    # various calculations...
    return np.asarray(mv, dtype=DTYPE, order='C')
Run Code Online (Sandbox Code Playgroud)

它编译,但编译器给出以下警告:

/Users/vlad/anaconda/lib/python2.7/site-packages/numpy/core/include
/nump/npy_1_7_deprecated_api.h:15:2: warning:
"Using deprecated NumPy API, disable it by #defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-W#warnings]
Run Code Online (Sandbox Code Playgroud)

我在setup.py中添加了建议的指令:

from distutils.core import …
Run Code Online (Sandbox Code Playgroud)

python numpy cython memoryview

37
推荐指数
1
解决办法
2万
查看次数

应该何时使用内存视图?

memoryview的完整描述可以在这里找到:

创建一个memoryview引用obj.obj必须支持缓冲协议.支持缓冲协议的内置对象包括bytesbytearray.

A memoryview具有元素的概念,元素是由始发对象obj处理的原子存储单元.对于许多简单类型,例如bytesbytearray,元素是单个字节,但是其他类型array.array可能具有更大的元素.

python python-3.x memoryview

29
推荐指数
1
解决办法
8872
查看次数

为什么仅在分配给变量时才创建此memoryview会引发ValueError?

Pythons memoryview支持datetime64timedelta.好.但是,当我尝试创建一个memoryview包含一个datetime64或的结构化数组时timedelta,它似乎可以工作...... 除非我将它分配给一个变量!

In [19]: memoryview(zeros(10, dtype=[("A", "m8[s]")]))
Out[19]: <memory at 0x7f1d455d6048>

In [20]: x = memoryview(zeros(10, dtype=[("A", "m8[s]")]))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
ValueError: cannot include dtype 'm' in a buffer

In [21]: x = _19

In [22]: x
Out[22]: <memory at 0x7f1d455d6048>
Run Code Online (Sandbox Code Playgroud)

这严重挑战了我对Python基本工作方式的理解.怎么能f()x = f()不同,考虑到(1)IPythons REPL分配输出到_19反正,和(2)的函数/类memoryview没有知道什么是来电者会用它的输出做的呢?

我正在运行Python 3.4.1上的代码,numpy 1.10.0.dev + fbcc24f,在Linux 2.6.32-431.23.3.el6.x86_64,Scientific Linux发行版6.6上.


编辑

在Python …

python numpy read-eval-print-loop memoryview structured-array

19
推荐指数
1
解决办法
653
查看次数

Cython:将内存视图转换为NumPy数组

如何在cython中将类型化的内存视图转换为NumPy数组?文档有

cimport numpy as np
import numpy as np

numpy_array = np.asarray(<np.int32_t[:10, :10]> my_pointer)
Run Code Online (Sandbox Code Playgroud)

我把它当作我的情况

np.asarray(<np.float_t[:, :]> my_memview)
Run Code Online (Sandbox Code Playgroud)

使用这个编译器告诉我:

Can only create cython.array from pointer or array
Run Code Online (Sandbox Code Playgroud)

复制与否并非如此具有决定性.我找不到任何帮助.

python arrays numpy cython memoryview

17
推荐指数
1
解决办法
9524
查看次数

Cython类型的记忆观点:它们到底是什么?

Cython 文档很好地解释了它们允许的内容,如何声明它们以及如何使用它们.

但是,我仍然不清楚他们到底是什么.例如,来自numpy数组的简单赋值如下:

my_arr = np.empty(10, np.int32)
cdef int [:] new_arr = my_arr
Run Code Online (Sandbox Code Playgroud)

可以使访问/分配my_arr更快.

幕后发生了什么?Numpy应该已经以连续的方式在内存中分配元素了,那么内存视图的处理是什么?显然不是那么多,实际上numpy数组的memoryview赋值new_arr应该相当于

cdef np.ndarray[np.int32_t, ndim=1] new_arr = np.empty(10, np.int32)
Run Code Online (Sandbox Code Playgroud)

在速度方面.但是,内存视图被认为比numpy数组缓冲区更通用; 你能举一个简单的例子,其中添加的"概括"是重要/有趣的吗?

此外,如果我已经分配了一个指针以使事情尽可能快,那么将它转换为类型化的内存视图有什么好处?(这个问题的答案可能与上面的问题相同)

cdef int *my_arr = <int *> malloc(N * sizeof(int))
cdef int[:] new_arr = <int[:N]>my_arr
Run Code Online (Sandbox Code Playgroud)

python arrays cython memoryview

15
推荐指数
1
解决办法
4554
查看次数

如何使用Cython类型的内存视图来接受Python中的字符串?

我如何编写一个Cython函数,它将一个字节串对象(一个普通字符串,一个bytearray或另一个跟在缓冲区协议下的对象)作为一个类型化的内存视图

根据Unicode和Passing Strings Cython教程页面,以下内容应该有效:

cpdef object printbuf(unsigned char[:] buf):
    chars = [chr(x) for x in buf]
    print repr(''.join(chars))
Run Code Online (Sandbox Code Playgroud)

它适用于bytearrays和其他可写缓冲区:

$ python -c 'import test; test.printbuf(bytearray("test\0ing"))'
'test\x00ing'
Run Code Online (Sandbox Code Playgroud)

但它不适用于普通字符串和其他只读缓冲区对象:

$ python -c 'import test; test.printbuf("test\0ing")'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "test.pyx", line 1, in test.printbuf (test.c:1417)
  File "stringsource", line 614, in View.MemoryView.memoryview_cwrapper (test.c:6795)
  File "stringsource", line 321, in View.MemoryView.memoryview.__cinit__ (test.c:3341)
BufferError: Object is not writable.
Run Code Online (Sandbox Code Playgroud)

查看生成的C代码,Cython总是将PyBUF_WRITABLE标志传递给PyObject_GetBuffer(),这解释了异常. …

python cython python-c-extension python-2.7 memoryview

13
推荐指数
2
解决办法
1835
查看次数

Cython Memoryview作为返回值

考虑这个虚拟的Cython代码:

#!python
#cython: boundscheck=False
#cython: wraparound=False
#cython: initializedcheck=False
#cython: cdivision=True
#cython: nonecheck=False

import numpy as np

# iterator function
cdef double[:] f(double[:] data):
    data[0] *= 1.01
    data[1] *= 1.02
    return data

# looping function
cdef double[:] _call_me(int bignumber, double[:] data):
    cdef int ii
    for ii in range(bignumber):
        data = f(data)
    return data

# helper function to allow calls from Python
def call_me(bignumber):
    cdef double[:] data = np.ones(2)
    return _call_me(bignumber, data)
Run Code Online (Sandbox Code Playgroud)

现在,如果我对此进行了一次cython -a,它会以黄色显示返回语句.我在一个性能非常关键的程序中做了类似的事情,根据分析,这实际上减慢了我的代码速度.那么,为什么cython需要python用于这些返回语句?带注释的文件提供了一个提示:

PyErr_SetString(PyExc_TypeError,"Memoryview return value is not initialized"); …
Run Code Online (Sandbox Code Playgroud)

python numpy cython memoryview

11
推荐指数
1
解决办法
1688
查看次数

缓冲区和Memoryview对象为非C程序员解释

Python 2.7 为缓冲区和内存视图对象引入了一个新的API.

我阅读了关于它们的文档,我认为我得到了基本的概念(以原始形式访问对象的内部数据而不复制它,我想这意味着"更快,更少内存的"获取对象数据的方式),但要真正理解文档,读者应该具备超越我所拥有的C知识.

如果有人愿意花时间,我将非常感激:

  • 用"外行术语"解释缓冲区和内存视图对象
  • 描述了一个场景,其中使用缓冲区和memoryview对象将是"Pythonic方式"

c python python-2.x python-2.7 memoryview

10
推荐指数
1
解决办法
4632
查看次数

Cython:已释放内存的内存视图

在Cython代码中,我可以分配一些内存并将其包装在内存视图中,例如:

cdef double* ptr
cdef double[::1] view
ptr = <double*> PyMem_Malloc(N*sizeof('double'))
view = <double[:N]> ptr
Run Code Online (Sandbox Code Playgroud)

如果现在我使用释放内存PyMem_Free(ptr),则尝试访问元素之类ptr[i]的错误将导致错误。但是,我可以安全地尝试访问view[i](尽管它不会返回原始数据)。

我的问题是:仅释放指针总是安全吗?是否以某种方式通知内存视图对象已释放内存,还是应该以某种方式手动删除视图?此外,即使内存视图引用了内存,也可以保证释放内存吗?

python memory free cython memoryview

10
推荐指数
1
解决办法
215
查看次数