MemoryView¶ ↑
MemoryView 提供了在扩展库之间共享内存中固定大小元素的同质多维数组的功能。
免责声明¶ ↑
-
此功能仍处于实验阶段。此处描述的规范将来可能会更改。
-
本文档正在建设中。请参阅 ruby 的 master 分支以获取本文档的最新版本。
概述¶ ↑
我们有时会处理某些类型的对象,这些对象在其内部表示中具有连续内存区域上相同类型固定大小元素的数组。 numo-narray 中的 Numo::NArray 和 rmagick 中的 Magick::Image 是此类对象的典型示例。 MemoryView 的作用是充当枢纽,在这些库之间共享此类对象的内部数据,而无需复制。
数据的无复制共享在某些领域非常重要,例如数据分析、机器学习和图像处理。在这些领域,人们需要使用多个库处理大量的内存数据。如果被迫在库之间复制大量数据来交换数据,那么大量的数据处理时间必须被复制数据所占用。您可以通过使用 MemoryView 来避免这种浪费时间的情况。
MemoryView 有两种类型的 API
-
生产者 API
类可以注册自己的 MemoryView 条目,这允许该类的对象公开其 MemoryView
-
消费者 API
消费者 API 允许我们获取和管理对象的 MemoryView
MemoryView 结构¶ ↑
MemoryView 结构 rb_memory_view_t
用于导出对象的 MemoryView。此结构包含对象的引用(即 MemoryView 的所有者)、指向导出内存头的指针以及描述内存结构的元数据。该元数据可以描述具有步幅的多维数组。
MemoryView 结构的成员¶ ↑
MemoryView 结构由以下成员组成。
-
VALUE obj
对原始对象的引用,该对象拥有通过 MemoryView 导出的内存。
RubyVM
管理 MemoryView 导出对象的引用计数,以防止它们被垃圾回收。消费者不必费力地保护此对象免受GC
的影响。 -
void *data
指向导出内存头的指针。
-
ssize_t byte_size
data
指向的内存中的字节数。 -
bool readonly
对于只读内存为
true
,对于可写内存为false
。 -
const char *format
用于描述元素格式的字符串,对于无符号字节则为 NULL。
-
ssize_t item_size
每个元素中的字节数。
-
const rb_memory_view_item_component_t *item_desc.components
元素中组件的元数据数组。
-
size_t item_desc.length
item_desc.components
中的项目数。 -
ssize_t ndim
维数。
-
const ssize_t *shape
一个
ndim
大小的数组,指示每个维度中的元素数。当ndim
为 1 时,可以为NULL
。 -
const ssize_t *strides
一个
ndim
大小的数组,指示在每个维度中跳到下一个元素要跳过的字节数。当ndim
为 1 时,可以为NULL
。 -
const ssize_t *sub_offsets
一个
ndim
大小的数组,由 MemoryView 公开嵌套数组时每个维度中的偏移量组成。当 MemoryView 公开一个平面数组时,可以为NULL
。 -
void *private_data
MemoryView 提供程序在内部使用的私有数据。当不需要任何私有数据时,可以为
NULL
。
MemoryView API¶ ↑
对于使用者¶ ↑
-
bool rb_memory_view_available_p(VALUE obj)
如果
obj
支持导出 MemoryView,则返回true
。否则返回false
。如果此函数返回
true
,则并不意味着函数rb_memory_view_get
将会成功。 -
bool rb_memory_view_get(VALUE obj, rb_memory_view_t *view, int flags)
如果给定的
obj
支持导出符合给定flags
的 MemoryView,则此函数会用 MemoryView 的信息填充view
并返回true
。在这种情况下,obj
的引用计数会增加。如果给定的
obj
和flags
组合无法导出 MemoryView,则此函数返回false
。在这种情况下,不会触及view
的内容。当不再需要 MemoryView 时,必须使用
rb_memory_view_release
释放导出的 MemoryView。 -
bool rb_memory_view_release(rb_memory_view_t *view)
释放给定的 MemoryView
view
并减少view->obj
的引用计数。当不再需要 MemoryView 时,消费者必须调用此函数。如果未调用此函数,则会导致内存泄漏。
-
ssize_t rb_memory_view_item_size_from_format(const char *format, const char **err)
计算元素占用的字节数。
当计算失败时,
format
中失败的位置存储到err
中,并返回-1
。 -
void *rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices)
计算给定
indices
指示的项的位置。indices
的长度必须等于view->ndim
。此函数在需要时初始化view->item_desc
。 -
VALUE rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices)
返回给定
indices
指示的项的 Ruby 对象表示形式。indices
的长度必须等于view->ndim
。此函数使用rb_memory_view_get_item_pointer
。 -
rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly)
将 view
的成员填充为一维字节数组。
-
void rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides)
用给定形状的连续数组的字节步幅和给定元素大小填充 strides
数组。
-
void rb_memory_view_prepare_item_desc(rb_memory_view_t *view)
填充 view
的 item_desc
成员。
-
bool rb_memory_view_is_contiguous(const rb_memory_view_t *view)
如果 MemoryView view
中的数据是行优先或列优先连续的,则返回 true
。
否则返回 false
。
-
bool rb_memory_view_is_row_major_contiguous(const rb_memory_view_t *view)
如果 MemoryView view
中的数据是行优先连续的,则返回 true
。
否则返回 false
。
-
bool rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view)
如果 MemoryView view
中的数据是列优先连续的,则返回 true
。
否则返回 false
。