ndav 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.gitlab-ci.yml +12 -0
- data/.yardopts +3 -0
- data/NDAV.png +0 -0
- data/README.md +165 -1
- data/Rakefile +4 -2
- data/lib/ndav/converter.rb +4 -0
- data/ndav.gemspec +4 -2
- data/test/test_ndav.rb +7 -0
- metadata +20 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e27d78e17f22830ab47cba80120c7fa3ad3139690dd276e1267abb8696c6ffe3
|
|
4
|
+
data.tar.gz: 1a3ab5273684a54a5920528663fa5ebcab8ab861213b622b60afe3267ff184e5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6fe639a15fd780e5add9dcf124f3222214f6dd82cef28e4c16589f0f9dae936dda08e378ed28a3fa9bb810933250caf48bad2a18885a6261685451b3faf14bf0
|
|
7
|
+
data.tar.gz: 3b3769ce7d12622bd231d0f4bffeb590b631a4c6be42984e2c998c49b64d2c24499bf922744d11b02c27dd308735c8f29d3385c70d5f3753509ce3bd70d4415f
|
data/.gitignore
CHANGED
data/.gitlab-ci.yml
CHANGED
data/.yardopts
ADDED
data/NDAV.png
ADDED
|
Binary file
|
data/README.md
CHANGED
|
@@ -1,9 +1,173 @@
|
|
|
1
1
|
NDAV - N-Dimensional Array View
|
|
2
2
|
===============================
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
[](https://badge.fury.io/rb/ndav)
|
|
5
|
+
|
|
6
|
+
A thin wrapper around [MemoryView][] ("buffer protocol" for Ruby).
|
|
7
|
+
|
|
8
|
+
It provides an interoperability layer for multi-dimensional arrays which can be shared between libraries.
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
SYNOPSIS
|
|
13
|
+
--------
|
|
14
|
+
|
|
15
|
+
waveform, sample_rate = TorchAudio.load("path/to/audio.wav")
|
|
16
|
+
|
|
17
|
+
# Convert Torch::Tensor to NDAV
|
|
18
|
+
# so that you can convert it to OrtValue,
|
|
19
|
+
# a data format for ONNX Runtime
|
|
20
|
+
input = waveform
|
|
21
|
+
.to_ndav
|
|
22
|
+
.to_ort_value
|
|
23
|
+
|
|
24
|
+
# Make ONNX Runtime return result as OrtValue
|
|
25
|
+
outputs = OnnxRuntime::Session.new("path/to/model.onnx")
|
|
26
|
+
.run(
|
|
27
|
+
[:output_name],
|
|
28
|
+
{input_name: input},
|
|
29
|
+
output_type: :ort_value
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# You may convert OrtValue to Torch::Tensor via NDAV
|
|
33
|
+
output_tensor = outputs[0]
|
|
34
|
+
.to_ndav
|
|
35
|
+
.to_torch_tensor # converts back to Torch::Tensor
|
|
36
|
+
|
|
37
|
+
TorchAudio.save("path/to/output.wav", output_tensor, sample_rate)
|
|
38
|
+
|
|
39
|
+
ABSTRACT
|
|
40
|
+
--------
|
|
41
|
+
|
|
42
|
+
NDAV acts as an interoperability layer between multi-dimensional arrays including images, audio and tensors such as [Numo::NArray][], [Torch.rb][]'s `Torch::Tensor`, [ONNX Runtime Ruby][]'s `OnnxRuntime::OrtValue`, [Red Arrow][]'s `Arrow::Array` and so on.
|
|
43
|
+
|
|
44
|
+
It allows data to be shared without copying.
|
|
45
|
+
|
|
46
|
+
BACKGROUND
|
|
47
|
+
----------
|
|
48
|
+
|
|
49
|
+
In the modern Ruby community, [Numo::NArray][] is often used for data conversion. But, data are copied when converting to and from Numo::NArray. In addition, Numo::NArray neither exports nor accepts MemoryView.
|
|
50
|
+
|
|
51
|
+
[Red Arrow][] is also used and it can export MemoryView from `Arrow::Array` (not from `Arrow::Tensor`, though). It also can be converted to and from Numo::NArray using [Red Arrow Numo::NArray][]. But, in real-world usage, we need, for example, to convert data with many hops:
|
|
52
|
+
|
|
53
|
+
Torch::Tensor -> Numo::NArray -> Red Arrow -> MemoryView -> some process...
|
|
54
|
+
|
|
55
|
+
It might not be difficult, but a little bit cumbersome. Additionally, Red Arrow doesn't accept MemoryView.
|
|
56
|
+
|
|
57
|
+
USAGE
|
|
58
|
+
-----
|
|
59
|
+
|
|
60
|
+
`ndav` gem is just a base library. You need to install bridges as well. Say, assume you want to make conversions between Numo::NArray each other.
|
|
61
|
+
|
|
62
|
+
require "numo/narray"
|
|
63
|
+
require "ndav"
|
|
64
|
+
require "ndav/numo/narray"
|
|
65
|
+
|
|
66
|
+
numo = Numo::SFloat.new(3, 5).seq # => Numo::SFloat
|
|
67
|
+
ndav = numo.to_ndav # => NDAV
|
|
68
|
+
|
|
69
|
+
numo = Numo::SFloat.from_ndav(ndav) # => Numo::SFloat
|
|
70
|
+
ndav = NDAV.from_numo_narray(numo) # => NDAV
|
|
71
|
+
|
|
72
|
+
include NDAV::Converter
|
|
73
|
+
numo = NumoNArray(ndav) #=> Numo::SFloat
|
|
74
|
+
ndav = NDAV(numo) # => NDAV
|
|
75
|
+
|
|
76
|
+
For `Torch::Tensor` and `OnnxRuntime::OrtValue`, you can do the same operation, therefore you may convert them to each other, like this:
|
|
77
|
+
|
|
78
|
+
numo
|
|
79
|
+
.to_ndav
|
|
80
|
+
.to_torch_tensor
|
|
81
|
+
.then {|torch_tensor| some_process(torch_tensor)}
|
|
82
|
+
.to_ndav
|
|
83
|
+
.to_ort_value
|
|
84
|
+
.then {|ort_value|
|
|
85
|
+
OnnxRuntime::Session.new("model.onnx")
|
|
86
|
+
.run(
|
|
87
|
+
[:output],
|
|
88
|
+
{input: ort_value},
|
|
89
|
+
output_type: :ort_value
|
|
90
|
+
)[0]
|
|
91
|
+
}
|
|
92
|
+
.to_ndav
|
|
93
|
+
.to_torch_tensor
|
|
94
|
+
.then {|torch_tensor| TorchAudio.save(torch_tensor, sample_rate)}
|
|
95
|
+
|
|
96
|
+
### Working With MemoryView ###
|
|
97
|
+
|
|
98
|
+
NDAV can be initialized *directly* from libraries which export [MemoryView][] such as [Red Arrow][], without any bridge library:
|
|
99
|
+
|
|
100
|
+
arrow = Arrow::Int16Array.new([1, 2, 3])
|
|
101
|
+
ndav = NDAV.new(arrow)
|
|
102
|
+
|
|
103
|
+
On the other hand, it also exports MemoryView. You can pass NDAV arrays *directly* to methods which accept MemoryView such as whispercpp without bridge libraries:
|
|
104
|
+
|
|
105
|
+
waveform, sample_rate = TorchAudio.load("path/to/audio.wav")
|
|
106
|
+
samples = waveform.to_ndav
|
|
107
|
+
whisper.full(params, samples)
|
|
108
|
+
|
|
109
|
+
### Notice On Memory Sharing ###
|
|
110
|
+
|
|
111
|
+
Notice that NDAV is just a memory view and libraries share a memory address. If you change source data destructively, it affects converted data.
|
|
112
|
+
|
|
113
|
+
Additionally, you potentially encounter odd data corruption or segmentation fault. These might be bugs in bridge libraries such as [ndav-numo-narray][]. As a user, you don't need to worry about this kind of memory management, but it's worth knowing such situations may occur.
|
|
114
|
+
|
|
115
|
+
INSTALLATION
|
|
116
|
+
------------
|
|
117
|
+
|
|
118
|
+
% gem install ndav
|
|
119
|
+
|
|
120
|
+
or,
|
|
121
|
+
|
|
122
|
+
% bundle add ndav
|
|
123
|
+
|
|
124
|
+
But, you need bridges for real-world use. See each bridge's documentation for individual requirements.
|
|
125
|
+
|
|
126
|
+
BRIDGES
|
|
127
|
+
-------
|
|
128
|
+
|
|
129
|
+
There are some bridges using NDAV:
|
|
130
|
+
|
|
131
|
+
* [ndav/ffi][]: [`FFI::MemoryPointer`][FFI Pointer], [`FFI::Pointer`][FFI Pointer] <-> `NDAV`
|
|
132
|
+
* [ndav-numo-narray][]: [`Numo::NArray`][Numo::NArray] <-> `NDAV`
|
|
133
|
+
* [ndav-ort_value][]: [`OnnxRuntime::OrtValue`][ONNX Runtime Ruby] <-> `NDAV`
|
|
134
|
+
* [ndav-torch-tensor][]: [`Torch::Tensor`][Torch.rb] <-> `NDAV`
|
|
135
|
+
* [onnxruntime-torch-tensor][]: [`Torch::Tensor`][Torch.rb] <-> [`OnnxRuntime::OrtValue`][ONNX Runtime Ruby] via `NDAV`
|
|
136
|
+
|
|
137
|
+
CREATING BRIDGES
|
|
138
|
+
----------------
|
|
139
|
+
|
|
140
|
+
Refer to existing bridge implementations listed above to create your bridge.
|
|
141
|
+
|
|
142
|
+
The points are:
|
|
143
|
+
|
|
144
|
+
* Implement `FromNDAV#from_ndav`, `ToNDAV#to_ndav` and `NDAV.register` them, and `NDAV.from_your_data` and `NDAV#to_your_data` are automatically derived
|
|
145
|
+
* When initializing NDAV object from your object, use `lifetime` keyword argument for `NDAV.new` effectively to prevent Ruby from GCing your object, which would lead to a dangling pointer
|
|
146
|
+
* When initializing your object from NDAV object, keep NDAV object alive to prevent Ruby from GCing NDAV object, which would lead to a dangling pointer, [ndav-numo-narray][], for instance, embeds the NDAV object in an instance variable
|
|
147
|
+
|
|
148
|
+
An advantage of NDAV over raw MemoryView is that you can write bridges in pure Ruby in most cases. It helps prototyping and experimentation. As an exception, I had to write C code for ndav-numo-narray because Numo::NArray only provides methods that access data by copying and does not directly expose its raw data pointer to Ruby API. However, in even such case, pure Ruby bridge remains a viable option for prototyping and experiments where a single initial copy is acceptable.
|
|
149
|
+
|
|
150
|
+
If you are a library author, I want you to consider making your library work with [MemoryView][] instead of creating an NDAV bridge.
|
|
151
|
+
|
|
152
|
+
FUTURE
|
|
153
|
+
------
|
|
154
|
+
|
|
155
|
+
If [MemoryView][] gets popular enough in the Ruby ecosystem, this library will end its role and will no longer be needed. I hope such future.
|
|
5
156
|
|
|
6
157
|
LICENSE
|
|
7
158
|
-------
|
|
8
159
|
|
|
9
160
|
BSD-2-Clause license. See LICENSE.txt file.
|
|
161
|
+
|
|
162
|
+
[MemoryView]: https://docs.ruby-lang.org/en/master/contributing/memory_view_md.html
|
|
163
|
+
[Numo::NArray]: https://ruby-numo.github.io/narray/
|
|
164
|
+
[Torch.rb]: https://github.com/ankane/torch.rb
|
|
165
|
+
[ONNX Runtime Ruby]: https://github.com/ankane/onnxruntime-ruby
|
|
166
|
+
[Red Arrow]: https://github.com/apache/arrow/tree/main/ruby
|
|
167
|
+
[Red Arrow Numo::NArray]: https://github.com/red-data-tools/red-arrow-numo-narray
|
|
168
|
+
[ndav/ffi]: https://gitlab.com/KitaitiMakoto/ndav/-/blob/main/lib/ndav/ffi.rb?ref_type=heads
|
|
169
|
+
[FFI Pointer]: https://github.com/ffi/ffi/wiki/Pointers
|
|
170
|
+
[ndav-numo-narray]: https://gitlab.com/KitaitiMakoto/ndav-numo-narray
|
|
171
|
+
[ndav-ort_value]: https://gitlab.com/KitaitiMakoto/ndav-ort_value
|
|
172
|
+
[ndav-torch-tensor]: https://gitlab.com/KitaitiMakoto/ndav-torch-tensor
|
|
173
|
+
[onnxruntime-torch-tensor]: https://gitlab.com/KitaitiMakoto/onnxruntime-torch-tensor
|
data/Rakefile
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
require "rake/clean"
|
|
2
2
|
require "rake/testtask"
|
|
3
3
|
require "rubygems/tasks"
|
|
4
|
+
require "yard"
|
|
4
5
|
|
|
5
6
|
DL_NAME = "ndav".ext(RbConfig::CONFIG["DLEXT"])
|
|
6
7
|
DL_BUILD_PATH = File.join("ext", DL_NAME)
|
|
7
8
|
DL_PATH = File.join("lib", DL_NAME)
|
|
8
9
|
|
|
9
10
|
SRC = FileList["ext/**.{h,c,rb}"]
|
|
11
|
+
CLEAN.include SRC.select {|src| src.end_with?(".o", ".so", ".bundle", ".dll") }
|
|
10
12
|
|
|
11
13
|
task default: :test
|
|
12
14
|
|
|
13
15
|
Rake::TestTask.new test: DL_PATH
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
Gem::Tasks.new
|
|
17
|
+
YARD::Rake::YardocTask.new
|
|
16
18
|
|
|
17
19
|
file DL_PATH => DL_BUILD_PATH do |t|
|
|
18
20
|
copy t.source, t.name
|
data/lib/ndav/converter.rb
CHANGED
data/ndav.gemspec
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
s.name = "ndav"
|
|
3
|
-
s.version = "0.0.
|
|
3
|
+
s.version = "0.0.4"
|
|
4
4
|
s.summary = "N-Dimensional Array View"
|
|
5
5
|
s.authors = ["Kitaiti Makoto"]
|
|
6
6
|
s.licenses = ["BSD-2-Clause"]
|
|
7
|
-
s.homepage = "https://gitlab.
|
|
7
|
+
s.homepage = "https://kitaitimakoto.gitlab.io/ndav"
|
|
8
|
+
s.metadata["source_code_uri"] = "https://gitlab.com/KitaitiMakoto/ndav"
|
|
8
9
|
|
|
9
10
|
s.files = Dir.chdir(__dir__) {`git ls-files -z`.split("\x0")}
|
|
10
11
|
s.extensions = ["ext/extconf.rb"]
|
|
@@ -20,4 +21,5 @@ Gem::Specification.new do |s|
|
|
|
20
21
|
s.add_development_dependency "rubygems-requirements-system"
|
|
21
22
|
s.add_development_dependency "red-arrow"
|
|
22
23
|
s.add_development_dependency "ffi"
|
|
24
|
+
s.add_development_dependency "yard"
|
|
23
25
|
end
|
data/test/test_ndav.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ndav
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kitaiti Makoto
|
|
@@ -149,6 +149,20 @@ dependencies:
|
|
|
149
149
|
- - ">="
|
|
150
150
|
- !ruby/object:Gem::Version
|
|
151
151
|
version: '0'
|
|
152
|
+
- !ruby/object:Gem::Dependency
|
|
153
|
+
name: yard
|
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
|
155
|
+
requirements:
|
|
156
|
+
- - ">="
|
|
157
|
+
- !ruby/object:Gem::Version
|
|
158
|
+
version: '0'
|
|
159
|
+
type: :development
|
|
160
|
+
prerelease: false
|
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - ">="
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '0'
|
|
152
166
|
executables: []
|
|
153
167
|
extensions:
|
|
154
168
|
- ext/extconf.rb
|
|
@@ -156,8 +170,10 @@ extra_rdoc_files: []
|
|
|
156
170
|
files:
|
|
157
171
|
- ".gitignore"
|
|
158
172
|
- ".gitlab-ci.yml"
|
|
173
|
+
- ".yardopts"
|
|
159
174
|
- Gemfile
|
|
160
175
|
- LICENSE.txt
|
|
176
|
+
- NDAV.png
|
|
161
177
|
- README.md
|
|
162
178
|
- Rakefile
|
|
163
179
|
- ext/extconf.rb
|
|
@@ -173,10 +189,11 @@ files:
|
|
|
173
189
|
- test/test_ffi.rb
|
|
174
190
|
- test/test_ndav.rb
|
|
175
191
|
- test/test_package.rb
|
|
176
|
-
homepage: https://gitlab.
|
|
192
|
+
homepage: https://kitaitimakoto.gitlab.io/ndav
|
|
177
193
|
licenses:
|
|
178
194
|
- BSD-2-Clause
|
|
179
|
-
metadata:
|
|
195
|
+
metadata:
|
|
196
|
+
source_code_uri: https://gitlab.com/KitaitiMakoto/ndav
|
|
180
197
|
rdoc_options: []
|
|
181
198
|
require_paths:
|
|
182
199
|
- lib
|