MemoryView¶ ↑
MemoryView 提供在扩展库之间共享内存上的固定大小元素的多维同构数组的功能。
免责声明¶ ↑
-
此功能仍处于实验阶段。此处描述的规范将来可能会更改。
-
本文档正在建设中。请参阅 Ruby 的主分支以获取本文档的最新版本。
概述¶ ↑
我们有时会处理某些类型的对象,这些对象在连续内存区域上具有相同类型固定大小元素的数组作为其内部表示。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
当 MemoryView 暴露嵌套数组时,由每个维度中的偏移量组成的
ndim
大小数组。当 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
。