Skip to content

Commit 7ea849d

Browse files
committed
openvino: massive perf improvements via async api usage
1 parent e4f01f1 commit 7ea849d

File tree

3 files changed

+40
-67
lines changed

3 files changed

+40
-67
lines changed

plugins/openvino/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/openvino/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@
4848
"devDependencies": {
4949
"@scrypted/sdk": "file:../../sdk"
5050
},
51-
"version": "0.1.147"
51+
"version": "0.1.148"
5252
}

plugins/openvino/src/ov/__init__.py

Lines changed: 37 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
except:
2626
OpenVINOTextRecognition = None
2727

28-
predictExecutor = concurrent.futures.ThreadPoolExecutor(1, "OpenVINO-Predict")
29-
prepareExecutor = concurrent.futures.ThreadPoolExecutor(1, "OpenVINO-Prepare")
28+
predictExecutor = concurrent.futures.ThreadPoolExecutor(thread_name_prefix="OpenVINO-Predict")
29+
prepareExecutor = concurrent.futures.ThreadPoolExecutor(thread_name_prefix="OpenVINO-Prepare")
3030

3131
availableModels = [
3232
"Default",
@@ -48,10 +48,6 @@
4848
"scrypted_yolov9s_320",
4949
"scrypted_yolov9t_320",
5050
"scrypted_yolov8n_320",
51-
"ssd_mobilenet_v1_coco",
52-
"ssdlite_mobilenet_v2",
53-
"yolo-v3-tiny-tf",
54-
"yolo-v4-tiny-tf",
5551
]
5652

5753

@@ -245,6 +241,15 @@ def __init__(self, nativeId: str | None = None, forked: bool = False):
245241
self.storage.removeItem("precision")
246242
self.requestRestart()
247243

244+
self.infer_queue = ov.AsyncInferQueue(self.compiled_model)
245+
def callback(infer_request, future: asyncio.Future):
246+
try:
247+
output = infer_request.get_output_tensor(0)
248+
self.loop.call_soon_threadsafe(future.set_result, output)
249+
except Exception as e:
250+
self.loop.call_soon_threadsafe(future.set_exception, e)
251+
self.infer_queue.set_callback(callback)
252+
248253
print(
249254
"EXECUTION_DEVICES",
250255
self.compiled_model.get_property("EXECUTION_DEVICES"),
@@ -318,68 +323,38 @@ def get_input_format(self):
318323
return super().get_input_format()
319324

320325
async def detect_once(self, input: Image.Image, settings: Any, src_size, cvss):
321-
def predict(input_tensor):
322-
infer_request = self.compiled_model.create_infer_request()
323-
infer_request.set_input_tensor(input_tensor)
324-
output_tensors = infer_request.infer()
326+
async def predict(input_tensor):
327+
f = asyncio.Future(loop = self.loop)
328+
self.infer_queue.start_async(input_tensor, f)
325329

326-
objs = []
330+
output_tensors = await f
327331

328-
if self.scrypted_yolo:
329-
if self.scrypted_yolov10:
330-
return yolo.parse_yolov10(output_tensors[0][0])
331-
if self.scrypted_yolo_nas:
332-
return yolo.parse_yolo_nas([output_tensors[1], output_tensors[0]])
333-
return yolo.parse_yolov9(output_tensors[0][0])
334-
335-
if self.yolo:
336-
# index 2 will always either be 13 or 26
337-
# index 1 may be 13/26 or 255 depending on yolo 3 vs 4
338-
if infer_request.outputs[0].data.shape[2] == 13:
339-
out_blob = infer_request.outputs[0]
340-
else:
341-
out_blob = infer_request.outputs[1]
342-
343-
# 13 13
344-
objects = yolo.parse_yolo_region(
345-
out_blob.data,
346-
(input.width, input.height),
347-
(81, 82, 135, 169, 344, 319),
348-
self.sigmoid,
349-
)
332+
if not self.yolo:
333+
output = output_tensors
334+
for values in output.data[0][0]:
335+
valid, index, confidence, l, t, r, b = values
336+
if valid == -1:
337+
break
350338

351-
for r in objects:
352-
obj = Prediction(
353-
r["classId"],
354-
r["confidence"],
355-
Rectangle(r["xmin"], r["ymin"], r["xmax"], r["ymax"]),
356-
)
357-
objs.append(obj)
339+
def torelative(value: float):
340+
return value * self.model_dim
358341

359-
# what about output[1]?
360-
# 26 26
361-
# objects = yolo.parse_yolo_region(out_blob, (input.width, input.height), (,27, 37,58, 81,82))
342+
l = torelative(l)
343+
t = torelative(t)
344+
r = torelative(r)
345+
b = torelative(b)
362346

363-
return objs
364-
365-
output = infer_request.get_output_tensor(0)
366-
for values in output.data[0][0]:
367-
valid, index, confidence, l, t, r, b = values
368-
if valid == -1:
369-
break
370-
371-
def torelative(value: float):
372-
return value * self.model_dim
373-
374-
l = torelative(l)
375-
t = torelative(t)
376-
r = torelative(r)
377-
b = torelative(b)
347+
obj = Prediction(index - 1, confidence, Rectangle(l, t, r, b))
348+
objs.append(obj)
378349

379-
obj = Prediction(index - 1, confidence, Rectangle(l, t, r, b))
380-
objs.append(obj)
350+
return objs
381351

382-
return objs
352+
output = output_tensors.data
353+
if self.scrypted_yolov10:
354+
return yolo.parse_yolov10(output[0])
355+
if self.scrypted_yolo_nas:
356+
return yolo.parse_yolo_nas([output[1], output[0]])
357+
return yolo.parse_yolov9(output[0])
383358

384359
def prepare():
385360
# the input_tensor can be created with the shared_memory=True parameter,
@@ -414,9 +389,7 @@ def prepare():
414389
input_tensor = await asyncio.get_event_loop().run_in_executor(
415390
prepareExecutor, lambda: prepare()
416391
)
417-
objs = await asyncio.get_event_loop().run_in_executor(
418-
predictExecutor, lambda: predict(input_tensor)
419-
)
392+
objs = await predict(input_tensor)
420393

421394
except:
422395
traceback.print_exc()

0 commit comments

Comments
 (0)