onnxruntime 0.2.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa019e016dea45f795caba9b06e972edc6ae705d1599826fb17adf10af572851
4
- data.tar.gz: e0704039d0c8a94bf523dce7f707636493696ee92aa3f741d5b49ea62561e6d5
3
+ metadata.gz: b7d22851572b35128d1e2bbcc041b4989851e02354cace5389afc25855674b11
4
+ data.tar.gz: f1eee285e5dbff1fbf6de4e350560e3e386e1f4d26d53810f154cd16117e38e6
5
5
  SHA512:
6
- metadata.gz: 07dbde3621a15379bceb5b0fe7bfbb2bb581cb54a1b78d0f104f432396bac9086ab3c6186798fab52026515c8331074b35a68f6cce6748d3315e10bc375c3a9a
7
- data.tar.gz: ccc9ee30c55d0c8ae611b70adeab1b8707bc15bce42281ce05ca6bb9d4d6ff4953c2795a3931f4ff325401a3caea95d62e08243732d125cebda9dfb4587bdbc8
6
+ metadata.gz: f89ba13181bfcc8cdf35356efae175d0e2c7a0787a13af8d46788645046f057bce466e28566c0f2982f52893dbb7cc1553a741b1ca4923066e90c0a5fb230edf
7
+ data.tar.gz: 3843b9c1e5a9432d3b72ebb33498aaef0fb6edf8942a9f0b6794bed36fb95df67290e6c4385e19927e5404510d89ad8965b15de0a96246b7f1770c4fb01216f6
@@ -1,3 +1,29 @@
1
+ ## 0.3.3 (2020-06-17)
2
+
3
+ - Fixed segmentation fault on exit on Linux
4
+
5
+ ## 0.3.2 (2020-06-16)
6
+
7
+ - Fixed error with FFI 1.13.0+
8
+ - Added friendly graph optimization levels
9
+
10
+ ## 0.3.1 (2020-05-18)
11
+
12
+ - Updated ONNX Runtime to 1.3.0
13
+ - Added `custom_metadata_map` to model metadata
14
+
15
+ ## 0.3.0 (2020-03-11)
16
+
17
+ - Updated ONNX Runtime to 1.2.0
18
+ - Added model metadata
19
+ - Added `end_profiling` method
20
+ - Added support for loading from IO objects
21
+ - Improved `input` and `output` for `seq` and `map` types
22
+
23
+ ## 0.2.3 (2020-01-23)
24
+
25
+ - Updated ONNX Runtime to 1.1.1
26
+
1
27
  ## 0.2.2 (2019-12-24)
2
28
 
3
29
  - Added support for session options
@@ -1,4 +1,4 @@
1
- Copyright (c) 2019 Andrew Kane
1
+ Copyright (c) 2019-2020 Andrew Kane
2
2
  Datasets Copyright (c) Microsoft Corporation
3
3
 
4
4
  MIT License
data/README.md CHANGED
@@ -20,7 +20,7 @@ Load a model and make predictions
20
20
 
21
21
  ```ruby
22
22
  model = OnnxRuntime::Model.new("model.onnx")
23
- model.predict(x: [1, 2, 3])
23
+ model.predict({x: [1, 2, 3]})
24
24
  ```
25
25
 
26
26
  > Download pre-trained models from the [ONNX Model Zoo](https://github.com/onnx/models)
@@ -37,10 +37,16 @@ Get outputs
37
37
  model.outputs
38
38
  ```
39
39
 
40
+ Get metadata
41
+
42
+ ```ruby
43
+ model.metadata
44
+ ```
45
+
40
46
  Load a model from a string
41
47
 
42
48
  ```ruby
43
- byte_str = File.binread("model.onnx")
49
+ byte_str = StringIO.new("...")
44
50
  model = OnnxRuntime::Model.new(byte_str)
45
51
  ```
46
52
 
@@ -57,8 +63,8 @@ OnnxRuntime::Model.new(path_or_bytes, {
57
63
  enable_cpu_mem_arena: true,
58
64
  enable_mem_pattern: true,
59
65
  enable_profiling: false,
60
- execution_mode: :sequential,
61
- graph_optimization_level: nil,
66
+ execution_mode: :sequential, # :sequential or :parallel
67
+ graph_optimization_level: nil, # :none, :basic, :extended, or :all
62
68
  inter_op_num_threads: nil,
63
69
  intra_op_num_threads: nil,
64
70
  log_severity_level: 2,
@@ -19,7 +19,7 @@ module OnnxRuntime
19
19
  self.ffi_lib = [vendor_lib]
20
20
 
21
21
  def self.lib_version
22
- FFI.OrtGetApiBase[:GetVersionString].call
22
+ FFI.OrtGetApiBase[:GetVersionString].call.read_string
23
23
  end
24
24
 
25
25
  # friendlier error message
@@ -20,7 +20,7 @@ module OnnxRuntime
20
20
  layout \
21
21
  :CreateStatus, callback(%i[int string], :pointer),
22
22
  :GetErrorCode, callback(%i[pointer], :pointer),
23
- :GetErrorMessage, callback(%i[pointer], :string),
23
+ :GetErrorMessage, callback(%i[pointer], :pointer),
24
24
  :CreateEnv, callback(%i[int string pointer], :pointer),
25
25
  :CreateEnvWithCustomLogger, callback(%i[], :pointer),
26
26
  :EnableTelemetryEvents, callback(%i[pointer], :pointer),
@@ -119,7 +119,30 @@ module OnnxRuntime
119
119
  :ReleaseTypeInfo, callback(%i[pointer], :void),
120
120
  :ReleaseTensorTypeAndShapeInfo, callback(%i[pointer], :void),
121
121
  :ReleaseSessionOptions, callback(%i[pointer], :void),
122
- :ReleaseCustomOpDomain, callback(%i[pointer], :void)
122
+ :ReleaseCustomOpDomain, callback(%i[pointer], :void),
123
+ :GetDenotationFromTypeInfo, callback(%i[], :pointer),
124
+ :CastTypeInfoToMapTypeInfo, callback(%i[pointer pointer], :pointer),
125
+ :CastTypeInfoToSequenceTypeInfo, callback(%i[pointer pointer], :pointer),
126
+ :GetMapKeyType, callback(%i[pointer pointer], :pointer),
127
+ :GetMapValueType, callback(%i[pointer pointer], :pointer),
128
+ :GetSequenceElementType, callback(%i[pointer pointer], :pointer),
129
+ :ReleaseMapTypeInfo, callback(%i[pointer], :void),
130
+ :ReleaseSequenceTypeInfo, callback(%i[pointer], :void),
131
+ :SessionEndProfiling, callback(%i[pointer pointer pointer], :pointer),
132
+ :SessionGetModelMetadata, callback(%i[pointer pointer], :pointer),
133
+ :ModelMetadataGetProducerName, callback(%i[pointer pointer pointer], :pointer),
134
+ :ModelMetadataGetGraphName, callback(%i[pointer pointer pointer], :pointer),
135
+ :ModelMetadataGetDomain, callback(%i[pointer pointer pointer], :pointer),
136
+ :ModelMetadataGetDescription, callback(%i[pointer pointer pointer], :pointer),
137
+ :ModelMetadataLookupCustomMetadataMap, callback(%i[pointer pointer pointer pointer], :pointer),
138
+ :ModelMetadataGetVersion, callback(%i[pointer pointer], :pointer),
139
+ :ReleaseModelMetadata, callback(%i[pointer], :void),
140
+ :CreateEnvWithGlobalThreadPools, callback(%i[], :pointer),
141
+ :DisablePerSessionThreads, callback(%i[], :pointer),
142
+ :CreateThreadingOptions, callback(%i[], :pointer),
143
+ :ReleaseThreadingOptions, callback(%i[], :pointer),
144
+ :ModelMetadataGetCustomMetadataMapKeys, callback(%i[pointer pointer pointer pointer], :pointer),
145
+ :AddFreeDimensionOverrideByName, callback(%i[], :pointer)
123
146
  end
124
147
 
125
148
  class ApiBase < ::FFI::Struct
@@ -127,7 +150,7 @@ module OnnxRuntime
127
150
  # to prevent "unable to resolve type" error on Ubuntu
128
151
  layout \
129
152
  :GetApi, callback(%i[uint32], Api.by_ref),
130
- :GetVersionString, callback(%i[], :string)
153
+ :GetVersionString, callback(%i[], :pointer)
131
154
  end
132
155
 
133
156
  attach_function :OrtGetApiBase, %i[], ApiBase.by_ref
@@ -10,18 +10,17 @@ module OnnxRuntime
10
10
  check_status api[:EnableMemPattern].call(session_options.read_pointer) if enable_mem_pattern
11
11
  check_status api[:EnableProfiling].call(session_options.read_pointer, "onnxruntime_profile_") if enable_profiling
12
12
  if execution_mode
13
- mode =
14
- case execution_mode
15
- when :sequential
16
- 0
17
- when :parallel
18
- 1
19
- else
20
- raise ArgumentError, "Invalid execution mode"
21
- end
13
+ execution_modes = {sequential: 0, parallel: 1}
14
+ mode = execution_modes[execution_mode]
15
+ raise ArgumentError, "Invalid execution mode" unless mode
22
16
  check_status api[:SetSessionExecutionMode].call(session_options.read_pointer, mode)
23
17
  end
24
- check_status api[:SetSessionGraphOptimizationLevel].call(session_options.read_pointer, graph_optimization_level) if graph_optimization_level
18
+ if graph_optimization_level
19
+ optimization_levels = {none: 0, basic: 1, extended: 2, all: 99}
20
+ # TODO raise error in 0.4.0
21
+ level = optimization_levels[graph_optimization_level] || graph_optimization_level
22
+ check_status api[:SetSessionGraphOptimizationLevel].call(session_options.read_pointer, level)
23
+ end
25
24
  check_status api[:SetInterOpNumThreads].call(session_options.read_pointer, inter_op_num_threads) if inter_op_num_threads
26
25
  check_status api[:SetIntraOpNumThreads].call(session_options.read_pointer, intra_op_num_threads) if intra_op_num_threads
27
26
  check_status api[:SetSessionLogSeverityLevel].call(session_options.read_pointer, log_severity_level) if log_severity_level
@@ -31,18 +30,27 @@ module OnnxRuntime
31
30
 
32
31
  # session
33
32
  @session = ::FFI::MemoryPointer.new(:pointer)
34
- path_or_bytes = path_or_bytes.to_str
33
+ from_memory =
34
+ if path_or_bytes.respond_to?(:read)
35
+ path_or_bytes = path_or_bytes.read
36
+ true
37
+ else
38
+ path_or_bytes = path_or_bytes.to_str
39
+ path_or_bytes.encoding == Encoding::BINARY
40
+ end
35
41
 
36
42
  # fix for Windows "File doesn't exist"
37
- if Gem.win_platform? && path_or_bytes.encoding != Encoding::BINARY
43
+ if Gem.win_platform? && !from_memory
38
44
  path_or_bytes = File.binread(path_or_bytes)
45
+ from_memory = true
39
46
  end
40
47
 
41
- if path_or_bytes.encoding == Encoding::BINARY
48
+ if from_memory
42
49
  check_status api[:CreateSessionFromArray].call(env.read_pointer, path_or_bytes, path_or_bytes.bytesize, session_options.read_pointer, @session)
43
50
  else
44
51
  check_status api[:CreateSession].call(env.read_pointer, path_or_bytes, session_options.read_pointer, @session)
45
52
  end
53
+ ObjectSpace.define_finalizer(self, self.class.finalize(@session))
46
54
 
47
55
  # input info
48
56
  allocator = ::FFI::MemoryPointer.new(:pointer)
@@ -73,6 +81,8 @@ module OnnxRuntime
73
81
  check_status api[:SessionGetOutputTypeInfo].call(read_pointer, i, typeinfo)
74
82
  @outputs << {name: name_ptr.read_pointer.read_string}.merge(node_info(typeinfo))
75
83
  end
84
+ ensure
85
+ # release :SessionOptions, session_options
76
86
  end
77
87
 
78
88
  # TODO support logid
@@ -98,6 +108,58 @@ module OnnxRuntime
98
108
  output_names.size.times.map do |i|
99
109
  create_from_onnx_value(output_tensor[i].read_pointer)
100
110
  end
111
+ ensure
112
+ release :RunOptions, run_options
113
+ if input_tensor
114
+ input_feed.size.times do |i|
115
+ release :Value, input_tensor[i]
116
+ end
117
+ end
118
+ end
119
+
120
+ def modelmeta
121
+ keys = ::FFI::MemoryPointer.new(:pointer)
122
+ num_keys = ::FFI::MemoryPointer.new(:int64_t)
123
+ description = ::FFI::MemoryPointer.new(:string)
124
+ domain = ::FFI::MemoryPointer.new(:string)
125
+ graph_name = ::FFI::MemoryPointer.new(:string)
126
+ producer_name = ::FFI::MemoryPointer.new(:string)
127
+ version = ::FFI::MemoryPointer.new(:int64_t)
128
+
129
+ metadata = ::FFI::MemoryPointer.new(:pointer)
130
+ check_status api[:SessionGetModelMetadata].call(read_pointer, metadata)
131
+
132
+ custom_metadata_map = {}
133
+ check_status = api[:ModelMetadataGetCustomMetadataMapKeys].call(metadata.read_pointer, @allocator.read_pointer, keys, num_keys)
134
+ num_keys.read(:int64_t).times do |i|
135
+ key = keys.read_pointer[i * ::FFI::Pointer.size].read_pointer.read_string
136
+ value = ::FFI::MemoryPointer.new(:string)
137
+ check_status api[:ModelMetadataLookupCustomMetadataMap].call(metadata.read_pointer, @allocator.read_pointer, key, value)
138
+ custom_metadata_map[key] = value.read_pointer.read_string
139
+ end
140
+
141
+ check_status api[:ModelMetadataGetDescription].call(metadata.read_pointer, @allocator.read_pointer, description)
142
+ check_status api[:ModelMetadataGetDomain].call(metadata.read_pointer, @allocator.read_pointer, domain)
143
+ check_status api[:ModelMetadataGetGraphName].call(metadata.read_pointer, @allocator.read_pointer, graph_name)
144
+ check_status api[:ModelMetadataGetProducerName].call(metadata.read_pointer, @allocator.read_pointer, producer_name)
145
+ check_status api[:ModelMetadataGetVersion].call(metadata.read_pointer, version)
146
+
147
+ {
148
+ custom_metadata_map: custom_metadata_map,
149
+ description: description.read_pointer.read_string,
150
+ domain: domain.read_pointer.read_string,
151
+ graph_name: graph_name.read_pointer.read_string,
152
+ producer_name: producer_name.read_pointer.read_string,
153
+ version: version.read(:int64_t)
154
+ }
155
+ ensure
156
+ release :ModelMetadata, metadata
157
+ end
158
+
159
+ def end_profiling
160
+ out = ::FFI::MemoryPointer.new(:string)
161
+ check_status api[:SessionEndProfiling].call(read_pointer, @allocator.read_pointer, out)
162
+ out.read_pointer.read_string
101
163
  end
102
164
 
103
165
  private
@@ -181,6 +243,8 @@ module OnnxRuntime
181
243
  output_tensor_size = api[:GetTensorShapeElementCount].call(typeinfo.read_pointer, out_size)
182
244
  output_tensor_size = read_size_t(out_size)
183
245
 
246
+ release :TensorTypeAndShapeInfo, typeinfo
247
+
184
248
  # TODO support more types
185
249
  type = FFI::TensorElementDataType[type]
186
250
  arr =
@@ -213,6 +277,7 @@ module OnnxRuntime
213
277
  check_status api[:GetValue].call(out_ptr, 1, @allocator.read_pointer, map_values)
214
278
  check_status api[:GetTensorTypeAndShape].call(map_keys.read_pointer, type_shape)
215
279
  check_status api[:GetTensorElementType].call(type_shape.read_pointer, elem_type)
280
+ release :TensorTypeAndShapeInfo, type_shape
216
281
 
217
282
  # TODO support more types
218
283
  elem_type = FFI::TensorElementDataType[elem_type.read_int]
@@ -239,7 +304,7 @@ module OnnxRuntime
239
304
 
240
305
  def check_status(status)
241
306
  unless status.null?
242
- message = api[:GetErrorMessage].call(status)
307
+ message = api[:GetErrorMessage].call(status).read_string
243
308
  api[:ReleaseStatus].call(status)
244
309
  raise OnnxRuntime::Error, message
245
310
  end
@@ -253,6 +318,7 @@ module OnnxRuntime
253
318
  case type
254
319
  when :tensor
255
320
  tensor_info = ::FFI::MemoryPointer.new(:pointer)
321
+ # don't free tensor_info
256
322
  check_status api[:CastTypeInfoToTensorInfo].call(typeinfo.read_pointer, tensor_info)
257
323
 
258
324
  type, shape = tensor_type_and_shape(tensor_info)
@@ -261,22 +327,39 @@ module OnnxRuntime
261
327
  shape: shape
262
328
  }
263
329
  when :sequence
264
- # TODO show nested
330
+ sequence_type_info = ::FFI::MemoryPointer.new(:pointer)
331
+ check_status api[:CastTypeInfoToSequenceTypeInfo].call(typeinfo.read_pointer, sequence_type_info)
332
+ nested_type_info = ::FFI::MemoryPointer.new(:pointer)
333
+ check_status api[:GetSequenceElementType].call(sequence_type_info.read_pointer, nested_type_info)
334
+ v = node_info(nested_type_info)[:type]
335
+
265
336
  {
266
- type: "seq",
337
+ type: "seq(#{v})",
267
338
  shape: []
268
339
  }
269
340
  when :map
270
- # TODO show nested
341
+ map_type_info = ::FFI::MemoryPointer.new(:pointer)
342
+ check_status api[:CastTypeInfoToMapTypeInfo].call(typeinfo.read_pointer, map_type_info)
343
+
344
+ # key
345
+ key_type = ::FFI::MemoryPointer.new(:int)
346
+ check_status api[:GetMapKeyType].call(map_type_info.read_pointer, key_type)
347
+ k = FFI::TensorElementDataType[key_type.read_int]
348
+
349
+ # value
350
+ value_type_info = ::FFI::MemoryPointer.new(:pointer)
351
+ check_status api[:GetMapValueType].call(map_type_info.read_pointer, value_type_info)
352
+ v = node_info(value_type_info)[:type]
353
+
271
354
  {
272
- type: "map",
355
+ type: "map(#{k},#{v})",
273
356
  shape: []
274
357
  }
275
358
  else
276
359
  unsupported_type("ONNX", type)
277
360
  end
278
361
  ensure
279
- api[:ReleaseTypeInfo].call(typeinfo.read_pointer)
362
+ release :TypeInfo, typeinfo
280
363
  end
281
364
 
282
365
  def tensor_type_and_shape(tensor_info)
@@ -307,7 +390,24 @@ module OnnxRuntime
307
390
  end
308
391
 
309
392
  def api
310
- @api ||= FFI.OrtGetApiBase[:GetApi].call(1)
393
+ self.class.api
394
+ end
395
+
396
+ def release(*args)
397
+ self.class.release(*args)
398
+ end
399
+
400
+ def self.api
401
+ @api ||= FFI.OrtGetApiBase[:GetApi].call(3)
402
+ end
403
+
404
+ def self.release(type, pointer)
405
+ api[:"Release#{type}"].call(pointer.read_pointer) if pointer && !pointer.null?
406
+ end
407
+
408
+ def self.finalize(session)
409
+ # must use proc instead of stabby lambda
410
+ proc { release :Session, session }
311
411
  end
312
412
 
313
413
  def env
@@ -316,7 +416,7 @@ module OnnxRuntime
316
416
  @@env ||= begin
317
417
  env = ::FFI::MemoryPointer.new(:pointer)
318
418
  check_status api[:CreateEnv].call(3, "Default", env)
319
- at_exit { api[:ReleaseEnv].call(env.read_pointer) }
419
+ at_exit { release :Env, env }
320
420
  # disable telemetry
321
421
  # https://github.com/microsoft/onnxruntime/blob/master/docs/Privacy.md
322
422
  check_status api[:DisableTelemetryEvents].call(env)
@@ -22,5 +22,9 @@ module OnnxRuntime
22
22
  def outputs
23
23
  @session.outputs
24
24
  end
25
+
26
+ def metadata
27
+ @session.modelmeta
28
+ end
25
29
  end
26
30
  end
@@ -1,3 +1,3 @@
1
1
  module OnnxRuntime
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.3"
3
3
  end
Binary file
Binary file
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: onnxruntime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-24 00:00:00.000000000 Z
11
+ date: 2020-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -106,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
106
  - !ruby/object:Gem::Version
107
107
  version: '0'
108
108
  requirements: []
109
- rubygems_version: 3.0.3
109
+ rubygems_version: 3.1.2
110
110
  signing_key:
111
111
  specification_version: 4
112
112
  summary: High performance scoring engine for ML models