Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Buffer protocol proposal #3261

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Sep 25, 2020
Merged

Buffer protocol proposal #3261

merged 28 commits into from
Sep 25, 2020

Conversation

mrkn
Copy link
Member

@mrkn mrkn commented Jun 26, 2020

@mrkn mrkn marked this pull request as draft June 26, 2020 09:06
@mrkn mrkn force-pushed the buffer_protocol branch 2 times, most recently from c1dc40a to 7d5e5e6 Compare June 29, 2020 12:35
/* The original object that have the memory exported via this buffer.
* The consumer of this buffer has the responsibility to call rb_gc_mark
* for preventing this obj collected by GC. */
VALUE obj;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed?
The consumer calls rb_obj_get_buffer(obj, ...). So it must know the obj.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some committers suggest to let RubyVM manage the reference of obj until its buffer will be released.
This obj may be useful for such a purpose.

@mrkn mrkn force-pushed the buffer_protocol branch 2 times, most recently from 88d54af to 8b8ecfb Compare July 19, 2020 14:46
@mrkn mrkn force-pushed the buffer_protocol branch 3 times, most recently from 829c6f2 to 07fd1a9 Compare August 24, 2020 02:25
@dsisnero
Copy link
Contributor

In python the memoryview constructor is used to build a memoryvieew object that references the original object. The original object implements the buffer protocol.

s = b"abcdefgh"
view = memoryview(s)
view[1]
98
limited = view[1:3]
limited
<memory at 0x7fca18b8d460>
bytes(view[1:3])
b'bc'

I think changing the name to memory view for the underlying buffer is confusing.
https://julien.danjou.info/high-performance-in-python-with-zero-copy-and-the-buffer-protocol/

@mrkn
Copy link
Member Author

mrkn commented Aug 25, 2020

@dsisnero Our goal isn’t completely following Python.

@mrkn mrkn force-pushed the buffer_protocol branch 5 times, most recently from 325f8d5 to 604949f Compare September 1, 2020 07:07
bool alignment = false;

const char *p = format;
if (*p == '|') { // alginment specifier
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I employed | for specifying element aligning mode.

@mrkn mrkn requested a review from akr September 1, 2020 07:26
@mrkn
Copy link
Member Author

mrkn commented Sep 1, 2020

@akr Could you please review this?

@mrkn mrkn marked this pull request as ready for review September 1, 2020 07:37
@mrkn mrkn changed the title WIP: Buffer protocol proposal Buffer protocol proposal Sep 10, 2020
*members = buf;
*n_members = len;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems no padding after the last component.
I guess that the size of "lc" would be 5.
But it should be 8 to align next item.

memory_view.c Outdated
uint8_t *ptr = view->data;

if (view->ndim == 1) {
return ptr + indices[0] * view->item_size;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

view->strides is ignored.
Is it intentional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, view->strides shouldn't be ignored. I'll fix it.

memory_view.c Outdated
if (view->strides == NULL) {
// row-major contiguous array
for (i = 0; i < view->ndim; ++i) {
ptr += indices[i] * view->shape[i] * view->item_size;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess view->shape[i] should be view->shape[i+1] * ... * view->shape[ndim-1].
Not tested.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly. I should write a test of this function.


#undef DEF_ALIGNMENT_CONST

exported_objects = rb_hash_new();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that string content-based comparison is not appropriate here.
It may needs compare_by_identity.


if (view.shape) {
VALUE shape = rb_ary_new_capa(view.ndim);
rb_hash_aset(hash, sym_shape, shape);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this is incomplete.
shape is always an empty array.
strides and sub_offsets has same issue.

/* 1 for readonly memory, 0 for writable memory. */
int readonly;

/* A string to describe the format of an element, or NULL for unsigned byte.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems "item" and "element" are same meaning.
How about using one word for one meaning?

@mrkn mrkn force-pushed the buffer_protocol branch 5 times, most recently from e8a67fe to 657b021 Compare September 20, 2020 09:24
@mrkn
Copy link
Member Author

mrkn commented Sep 25, 2020

The CI failure isn’t due to this pull request.

@mrkn mrkn merged commit 890bc2c into ruby:master Sep 25, 2020
@mrkn mrkn deleted the buffer_protocol branch September 25, 2020 11:32
@mrkn
Copy link
Member Author

mrkn commented Sep 25, 2020

Oh, I rewrote the merge commit message but I don't know why it was rolled back..
The message I wrote was:

Memory view interface (#3261)

The memory view interface is a C-API set to exchange a raw memory area,
such as a numeric array and a bitmap image, between extension libraries.
The extension libraries can share also the metadata of the memory area
that consists of the shape, the element format, and so on.
Using these kinds of metadata, the extension libraries can share even
a multidimensional array appropriately.
This feature is designed by referring to Python's buffer protocol.

[Feature #13767]
[Feature #14722]

ioquatix pushed a commit to ioquatix/ruby that referenced this pull request Sep 30, 2020
* Add buffer protocol

* Modify for some review comments

* Per-object buffer availability

* Rename to MemoryView from Buffer and make compilable

* Support integral repeat count in memory view format

* Support 'x' for padding bytes

* Add rb_memory_view_parse_item_format

* Check type in rb_memory_view_register

* Update dependencies in common.mk

* Add test of MemoryView

* Add test of rb_memory_view_init_as_byte_array

* Add native size format test

* Add MemoryView test utilities

* Add test of rb_memory_view_fill_contiguous_strides

* Skip spaces in format string

* Support endianness specifiers

* Update documentation

* Support alignment

* Use RUBY_ALIGNOF

* Fix format parser to follow the pack format

* Support the _ modifier

* Parse count specifiers in get_format_size function.

* Use STRUCT_ALIGNOF

* Fix test

* Fix test

* Fix total size for the case with tail padding

* Fix rb_memory_view_get_item_pointer

* Fix rb_memory_view_parse_item_format again
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants