Python Cython:理解带有间接相邻内存布局的类型化内存视图
我想了解更多关于Cython的精彩和内存布局Python Cython:理解带有间接相邻内存布局的类型化内存视图,python,cython,typed-memory-views,Python,Cython,Typed Memory Views,我想了解更多关于Cython的精彩和内存布局indirect\u continuous 根据间接法,当“指针列表是连续的”时使用 还有一个示例用法: 如果我错了,请纠正我,但是我假设“连续的int”列表的指针“连续列表”的意思是类似于由下面的C++虚伪代码创建的数组: //我们要创建一个“指向连续整数列表的连续指针列表” 整数**数组; //分配行指针 //这是与第一个维度相关的“连续指针列表”: 数组=新整数*[行计数] //分配一些行,每行都是“连续的整数列表” 数组[0]=新整数[COL
indirect\u continuous
根据间接法,当“指针列表是连续的”时使用
还有一个示例用法:
如果我错了,请纠正我,但是我假设“连续的int”列表的指针“连续列表”的意思是类似于由下面的C++虚伪代码创建的数组:
//我们要创建一个“指向连续整数列表的连续指针列表”
整数**数组;
//分配行指针
//这是与第一个维度相关的“连续指针列表”:
数组=新整数*[行计数]
//分配一些行,每行都是“连续的整数列表”
数组[0]=新整数[COL_COUNT]{1,2,3}
因此,如果我理解正确,那么在我的Cython代码中,应该可以从int**
中获得如下的memoryview:
cdef int**list_of_pointers=get_pointers()
cdef int[::view.indirect_continuous,::1]view=指针列表
但我得到编译错误:
cdef int[::view.indirect_contiguous, ::1] view = <int[:ROW_COUNT:view.indirect_contiguous,:COL_COUNT:1]> list_of_pointers
^
------------------------------------------------------------
memview_test.pyx:76:116: Pointer base type does not match cython.array base type
cdef int[::view.indirect_continuous,::1]view=指针列表
^
------------------------------------------------------------
memview_test.pyx:76:116:指针基类型与cython.array基类型不匹配
我做错了什么?
我是否遗漏了任何类型转换,或者我是否误解了间接连续的概念?让我们澄清一下:类型化内存视图只能用于实现的对象
原始C指针显然没有实现缓冲区协议。但您可能会问,为什么下面的快速脏代码会起作用:
%%cython
from libc.stdlib cimport calloc
def f():
cdef int* v=<int *>calloc(4, sizeof(int))
cdef int[:] b = <int[:4]>v
return b[0] # leaks memory, so what?
在您的情况下,跨步
和偏移
将是
strips=[sizeof(int*),sizeof(int)]
(即在普通x86\u 64
机器上的[8,4]
)
偏移量=[0,-1]
,即只有第一个维度是间接的
获取元素[x,y]
的地址将按如下方式进行:
- 在
A
行中,指针
设置为buf
,假设buf
- 第一维度:
- 在第
B
行中,指针
变为BUF+x*8
,并指向指向第x行的指针位置
- 因为
suboffset[0]>=0
,我们在C
行中取消对指针的引用,因此它显示了地址行X
——第X行的开始
- 第二维度:
- 在第
B行
中,我们使用步长
获得y
元素的地址,即指针=行X+4*y
- 第二维度是直接的(由
suboffset[1]表示),这可能不可能仅通过强制转换实现-例如,请参见似乎手动构造缓冲区接口的示例。很好,非常感谢您的详细解释。我将深入了解缓冲区协议的详细信息
%%cython
from libc.stdlib cimport calloc
def f():
cdef int* v=<int *>calloc(4, sizeof(int))
cdef int[:] b = <int[:4]>v
return b[0] # leaks memory, so what?
void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides,
Py_ssize_t *suboffsets, Py_ssize_t *indices) {
char *pointer = (char*)buf; // A
int i;
for (i = 0; i < ndim; i++) {
pointer += strides[i] * indices[i]; // B
if (suboffsets[i] >=0 ) {
pointer = *((char**)pointer) + suboffsets[i]; // C
}
}
return (void*)pointer; // D
}