Commit e14e5737 authored by cuongvt2's avatar cuongvt2

add branch & tool, example

parent 615e3857
2021-08-23 21:24:21,465 - INFO - udp_rate_limiter.py:525 - Setting UDP rate to 400000.0 Kbits for 10.0.0.93:32401
2021-08-23 21:24:26,682 - ERROR - udp_rate_limiter.py:184 - RTNETLINK answers: File exists
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
2021-08-21 19:44:58,002 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-21 19:58:52,510 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-21 19:59:41,572 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-21 19:59:55,012 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-21 20:01:05,296 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-21 20:01:46,777 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-21 20:02:53,863 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-21 22:57:03,084 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-22 11:51:45,552 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-22 11:52:44,969 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-22 11:52:56,664 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-22 11:53:48,143 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 15:06:27,518 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 15:07:31,106 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 15:19:06,226 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 15:22:32,602 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 15:24:07,830 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 15:24:58,785 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 15:28:54,779 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 15:29:10,537 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 15:32:28,607 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 19:46:08,289 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 19:48:13,809 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 19:52:07,580 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 19:53:05,957 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 20:08:51,371 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 20:14:05,698 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 20:15:03,539 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 20:16:18,598 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 20:21:18,399 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 20:51:15,420 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 20:52:14,802 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 20:53:11,441 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 20:59:13,610 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 21:26:00,521 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 22:12:07,459 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 22:15:19,810 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-08-23 22:19:45,077 - INFO - base_utils.py:55 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:04:41,384 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:10:44,654 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:11:03,048 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:19:24,220 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:31:44,528 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:33:17,463 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:37:26,225 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:38:28,359 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:40:12,065 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:40:33,552 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:46:16,021 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:47:48,122 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:52:54,029 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:54:34,085 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:54:48,953 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:58:13,721 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:58:20,721 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:58:25,289 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:58:43,949 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 22:59:46,540 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:00:05,784 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:00:30,832 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:00:34,468 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:01:17,229 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:01:24,204 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:01:32,364 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:01:36,661 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:01:45,091 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:02:13,482 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:02:18,351 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:03:18,378 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:03:23,262 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:04:25,541 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:04:30,556 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:05:20,402 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:05:25,210 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:06:29,597 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:06:34,456 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:07:27,165 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:07:32,051 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:08:55,415 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:09:00,453 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:09:56,628 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:10:01,510 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:12:27,741 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:12:32,428 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:18:09,370 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:18:19,383 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:19:37,136 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:19:41,962 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:22:47,343 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
2021-09-26 23:22:52,314 - INFO - base_utils.py:54 - (hailo) Running command 'udp-rate-limiter' with 'hailortcli'
#!/usr/bin/env python3
'''
A Simple Python example showing how to:
1. Load a compiled network (HEF) to a Hailo-8 device
2. setup the device for running inference
3. Streaming in images to the device
4. Reading out results
'''
from __future__ import division
import os
import time
import argparse as ap
import numpy as np
from zenlog import logging as logger
from colorama import Fore
from tqdm import trange
import ctypes
from multiprocessing import Process, Value, Array
from hailo_platform import (HEF, PcieDevice, EthernetDevice,HailoStreamInterface, InferVStreams, ConfigureParams,
InputVStreamParams, OutputVStreamParams, InputVStreams, OutputVStreams, FormatType)
import yolov5_postprocess
import cv2
from past.utils import old_div
import tensorflow as tf
TOTAL_IMAGE=1200
g_img2 = []
g_cap = cv2.VideoCapture("./full_mov_slow.mp4")
for i in range(0,TOTAL_IMAGE):
g_ret, g_imgs = g_cap.read()
g_imgs = cv2.resize(g_imgs, (640,640), cv2.IMREAD_UNCHANGED)
g_img2.append(g_imgs)
def get_coco_name_from_int(cls):
return {
0: "__background__",
1: "person",
2: "bicycle",
3: "car",
4: "motorcycle",
5: "airplane",
6: "bus",
7: "train",
8: "truck",
9: "boat",
10: "traffic light",
11: "fire hydrant",
12: "stop sign",
13: "parking meter",
14: "bench",
15: "bird",
16: "cat",
17: "dog",
18: "horse",
19: "sheep",
20: "cow",
21: "elephant",
22: "bear",
23: "zebra",
24: "giraffe",
25: "backpack",
26: "umbrella",
27: "handbag",
28: "tie",
29: "suitcase",
30: "frisbee",
31: "skis",
32: "snowboard",
33: "sports ball",
34: "kite",
35: "baseball bat",
36: "baseball glove",
37: "skateboard",
38: "surfboard",
39: "tennis racket",
40: "bottle",
41: "wine glass",
42: "cup",
43: "fork",
44: "knife",
45: "spoon",
46: "bowl",
47: "banana",
48: "apple",
49: "sandwich",
50: "orange",
51: "broccoli",
52: "carrot",
53: "hot dog",
54: "pizza",
55: "donut",
56: "cake",
57: "chair",
58: "couch",
59: "potted plant",
60: "bed",
61: "dining table",
62: "toilet",
63: "tv",
64: "laptop",
65: "mouse",
66: "remote",
67: "keyboard",
68: "cell phone",
69: "microwave",
70: "oven",
71: "toaster",
72: "sink",
73: "refrigerator",
74: "book",
75: "clock",
76: "vase",
77: "scissors",
78: "teddy bear",
79: "hair drier",
80: "toothbrush"
}.get(cls, "None")
# https://github.com/anishathalye/imagenet-simple-labels
IMAGENET_LBL_FILE = 'imagenet-simple-labels.json'
INPUT_IMAGE_DIR = './images_net'
HEF_FILE = 'yolov5m.hef'
def arg_prep():
parser = ap.ArgumentParser()
parser.add_argument('--hef', help='Point to the HEF')
parser.add_argument('--mode', help='Choose the communication mode [hw-only|full]', type=str, default='full')
parser.add_argument('--iterations', help='How many repeasts on the picture stream (Default:100)', type=int, default=TOTAL_IMAGE)
parser.add_argument('--power', help='Enable Power measurement', default=False, action='store_true')
parser.add_argument('--source', help='Specify image or video source', default=None)
parser.add_argument('--interface', help='Specify the physical interface, pcie or udp', default='pcie')
parser.add_argument('--fps', help='Emulate a source FPS', type=int, default='0')
# parser.add_argument('--ip', help='Set the IP of the Hailo device', type=str, default='10.0.0.100')
args = parser.parse_args()
return args
def _recv_process(activated_network, num_frames, end_time, recv_times):
global g_img2
global g_start
thr=0.2;
vstreams_params = OutputVStreamParams.make_from_network_group(activated_network)
logger.info('RECV process Full Started')
with OutputVStreams(activated_network, vstreams_params) as vstreams:
#output_streams = {name : recv.get_output_by_name(name) for name in activated_network.target.sorted_output_layer_names}
# [logger.info("Output: {}".format(name)) for name in activated_network.target.sorted_output_layer_names]
outputs = dict()
for y in range(num_frames):
x=0
for vstream in vstreams:
#data = vstream.recv()
#print("recv frame", data.shape. vstreams_params.name())
#if x<2:
#print("recv frame", outputs[x].shape)
if x==2:
#print("recv frame", data.shape. vstreams_params.name())
#print("recv frame")
detections = yolov5_postprocess.run(vstream.recv(), outputs[0], outputs[1], 0.0, 0, 0.0, 0.003921144641935825, 0.0, 0.00392112368717789659, 0.2)
if y%6 == 0:
num_detections = int(detections.shape[0])
classes = detections[:, 4].astype("int32")
#for i in classes:
# print(get_coco_name_from_int(int(i)), end =" ")
#print("")
boxes = 640*(np.reshape(np.array([x[:4] for x in detections]), (-1, 4)))
fpsl = int(y/(time.time() - g_start))
strl = "FPS: " + str(fpsl)
for j in range(0,num_detections):
cv2.rectangle(g_img2[y], ((int(boxes[j][1]), int(boxes[j][0]))), ((int(boxes[j][3]), int(boxes[j][2]))), (80,220,80), 3)
cv2.putText(g_img2[y], strl, (50, 50), cv2.FONT_HERSHEY_PLAIN, 2.0, (0,0,255), 4);
cv2.imshow("Image", g_img2[y])
cv2.waitKey(1)
else:
outputs[x] = vstream.recv()
x=x+1
'''
for i in trange(iterations, desc='INFO:Recv...', position=0, bar_format="{l_bar}%s{bar}%s{r_bar}" % (Fore.GREEN, Fore.RESET)):
for name, output_stream in output_streams.items():
outputs[x] = output_stream.recv()
x=x+1
if x==3:
detections = yolov5_postprocess.run(outputs[0], outputs[1], outputs[2], 0.0, 0, 0.0, 0.003921144641935825, 0.0, 0.00392112368717789659, 0.2)
num_detections = int(detections.shape[0])
classes = detections[:, 4].astype("int32")
for i in classes:
print(get_coco_name_from_int(int(i)), end =" ")
print("")
boxes = 640*(np.reshape(np.array([x[:4] for x in detections]), (-1, 4)))
fpsl = int(y/(time.time() - g_start))
strl = "FPS: " + str(fpsl)
for j in range(0,num_detections):
cv2.rectangle(g_img2[y], ((int(boxes[j][1]), int(boxes[j][0]))), ((int(boxes[j][3]), int(boxes[j][2]))), (80,220,80), 3)
cv2.putText(g_img2[y], strl, (50, 50), cv2.FONT_HERSHEY_PLAIN, 2.0, (0,0,255), 4);
cv2.imshow("Image", g_img2[y])
cv2.waitKey(1)
x=0
y+=1
'''
end_time.value = time.time()
logger.info("[{}] Finished Recving {} frames".format(end_time.value, num_frames))
def _send_process(configured_network, num_frames, input_shapes, fps, send_times):
global g_img2
vstreams_params = InputVStreamParams.make_from_network_group(configured_network)
with InputVStreams(configured_network, vstreams_params) as vstreams:
#input_streams = {input_name : send_pipeline.get_input_by_name(input_name) for input_name, shape in input_shapes.items()}
#data_per_input = {input_name : np.random.randint(256, size=(1,) + shape, dtype=np.uint8) for input_name, shape in input_shapes.items()}
[logger.info("Input: {} with shape: {}".format(name, shape)) for name, shape in input_shapes.items()]
if fps>0.0:
logger.info("Emulate source FPS: {}".format(fps))
cap = cv2.VideoCapture("./full_mov_slow.mp4")
local_send_times = list()
for i in range(num_frames):
for vstream in vstreams:
#print("send frame", buff.shape)
#ret, g_img2[i] = cap.read()
#g_img2[i] = cv2.resize(cap.read()[1], (640,640), cv2.IMREAD_UNCHANGED)
#image_np = np.expand_dims(np.asarray(cv2.resize(cap.read()[1], (640,640), cv2.IMREAD_UNCHANGED)), axis=0)
vstream.send(np.expand_dims(np.asarray(cv2.resize(cap.read()[1], (640,640), cv2.IMREAD_UNCHANGED)), axis=0))
'''
i=0
while i<TOTAL_IMAGE:
ret, g_img2[i] = cap.read()
g_img2[i] = cv2.resize(g_img2[i], (640,640), cv2.IMREAD_UNCHANGED)
image_np = np.expand_dims(np.asarray(g_img2[i]), axis=0)
i+=1
try:
for name, input_stream in input_streams.items():
input_stream.send(image_np)
except HailoRTException as e:
if e.args and '0x4' in e.args and i>iterations*0.9:
pass
'''
def run_hef(target, hef, iterations, streaming_mode, fps):
global g_start
'''
Receive a hef buffer, and a target device, and run ImageNet classifcation
on a predefined directory containing JPG images of size 224x224
'''
logger.info("Loading HEF to target")
# Configure network groups
configure_params = ConfigureParams.create_from_hef(hef=hef, interface=HailoStreamInterface.ETH)
network_groups = target.configure(hef, configure_params)
network_group = network_groups[0]
network_group_params = network_group.create_params()
# Explanation about definition of the streams-
# quantized - Whether to scale and zero-point the values from 0-255, if the input is uint8 can use as-is
# format_type - The input type UINT8, UINT16, FLOAT32, AUTO
#print("##################### quantized ########################", quantized)
input_streams_params = InputVStreamParams.make_from_network_group(network_group, quantized=False, format_type=FormatType.UINT8)
output_streams_params = OutputVStreamParams.make_from_network_group(network_group, quantized=True, format_type=FormatType.UINT8)
with network_group.activate(network_group_params) as activated_network:
send_times = Array(ctypes.c_double, [0.0] * 100)
recv_times = Array(ctypes.c_double, [0.0] * 100)
end_time = Value(ctypes.c_double, 0.0)
input_shapes = {layer_info.name: layer_info.shape for layer_info in hef.get_input_layers_info()}
recv_process = Process(target=_recv_process, args=(network_group, iterations, end_time, recv_times))
send_process = Process(target=_send_process, args=(network_group, iterations, input_shapes, fps, send_times))
start = time.time()
g_start = start
try:
logger.info("[{}] Starting Inference".format(start))
send_process.start()
recv_process.start()
except KeyboardInterrupt:
logger.info("Interrupted by the user, stopping..")
send_process.terminate()
recv_process.terminate()
except Exception:
logger.info("Exception happened, stopping..")
send_process.terminate()
recv_process.terminate()
finally:
send_process.join()
recv_process.join()
logger.info("[{}] Finished Inference".format(end_time.value))
latencies = [r-t for r,t in zip(recv_times, send_times)]
logger.info("-------------------------------------")
logger.info(" Infer Time: {:.3f} sec".format(end_time.value - start))
logger.info(" Average FPS: {:.3f}".format(iterations/(end_time.value - start)))
logger.info(" Average Latency: {:.3f} ms".format(np.average(latencies) * 1000.0))
logger.info("-------------------------------------")
def main():
logger.basicConfig(level=logger.INFO)
args = arg_prep()
logger.info('Reading HEF from: {}'.format(args.hef))
hef = HEF(args.hef)
# The target can be used as a context manager ("with" statement) to ensure it's released on time.
# Here it's avoided for the sake of simplicity
remote_ip = '10.0.0.93'
with EthernetDevice(remote_ip) as target:
run_hef(target, hef, args.iterations, args.mode, args.fps)
#target = PcieDevice(hw_arch='hailo8')
#with PcieDevice() as target:
# run_hef(target, hef, args.iterations, args.mode, args.fps)
if __name__ == "__main__":
main()
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['run.py'],
pathex=['/home/avim/repos_3_7_1/customer-support2_work/tools/HailoRT/python_example_video_140fps'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
[],
exclude_binaries=True,
name='run',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True,
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None )
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='run')
#
- video file (~95MB): full_mov_slow.mp4
\ No newline at end of file
. /home/avim/SDK/Latest/platform/hailo_platform_venv/bin/activate
pip3 install zenlog
pip3 install colorama
pip3 install pillow
pip3 install opencv-python
pip3 install tensorflow
hailo udp-limiter reset --board-ip 10.0.0.93
hailo udp-limiter set --board-ip=10.0.0.93 --kbit-rate=400000
sudo /home/avim/SDK/Latest/platform/scripts/configure_ethernet_buffers.sh eno2
./run.py --hef yolov5m.hef
cmake_minimum_required(VERSION 3.0.0)
# Setting the ARCH if not provided
if (NOT DEFINED ARCH)
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch_from_cmd)
string(STRIP ${arch_from_cmd} arch_from_cmd)
set(ARCH ${arch_from_cmd})
endif()
set(HAILORT_ROOT $ENV{HAILORT_ROOT})
set(HAILORT_VER $ENV{HAILORT_VER})
set(HAILORT_LIB ${HAILORT_ROOT}/../lib/linux.${ARCH}.release/libhailort.so.${HAILORT_VER})
set(HAILORT_LIB ${HAILORT_ROOT}/lib/${ARCH}/libhailort.so.${HAILORT_VER})
set(HAILORT_INCLUDE_DIR ${HAILORT_ROOT}/include)
message(STATUS ${HAILORT_LIB})
message(STATUS ${HAILORT_INCLUDE_DIR})
set(COMPILE_OPTIONS -Wall -g -O0)
find_package(Threads)
foreach(target example-hef example)
add_executable(${target}.${HAILORT_VER} "${target}.c")
include_directories(${HAILORT_INCLUDE_DIR})
target_compile_options(${target}.${HAILORT_VER} PRIVATE ${COMPILE_OPTIONS})
target_link_libraries(${target}.${HAILORT_VER} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${target}.${HAILORT_VER} ${HAILORT_LIB})
endforeach(target)
To Compile all targets to all architectures (x86, armv7l, aarch64):
`build.sh`
\ No newline at end of file
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file example.c
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include <net/if.h>
#include <pthread.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <linux/limits.h>
#include <time.h>
#include <hailo/hailort.h>
#include "example_utils.h"
#define NOF_STREAMS (15)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
#define DEFAULT_POWER_MEASUREMENT_DELAY_MS (1100 / 1000.0 * 256 * 2 * 1.2)
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
unsigned int actual_measurments;
void* _send_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
uint32_t input_size = write_args->frame_hw_size;
uint8_t* src_data = (uint8_t*)malloc(input_size);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
struct timespec ts;
float delay = 0.0;
printf("-I- Send Thread stated TX frame size:%d\n", input_size);
if (NULL == src_data) {
printf("-E- Failed to allocate buffers\n");
status = HAILO_OUT_OF_HOST_MEMORY;
goto l_release_buffers;
}
for(size_t i = 0; i < input_size; i++) {
src_data[i] = (uint8_t)(rand() % 256);
}
flag_100 = (uint32_t)write_args->num_images / 10;
if (flag_100==0)
flag_100 = 1;
if (write_args->source_fps > 0) {
delay = 1000000.0 / write_args->source_fps;
printf(CYAN);
printf("-I- Setting the delay to %f usec\n", delay);
printf(RESET);
}
for (uint32_t i = 1; i <= (uint32_t)write_args->num_images; i++) {
if (delay > 0.0)
usleep(delay);
if ((i % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] Send frame [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, i, write_args->num_images, src_data[0], src_data[1], src_data[2], src_data[3]);
sent_clock_t[lat_counter++] = ts;
}
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream, src_data, 0, input_size);
if (status != HAILO_SUCCESS) {
printf("-E- hailo_stream_sync_write_all_raw_buffer failed: %d\n",status);
break;
}
}
l_release_buffers:
FREE(src_data);
write_args->status = status;
return NULL;
}
double get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (double)(ts.tv_nsec / 1000000.0));
return result;
}
void* _recv_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
recv_thread_args_t *recv_args = (recv_thread_args_t *)args;
uint32_t datasize = recv_args->frame_hw_size;
struct timespec ts;
uint8_t *dst_data = (uint8_t*)malloc(datasize);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
printf("-I- Recv thread %d started, datasize: %d\n", recv_args->tid, datasize);
flag_100 = (uint32_t)recv_args->num_images / 10;
if (flag_100==0)
flag_100 = 1;
actual_measurments = 0;
for (uint32_t j = 1; j <= (uint32_t)recv_args->num_images; j++) {
status = hailo_stream_sync_read_all_raw_buffer(recv_args->output_stream, dst_data, 0, datasize);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_read_all_raw_buffer failed");
if ((j % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Recv [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, recv_args->tid, j, recv_args->num_images, dst_data[0], dst_data[1], dst_data[2], dst_data[3]);
recv_clock_t[recv_args->tid][lat_counter++] = ts;
actual_measurments++;
}
}
l_exit:
FREE(dst_data);
recv_args->status = status;
return NULL;
}
hailo_status infer(
hailo_input_stream input_stream, hailo_output_stream *output_streams, hailo_stream_info_t *all_strems_info,
int output_stream_cnt, int num_images, int write_log, size_t* host_output_frame_size, size_t host_input_frame_size, int source_fps)
{
hailo_status status = HAILO_SUCCESS;
pthread_t write_thread = 1;
recv_thread_args_t recv_args[NOF_STREAMS-1];
pthread_t recv_threads[NOF_STREAMS-1];
// struct timespec st, et;
// uint8_t* src_data = (uint8_t*)malloc(all_strems_info[0].hw_frame_size);
// uint8_t* dst_data = (uint8_t*)malloc(all_strems_info[1].hw_frame_size);
write_thread_args_t write_args = {
.input_stream = input_stream,
.status = HAILO_UNINITIALIZED,
.output_streams_cnt = output_stream_cnt,
.num_images = num_images,
.host_frame_size = host_input_frame_size,
.frame_hw_size = all_strems_info[0].hw_frame_size,
.source_fps = source_fps
};
for (int ii=0; ii<output_stream_cnt; ii++) {
recv_args[ii].output_stream = output_streams[ii];
recv_args[ii].tid = ii;
recv_args[ii].status = HAILO_UNINITIALIZED;
recv_args[ii].num_images = num_images;
recv_args[ii].write_log = write_log;
recv_args[ii].host_frame_size = host_output_frame_size[ii];
recv_args[ii].frame_hw_size = all_strems_info[ii+1].hw_frame_size;
(void) pthread_create(&recv_threads[ii], NULL, _recv_thread, &recv_args[ii]);
};
(void) pthread_create(&write_thread, NULL, _send_thread, &write_args);
pthread_join(write_thread, NULL);
if (HAILO_SUCCESS != write_args.status) {
printf("-E- write_thread failed\n");
status = HAILO_INTERNAL_FAILURE;
}
for (int ii=0; ii<output_stream_cnt; ii++) {
pthread_join(recv_threads[ii], NULL);
printf("-I- Closing Recv thread #%d: %d\n", recv_args[ii].tid, recv_args[ii].status);
if (HAILO_SUCCESS != recv_args[ii].status) {
printf("-E- Recv thread %d failed\n", recv_args[ii].tid);
status = HAILO_INTERNAL_FAILURE;
}
}
// for (uint32_t i = 1; i <= (uint32_t)num_images; i++) {
// clock_gettime(CLOCK_REALTIME, &st);
// status = hailo_stream_sync_write_all_raw_buffer(input_stream, src_data, 0, all_strems_info[0].hw_frame_size);
// status = hailo_stream_sync_read_all_raw_buffer(output_streams[0], dst_data, 0, all_strems_info[1].hw_frame_size);
// clock_gettime(CLOCK_REALTIME, &et);
// printf("-I- [%f ms] Infer [%3d/%3d]\n", get_time_from_ts(et)-get_time_from_ts(st), i, num_images);
// }
// FREE(src_data);
// FREE(dst_data);
return status;
}
void print_net_banner(hailo_input_stream_params_by_name_t* inputs, hailo_output_stream_params_by_name_t* outputs, size_t in_cnt, size_t out_cnt)
{
printf(MAGENTA);
printf("-I-----------------------------------------------------------\n");
printf("-I- Dir Name Transform Type Flags Order\n");
printf("-I-----------------------------------------------------------\n");
for (int i=0; i<in_cnt; i++) {
printf("-I- IN: %-20.20s: %-9.9s %-7.7s %-5.5s %-4.4s\n",
inputs[i].name,
get_transform_string(inputs[i].params.pcie_params.base_params.transform_mode),
get_type_string(inputs[i].params.pcie_params.base_params.user_buffer_format.type),
get_flags_string(inputs[i].params.pcie_params.base_params.user_buffer_format.flags),
get_order_string(inputs[i].params.pcie_params.base_params.user_buffer_format.order));
}
printf("-I-----------------------------------------------------------\n");
for (int i=0; i<out_cnt; i++) {
printf("-I- OUT:%-20.20s: %-9.9s %-7.7s %-5.5s %-4.4s\n",
outputs[i].name,
get_transform_string(outputs[i].params.pcie_params.base_params.transform_mode),
get_type_string(outputs[i].params.pcie_params.base_params.user_buffer_format.type),
get_flags_string(outputs[i].params.pcie_params.base_params.user_buffer_format.flags),
get_order_string(outputs[i].params.pcie_params.base_params.user_buffer_format.order));
}
printf("-I-----------------------------------------------------------\n");
printf(RESET);
}
double calc_latency(int count, double precentile, int write_log) {
double cur_rcv;
double cur_snd;
double latencies[actual_measurments];
for (int j=0; j<actual_measurments; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
latencies[j] = (cur_rcv - cur_snd);
}
if ((precentile<0) || (precentile>1)) {
precentile = 0.5;
}
if (write_log>0) {
FILE *fp = fopen("latency_redouts.txt", "w");
for (int ii=0; ii<actual_measurments; ii++) {
fprintf(fp, "%f\n",latencies[ii]);
}
fclose(fp);
}
return latencies[(int)(precentile * actual_measurments)];
}
void print_inference_stats(struct timespec start_time, struct timespec end_time, hailo_stream_info_t *all_stream_infos, int output_stream_cnt,
int num_images, uint32_t latency_readout, int write_log, hailo_latency_measurement_result_t driver_lat, int nbatch)
{
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
uint32_t send_frame_size = all_stream_infos[0].hw_frame_size;
uint32_t recv_frame_size = 0;
printf(BOLDGREEN);
printf("-I-----------------------------------------------\n");
printf("-I- Batch Size: %-4d\n", nbatch);
printf("-I- Total time: %4.2lf sec\n", infer_time_secs);
printf("-I- Average FPS: %4.2lf\n", num_images / infer_time_secs);
printf("-I- 95p Latency: %3.2lf ms\n", calc_latency(output_stream_cnt, 0.95, write_log));
printf("-I- Driver Latency: %3.2lf ms\n", driver_lat.avg_hw_latency_ms);
printf("-I- Send data rate: %-4.2lf Mbit/s\n",
(double)(num_images) * send_frame_size * mbit_per_byte / infer_time_secs);
for (int i=1; i<=output_stream_cnt; i++) {
recv_frame_size = all_stream_infos[i].hw_frame_size;
printf("-I- Recv[%d] data rate: %-4.2lf Mbit/s\n", i,
(double)(num_images) * recv_frame_size * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
void set_default_eth_output_stream_params(hailo_eth_output_stream_params_t* stream) {
stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
stream->device_port = 0;
stream->host_address.sin_family = AF_INET;
stream->host_address.sin_port = 0;
stream->host_address.sin_addr.s_addr = INADDR_ANY;
stream->base_params.buffers_threshold = 1;
// stream->is_sync_enabled = true;
memset(&stream->host_address.sin_zero, 0, sizeof(stream->host_address.sin_zero));
}
void set_default_pcie_output_stream_params(hailo_pcie_output_stream_params_t* stream) {
stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
}
hailo_status create_and_load_hef(hailo_device device, hailo_hef *hef, char* hef_file, hailo_network_group *network_group, int nbatch)
{
hailo_status status = HAILO_SUCCESS;
size_t number_of_network_groups = 1;
status = hailo_create_hef_file(hef, hef_file);
REQUIRE_SUCCESS(status, l_exit, "Failed to create hef file");
printf(MAGENTA);
printf("-I- Loading HEF file from %s\n", hef_file);
printf(RESET);
const char* net_group_name = "yolov4";
hailo_configure_params_t configure_params = {0};
configure_params.network_group_params_count = 1;
configure_params.network_group_params[0].batch_size = nbatch;
memcpy(configure_params.network_group_params[0].name, net_group_name, 6);
status = hailo_configure_device(device, *hef, &configure_params, network_group, &number_of_network_groups);
REQUIRE_SUCCESS(status, l_exit, "Failed to configure device from hef");
if (number_of_network_groups > 1) {
status = HAILO_UNINITIALIZED;
printf("-E- Got network_group=%ld", number_of_network_groups);
REQUIRE_SUCCESS(status, l_exit, "Failed to extract network group, larger than 1");
}
l_exit:
return status;
}
hailo_status activate_network_group(hailo_hef *hef, hailo_stream_info_t *streams_info, hailo_network_group network_group, hailo_activated_network_group *active_net_g, hailo_input_stream_params_by_name_t *input_stream_params, hailo_output_stream_params_by_name_t *output_stream_param, size_t *output_stream_cnt)
{
hailo_status status = HAILO_SUCCESS;
hailo_network_group_params_t network_group_params = {0};//HAILO_NETWORK_GROUP_PARAMS_DEFAULT;
size_t out_param_size = NOF_STREAMS-1;
size_t in_param_size = 1;
size_t number_of_streams;
hailo_stream_transform_mode_t transform_mode = HAILO_STREAM_NO_TRANSFORM;// HAILO_STREAM_NO_TRANSFORM
status = hailo_hef_get_all_stream_infos(hef, NULL, streams_info, sizeof(*streams_info), &number_of_streams);
status = hailo_make_input_stream_params(network_group, transform_mode, true, HAILO_FORMAT_TYPE_UINT8, input_stream_params, &in_param_size);
REQUIRE_SUCCESS(status, l_exit, "Failed to create input_params");
status = hailo_make_output_stream_params(network_group, transform_mode, true, HAILO_FORMAT_TYPE_UINT8, output_stream_param, &out_param_size);
*output_stream_cnt = out_param_size;
REQUIRE_SUCCESS(status, l_exit, "Failed to create output_params");
if (output_stream_param->params.pcie_params.base_params.user_buffer_format.order != HAILO_FORMAT_ORDER_HAILO_NMS)
network_group_params.latency = HAILO_LATENCY_MEASURE;
output_stream_param->params.eth_params.base_params.buffers_threshold = 1;
input_stream_params->params.eth_params.base_params.buffers_threshold = 1;
// input_stream_params->params.pcie_params.base_params.user_buffer_format.flags = streams_info[0].format.flags;
// input_stream_params->params.pcie_params.base_params.user_buffer_format.flags |= HAILO_FORMAT_FLAGS_TRANSPOSED;
print_net_banner(input_stream_params, output_stream_param, in_param_size, out_param_size);
status = hailo_activate_network_group(network_group,
&network_group_params,
input_stream_params, // Input params
in_param_size, // number of inputs
output_stream_param, // Output params
out_param_size, // number of ouputs
active_net_g);
REQUIRE_SUCCESS(status, l_exit, "Failed to activate network group");
l_exit:
return status;
}
hailo_status initialize_eth_device(const char *interface_name, hailo_device *device)
{
hailo_status status = HAILO_SUCCESS;
hailo_eth_device_info_t eth_device_info = {0};
size_t number_of_devices = 0;
status = hailo_scan_ethernet_devices(interface_name, &eth_device_info, 1, &number_of_devices, HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for eth_devices");
if (0 == number_of_devices) {
printf("No eth_device found on the given interface\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_ethernet_device(&eth_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_device");
l_exit:
return status;
}
hailo_status initialize_pcie_device(hailo_pcie_device_info_t *pcie_device_info, hailo_device *device)
{
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
status = hailo_scan_pcie_devices(pcie_device_info, 4, &number_of_devices);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for pcie_devices");
if (0 == number_of_devices) {
printf("No pcie_device found\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_pcie_device(pcie_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create pcie_device");
status = HAILO_SUCCESS;
l_exit:
return status;
}
hailo_status initiazlie_inference(hailo_device *device, hailo_input_stream *input_stream, hailo_stream_info_t *streams_info,
hailo_output_stream *output_streams, size_t *host_input_frame_size, size_t *host_output_frame_size, char* hef_path, size_t* output_stream_cnt,
hailo_activated_network_group *active_net_g, const char *interface, int nbatch)
{
// NADAV: Added two devices to support multiple M.2 connected to the machine
hailo_pcie_device_info_t pcie_device_info[4];
hailo_hef hef = NULL;
hailo_status status = HAILO_SUCCESS;
hailo_network_group network_groups = NULL;
hailo_input_stream_params_by_name_t input_stream_params = {0};
hailo_output_stream_params_by_name_t output_stream_params[NOF_STREAMS];
if (strncmp("pcie", interface, 4) == 0) {
status = initialize_pcie_device(pcie_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to initialize PCIe device");
} else {
status = initialize_eth_device(interface, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to initialize Eth device");
}
status = create_and_load_hef(*device, &hef, hef_path, &network_groups, nbatch);
REQUIRE_SUCCESS(status, l_exit, "Failed to create and load HEF");
status = activate_network_group(hef, streams_info, network_groups, active_net_g, &input_stream_params, output_stream_params, output_stream_cnt);
REQUIRE_SUCCESS(status, l_release_hef, "Failed to activate network group and streams");
REQUIRE_SUCCESS(status, l_release_hef, "Failed to create and activate pcie_streams");
status = hailo_get_input_stream_by_name(*active_net_g, streams_info[0].name, input_stream);
REQUIRE_SUCCESS(status, l_release_hef, "Failed getting stream info for input");
*host_input_frame_size = hailo_get_input_stream_frame_size(*input_stream);
for (size_t i = 0; i < *output_stream_cnt; i++) {
status = hailo_get_output_stream_by_name(*active_net_g, streams_info[i+1].name, &output_streams[i]);
REQUIRE_SUCCESS(status, l_release_hef, "Failed getting stream info for output");
host_output_frame_size[i] = hailo_get_output_stream_frame_size(output_streams[i]);
}
l_release_hef:
(void) hailo_release_hef(hef);
l_exit:
return status;
}
hailo_status print_power_stats(hailo_device device) {
hailo_status status;
hailo_power_measurement_data_t measurement_data[3];
status = hailo_stop_power_measurement(device);
status = hailo_get_power_measurement(device, 0, true, &measurement_data[0]);
printf(BOLDBLUE);
printf("-I-----------------------------------------------\n");
if (measurement_data[0].total_number_of_samples==0) {
printf("-W- The test was too short to measure power\n");
} else {
printf("-I- Total samples: %d ", measurement_data[0].total_number_of_samples);
printf(" Average time per sample (ms): %.3f\n", measurement_data[0].average_time_value_milliseconds);
printf("-I- CORE [%.3f, %.3f] W\n", measurement_data[0].min_value, measurement_data[0].max_value);
}
status = hailo_get_power_measurement(device, 1, true, &measurement_data[1]);
if (measurement_data[1].total_number_of_samples==0) {
printf("-W- The test was too short to measure power\n");
} else {
printf("-I- TOP [%.3f, %.3f] W\n", measurement_data[1].min_value, measurement_data[1].max_value);
}
status = hailo_get_power_measurement(device, 2, true, &measurement_data[2]);
if (measurement_data[2].total_number_of_samples==0) {
printf("-W- The test was too short to measure power\n");
} else {
printf("-I- MIPI [%.3f, %.3f] W\n", measurement_data[2].min_value, measurement_data[2].max_value);
}
float min=0;
float max=0;
for (int i=0;i<3;i++) {
min += measurement_data[i].min_value;
max += measurement_data[i].max_value;
}
printf("-I- TOTAL [%.3f, %.3f] W\n", min, max);
printf(RESET);
return status;
}
int main(int argc, char **argv)
{
hailo_status status = HAILO_SUCCESS;
hailo_device device = NULL;
hailo_input_stream input_stream = NULL;
hailo_output_stream output_streams[NOF_STREAMS];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
size_t host_input_frame_size = 0;
size_t host_output_frame_size[NOF_STREAMS];
struct timespec start_time = {0};
struct timespec end_time = {0};
size_t output_stream_cnt = 0;
char *config = "";
int opt;
char *iface = "pcie";
int num_img = 100;
int nbatch = 1;
int write_log = 0;
int source_fps = 0;
// hailo_dvm_options_t dvm_option = HAILO_DVM_OPTIONS_OVERCURRENT_PROTECTION;
hailo_dvm_options_t dvm_option0 = HAILO_DVM_OPTIONS_VDD_CORE;
hailo_dvm_options_t dvm_option1 = HAILO_DVM_OPTIONS_VDD_TOP;
hailo_dvm_options_t dvm_option2 = HAILO_DVM_OPTIONS_MIPI_AVDD;
enum hailo_power_measurement_types_e measurement_type = HAILO_POWER_MEASUREMENT_TYPES__POWER;
int measure_power = 0;
hailo_activated_network_group activated_network_group = NULL;
hailo_latency_measurement_result_t driver_result = {0};
uint32_t latency_readout = 0;
while ((opt = getopt(argc, argv, "b:f:i:c:n:pl")) != -1) {
switch (opt) {
case 'c': config = optarg; break;
case 'i': iface = optarg; break;
case 'n': num_img = atoi(optarg); break;
case 'b': nbatch = atoi(optarg); break;
case 'f': source_fps = atoi(optarg); break;
case 'l': write_log = 1; break;
case 'p': measure_power = 1; break;
case '?': fprintf (stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -c HEF [-i INTERFACE] [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -c HEF FILE The HEF config file \n");
fprintf(stderr, " -i INTERFACE The Interface, defaults to \'pcie\', can be also an Ethernet port name\n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -b BATCH Batch size (def. 1)\n");
fprintf(stderr, " -f FPS Emulate the source FPS (def. inf.)\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
fprintf(stderr, " -p Enable Power Measurement\n");
exit(EXIT_FAILURE);
}
}
if (num_img%nbatch != 0) {
printf(BOLDRED);
printf("-E- When specifying batch (%d), needs to make it a complete divisor of NUM-IMAGES (%d)\n", nbatch, num_img);
printf(RESET);
exit(1);
}
if (!strcmp(config,"")) {
printf(BOLDRED);
printf("-E- Must specify a path to existing HEF file\n");
printf(RESET);
exit(1);
}
printf(BOLDCYAN);
printf("-I- Running on interface: %s for %d images\n", iface, num_img);
printf(RESET);
status = initiazlie_inference(&device, &input_stream, all_stream_infos, output_streams, &host_input_frame_size,
host_output_frame_size, config, &output_stream_cnt, &activated_network_group, iface, nbatch);
REQUIRE_SUCCESS(status, l_release_device, "Failed to initialize inference");
if (measure_power==1) {
status = hailo_stop_power_measurement(device);
status = hailo_set_power_measurement(device, 0, dvm_option0, measurement_type);
status = hailo_set_power_measurement(device, 1, dvm_option1, measurement_type);
status = hailo_set_power_measurement(device, 2, dvm_option2, measurement_type);
status = hailo_start_power_measurement(device, DEFAULT_POWER_MEASUREMENT_DELAY_MS, HAILO_DEFAULT_INIT_AVERAGING_FACTOR, HAILO_DEFAULT_INIT_SAMPLING_PERIOD_US);
}
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
status = infer(input_stream, output_streams, all_stream_infos, output_stream_cnt, num_img, write_log, host_output_frame_size, host_input_frame_size, source_fps);
REQUIRE_SUCCESS(status, l_release_device, "Inference failure");
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
if (measure_power==1)
status = print_power_stats(device);
// Getting the latency from the driver
status = hailo_get_latency_measurement(activated_network_group, &driver_result);
print_inference_stats(start_time, end_time, all_stream_infos, output_stream_cnt, num_img, latency_readout, write_log, driver_result, nbatch);
l_release_device:
(void) hailo_deactivate_network_group(activated_network_group);
if (device != NULL)
(void) hailo_release_device(device);
printf(MAGENTA);
printf("-I- Finished gracefully\n");
printf(RESET);
return status;
}
#include <hailo/hailort.h>
#define FREE(var) \
do \
{ \
if (NULL != (var)) \
{ \
free(var); \
var = NULL; \
} \
} while (0)
#define REQUIRE_SUCCESS(status, label, msg) \
do \
{ \
if (HAILO_SUCCESS != (status)) \
{ \
printf(BOLDRED); \
printf("-E- %s : (%d)\n",msg, status); \
printf(RESET); \
goto label; \
} \
} while (0)
typedef struct write_thread_args_t
{
hailo_stream_info_t *input_stream_info;
hailo_input_stream input_stream;
hailo_status status;
int output_streams_cnt;
unsigned int num_images;
size_t host_frame_size;
size_t frame_hw_size;
int write_log;
int tid;
int source_fps;
} write_thread_args_t;
typedef struct recv_thread_args_t
{
hailo_stream_info_t *output_stream_info;
hailo_output_stream output_stream;
hailo_status status;
int tid;
unsigned int num_images;
int num_streams;
int write_log;
size_t host_frame_size;
size_t frame_hw_size;
} recv_thread_args_t;
typedef struct video_thread_args_t
{
hailo_stream_info_t *input_stream_info;
const char *video_path;
int num_images;
} video_thread_args_t;
const char* get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
const char *get_transform_string(hailo_stream_transform_mode_t transform)
{
switch(transform) {
case HAILO_STREAM_NO_TRANSFORM: return "NO";
case HAILO_STREAM_TRANSFORM_COPY: return "COPY";
case HAILO_STREAM_TRANSFORM_INPLACE: return "IN_PLACE";
case HAILO_STREAM_MAX_ENUM:
default: return "Wrong";
}
}
const char *get_flags_string(int flags)
{
switch(flags) {
case 0: return "NONE";
case 1: return "QUANT";
case 2: return "TRANS";
case 3: return "QT+TR";
default: return "UNKNOWN";
}
}
const char *get_type_string(int type)
{
switch(type) {
case 0: return "AUTO";
case 1: return "UINT8";
case 2: return "UINT16";
case 3: return "FLOAT32";
default: return "UNKNOWN";
}
}
const char *get_order_string(int order)
{
switch(order) {
case 0: return "NHWC";
case 1: return "NHCW";
case 2: return "FCR";
case 3: return "F8CR";
case 5: return "NC";
case 8: return "NMS";
case 10: return "NCHW";
default: return "UNKNOWN";
}
}
#define RESET "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
\ No newline at end of file
cmake_minimum_required(VERSION 3.0.0)
project( OpenCV_example )
##Setting the ARCH if not provided
if (NOT DEFINED ARCH)
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch_from_cmd)
string(STRIP ${arch_from_cmd} arch_from_cmd)
set(ARCH ${arch_from_cmd})
endif()
# Setting the CMAKE_C_COMPILER if not provided
if (${ARCH} STREQUAL "aarch64")
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "/usr/bin/aarch64-linux-gnu-gcc")
endif()
else()
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "/usr/bin/gcc")
endif()
endif()
set(CMAKE_CXX_COMPILER "/usr/bin/g++-9")
set(HAILORT_ROOT "/home/nadave/SDK/3.2.0/platform/hailort")
set(HAILORT_INCLUDE_DIR "${HAILORT_ROOT}/include")
set(HAILORT_LIB "${HAILORT_ROOT}/lib/x86_64/libhailort.so.2.2.0")
set(COMPILE_OPTIONS -Wall -std=gnu++2a -DNDEBUG)
include_directories(${HAILORT_INCLUDE_DIR})
set(target runme)
add_executable(${target} example.cpp ImageNetLabels.cpp)
target_compile_options(${target} PRIVATE ${COMPILE_OPTIONS})
find_package(Threads)
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
target_link_libraries(${target} ${OpenCV_LIBS})
target_link_libraries(${target} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${target} ${HAILORT_LIB})
#include "ImageNetLabels.hpp"
#include <cassert>
ImageNetLabels::ImageNetLabels() {
for( int i=0 ; i<1000; i++ ) {
std::string x = "NA";
_labels.push_back( x );
}
{
_labels[0]= "tench, Tinca tinca";
_labels[1]= "goldfish, Carassius auratus";
_labels[2]= "great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias";
_labels[3]= "tiger shark, Galeocerdo cuvieri";
_labels[4]= "hammerhead, hammerhead shark";
_labels[5]= "electric ray, crampfish, numbfish, torpedo";
_labels[6]= "stingray";
_labels[7]= "cock";
_labels[8]= "hen";
_labels[9]= "ostrich, Struthio camelus";
_labels[10]= "brambling, Fringilla montifringilla";
_labels[11]= "goldfinch, Carduelis carduelis";
_labels[12]= "house finch, linnet, Carpodacus mexicanus";
_labels[13]= "junco, snowbird";
_labels[14]= "indigo bunting, indigo finch, indigo bird, Passerina cyanea";
_labels[15]= "robin, American robin, Turdus migratorius";
_labels[16]= "bulbul";
_labels[17]= "jay";
_labels[18]= "magpie";
_labels[19]= "chickadee";
_labels[20]= "water ouzel, dipper";
_labels[21]= "kite";
_labels[22]= "bald eagle, American eagle, Haliaeetus leucocephalus";
_labels[23]= "vulture";
_labels[24]= "great grey owl, great gray owl, Strix nebulosa";
_labels[25]= "European fire salamander, Salamandra salamandra";
_labels[26]= "common newt, Triturus vulgaris";
_labels[27]= "eft";
_labels[28]= "spotted salamander, Ambystoma maculatum";
_labels[29]= "axolotl, mud puppy, Ambystoma mexicanum";
_labels[30]= "bullfrog, Rana catesbeiana";
_labels[31]= "tree frog, tree-frog";
_labels[32]= "tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui";
_labels[33]= "loggerhead, loggerhead turtle, Caretta caretta";
_labels[34]= "leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea";
_labels[35]= "mud turtle";
_labels[36]= "terrapin";
_labels[37]= "box turtle, box tortoise";
_labels[38]= "banded gecko";
_labels[39]= "common iguana, iguana, Iguana iguana";
_labels[40]= "American chameleon, anole, Anolis carolinensis";
_labels[41]= "whiptail, whiptail lizard";
_labels[42]= "agama";
_labels[43]= "frilled lizard, Chlamydosaurus kingi";
_labels[44]= "alligator lizard";
_labels[45]= "Gila monster, Heloderma suspectum";
_labels[46]= "green lizard, Lacerta viridis";
_labels[47]= "African chameleon, Chamaeleo chamaeleon";
_labels[48]= "Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis";
_labels[49]= "African crocodile, Nile crocodile, Crocodylus niloticus";
_labels[50]= "American alligator, Alligator mississipiensis";
_labels[51]= "triceratops";
_labels[52]= "thunder snake, worm snake, Carphophis amoenus";
_labels[53]= "ringneck snake, ring-necked snake, ring snake";
_labels[54]= "hognose snake, puff adder, sand viper";
_labels[55]= "green snake, grass snake";
_labels[56]= "king snake, kingsnake";
_labels[57]= "garter snake, grass snake";
_labels[58]= "water snake";
_labels[59]= "vine snake";
_labels[60]= "night snake, Hypsiglena torquata";
_labels[61]= "boa constrictor, Constrictor constrictor";
_labels[62]= "rock python, rock snake, Python sebae";
_labels[63]= "Indian cobra, Naja naja";
_labels[64]= "green mamba";
_labels[65]= "sea snake";
_labels[66]= "horned viper, cerastes, sand viper, horned asp, Cerastes cornutus";
_labels[67]= "diamondback, diamondback rattlesnake, Crotalus adamanteus";
_labels[68]= "sidewinder, horned rattlesnake, Crotalus cerastes";
_labels[69]= "trilobite";
_labels[70]= "harvestman, daddy longlegs, Phalangium opilio";
_labels[71]= "scorpion";
_labels[72]= "black and gold garden spider, Argiope aurantia";
_labels[73]= "barn spider, Araneus cavaticus";
_labels[74]= "garden spider, Aranea diademata";
_labels[75]= "black widow, Latrodectus mactans";
_labels[76]= "tarantula";
_labels[77]= "wolf spider, hunting spider";
_labels[78]= "tick";
_labels[79]= "centipede";
_labels[80]= "black grouse";
_labels[81]= "ptarmigan";
_labels[82]= "ruffed grouse, partridge, Bonasa umbellus";
_labels[83]= "prairie chicken, prairie grouse, prairie fowl";
_labels[84]= "peacock";
_labels[85]= "quail";
_labels[86]= "partridge";
_labels[87]= "African grey, African gray, Psittacus erithacus";
_labels[88]= "macaw";
_labels[89]= "sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita";
_labels[90]= "lorikeet";
_labels[91]= "coucal";
_labels[92]= "bee eater";
_labels[93]= "hornbill";
_labels[94]= "hummingbird";
_labels[95]= "jacamar";
_labels[96]= "toucan";
_labels[97]= "drake";
_labels[98]= "red-breasted merganser, Mergus serrator";
_labels[99]= "goose";
_labels[100]= "black swan, Cygnus atratus";
_labels[101]= "tusker";
_labels[102]= "echidna, spiny anteater, anteater";
_labels[103]= "platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus";
_labels[104]= "wallaby, brush kangaroo";
_labels[105]= "koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus";
_labels[106]= "wombat";
_labels[107]= "jellyfish";
_labels[108]= "sea anemone, anemone";
_labels[109]= "brain coral";
_labels[110]= "flatworm, platyhelminth";
_labels[111]= "nematode, nematode worm, roundworm";
_labels[112]= "conch";
_labels[113]= "snail";
_labels[114]= "slug";
_labels[115]= "sea slug, nudibranch";
_labels[116]= "chiton, coat-of-mail shell, sea cradle, polyplacophore";
_labels[117]= "chambered nautilus, pearly nautilus, nautilus";
_labels[118]= "Dungeness crab, Cancer magister";
_labels[119]= "rock crab, Cancer irroratus";
_labels[120]= "fiddler crab";
_labels[121]= "king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica";
_labels[122]= "American lobster, Northern lobster, Maine lobster, Homarus americanus";
_labels[123]= "spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish";
_labels[124]= "crayfish, crawfish, crawdad, crawdaddy";
_labels[125]= "hermit crab";
_labels[126]= "isopod";
_labels[127]= "white stork, Ciconia ciconia";
_labels[128]= "black stork, Ciconia nigra";
_labels[129]= "spoonbill";
_labels[130]= "flamingo";
_labels[131]= "little blue heron, Egretta caerulea";
_labels[132]= "American egret, great white heron, Egretta albus";
_labels[133]= "bittern";
_labels[134]= "crane";
_labels[135]= "limpkin, Aramus pictus";
_labels[136]= "European gallinule, Porphyrio porphyrio";
_labels[137]= "American coot, marsh hen, mud hen, water hen, Fulica americana";
_labels[138]= "bustard";
_labels[139]= "ruddy turnstone, Arenaria interpres";
_labels[140]= "red-backed sandpiper, dunlin, Erolia alpina";
_labels[141]= "redshank, Tringa totanus";
_labels[142]= "dowitcher";
_labels[143]= "oystercatcher, oyster catcher";
_labels[144]= "pelican";
_labels[145]= "king penguin, Aptenodytes patagonica";
_labels[146]= "albatross, mollymawk";
_labels[147]= "grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus";
_labels[148]= "killer whale, killer, orca, grampus, sea wolf, Orcinus orca";
_labels[149]= "dugong, Dugong dugon";
_labels[150]= "sea lion";
_labels[151]= "Chihuahua";
_labels[152]= "Japanese spaniel";
_labels[153]= "Maltese dog, Maltese terrier, Maltese";
_labels[154]= "Pekinese, Pekingese, Peke";
_labels[155]= "Shih-Tzu";
_labels[156]= "Blenheim spaniel";
_labels[157]= "papillon";
_labels[158]= "toy terrier";
_labels[159]= "Rhodesian ridgeback";
_labels[160]= "Afghan hound, Afghan";
_labels[161]= "basset, basset hound";
_labels[162]= "beagle";
_labels[163]= "bloodhound, sleuthhound";
_labels[164]= "bluetick";
_labels[165]= "black-and-tan coonhound";
_labels[166]= "Walker hound, Walker foxhound";
_labels[167]= "English foxhound";
_labels[168]= "redbone";
_labels[169]= "borzoi, Russian wolfhound";
_labels[170]= "Irish wolfhound";
_labels[171]= "Italian greyhound";
_labels[172]= "whippet";
_labels[173]= "Ibizan hound, Ibizan Podenco";
_labels[174]= "Norwegian elkhound, elkhound";
_labels[175]= "otterhound, otter hound";
_labels[176]= "Saluki, gazelle hound";
_labels[177]= "Scottish deerhound, deerhound";
_labels[178]= "Weimaraner";
_labels[179]= "Staffordshire bullterrier, Staffordshire bull terrier";
_labels[180]= "American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier";
_labels[181]= "Bedlington terrier";
_labels[182]= "Border terrier";
_labels[183]= "Kerry blue terrier";
_labels[184]= "Irish terrier";
_labels[185]= "Norfolk terrier";
_labels[186]= "Norwich terrier";
_labels[187]= "Yorkshire terrier";
_labels[188]= "wire-haired fox terrier";
_labels[189]= "Lakeland terrier";
_labels[190]= "Sealyham terrier, Sealyham";
_labels[191]= "Airedale, Airedale terrier";
_labels[192]= "cairn, cairn terrier";
_labels[193]= "Australian terrier";
_labels[194]= "Dandie Dinmont, Dandie Dinmont terrier";
_labels[195]= "Boston bull, Boston terrier";
_labels[196]= "miniature schnauzer";
_labels[197]= "giant schnauzer";
_labels[198]= "standard schnauzer";
_labels[199]= "Scotch terrier, Scottish terrier, Scottie";
_labels[200]= "Tibetan terrier, chrysanthemum dog";
_labels[201]= "silky terrier, Sydney silky";
_labels[202]= "soft-coated wheaten terrier";
_labels[203]= "West Highland white terrier";
_labels[204]= "Lhasa, Lhasa apso";
_labels[205]= "flat-coated retriever";
_labels[206]= "curly-coated retriever";
_labels[207]= "golden retriever";
_labels[208]= "Labrador retriever";
_labels[209]= "Chesapeake Bay retriever";
_labels[210]= "German short-haired pointer";
_labels[211]= "vizsla, Hungarian pointer";
_labels[212]= "English setter";
_labels[213]= "Irish setter, red setter";
_labels[214]= "Gordon setter";
_labels[215]= "Brittany spaniel";
_labels[216]= "clumber, clumber spaniel";
_labels[217]= "English springer, English springer spaniel";
_labels[218]= "Welsh springer spaniel";
_labels[219]= "cocker spaniel, English cocker spaniel, cocker";
_labels[220]= "Sussex spaniel";
_labels[221]= "Irish water spaniel";
_labels[222]= "kuvasz";
_labels[223]= "schipperke";
_labels[224]= "groenendael";
_labels[225]= "malinois";
_labels[226]= "briard";
_labels[227]= "kelpie";
_labels[228]= "komondor";
_labels[229]= "Old English sheepdog, bobtail";
_labels[230]= "Shetland sheepdog, Shetland sheep dog, Shetland";
_labels[231]= "collie";
_labels[232]= "Border collie";
_labels[233]= "Bouvier des Flandres, Bouviers des Flandres";
_labels[234]= "Rottweiler";
_labels[235]= "German shepherd, German shepherd dog, German police dog, alsatian";
_labels[236]= "Doberman, Doberman pinscher";
_labels[237]= "miniature pinscher";
_labels[238]= "Greater Swiss Mountain dog";
_labels[239]= "Bernese mountain dog";
_labels[240]= "Appenzeller";
_labels[241]= "EntleBucher";
_labels[242]= "boxer";
_labels[243]= "bull mastiff";
_labels[244]= "Tibetan mastiff";
_labels[245]= "French bulldog";
_labels[246]= "Great Dane";
_labels[247]= "Saint Bernard, St Bernard";
_labels[248]= "Eskimo dog, husky";
_labels[249]= "malamute, malemute, Alaskan malamute";
_labels[250]= "Siberian husky";
_labels[251]= "dalmatian, coach dog, carriage dog";
_labels[252]= "affenpinscher, monkey pinscher, monkey dog";
_labels[253]= "basenji";
_labels[254]= "pug, pug-dog";
_labels[255]= "Leonberg";
_labels[256]= "Newfoundland, Newfoundland dog";
_labels[257]= "Great Pyrenees";
_labels[258]= "Samoyed, Samoyede";
_labels[259]= "Pomeranian";
_labels[260]= "chow, chow chow";
_labels[261]= "keeshond";
_labels[262]= "Brabancon griffon";
_labels[263]= "Pembroke, Pembroke Welsh corgi";
_labels[264]= "Cardigan, Cardigan Welsh corgi";
_labels[265]= "toy poodle";
_labels[266]= "miniature poodle";
_labels[267]= "standard poodle";
_labels[268]= "Mexican hairless";
_labels[269]= "timber wolf, grey wolf, gray wolf, Canis lupus";
_labels[270]= "white wolf, Arctic wolf, Canis lupus tundrarum";
_labels[271]= "red wolf, maned wolf, Canis rufus, Canis niger";
_labels[272]= "coyote, prairie wolf, brush wolf, Canis latrans";
_labels[273]= "dingo, warrigal, warragal, Canis dingo";
_labels[274]= "dhole, Cuon alpinus";
_labels[275]= "African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus";
_labels[276]= "hyena, hyaena";
_labels[277]= "red fox, Vulpes vulpes";
_labels[278]= "kit fox, Vulpes macrotis";
_labels[279]= "Arctic fox, white fox, Alopex lagopus";
_labels[280]= "grey fox, gray fox, Urocyon cinereoargenteus";
_labels[281]= "tabby, tabby cat";
_labels[282]= "tiger cat";
_labels[283]= "Persian cat";
_labels[284]= "Siamese cat, Siamese";
_labels[285]= "Egyptian cat";
_labels[286]= "cougar, puma, catamount, mountain lion, painter, panther, Felis concolor";
_labels[287]= "lynx, catamount";
_labels[288]= "leopard, Panthera pardus";
_labels[289]= "snow leopard, ounce, Panthera uncia";
_labels[290]= "jaguar, panther, Panthera onca, Felis onca";
_labels[291]= "lion, king of beasts, Panthera leo";
_labels[292]= "tiger, Panthera tigris";
_labels[293]= "cheetah, chetah, Acinonyx jubatus";
_labels[294]= "brown bear, bruin, Ursus arctos";
_labels[295]= "American black bear, black bear, Ursus americanus, Euarctos americanus";
_labels[296]= "ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus";
_labels[297]= "sloth bear, Melursus ursinus, Ursus ursinus";
_labels[298]= "mongoose";
_labels[299]= "meerkat, mierkat";
_labels[300]= "tiger beetle";
_labels[301]= "ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle";
_labels[302]= "ground beetle, carabid beetle";
_labels[303]= "long-horned beetle, longicorn, longicorn beetle";
_labels[304]= "leaf beetle, chrysomelid";
_labels[305]= "dung beetle";
_labels[306]= "rhinoceros beetle";
_labels[307]= "weevil";
_labels[308]= "fly";
_labels[309]= "bee";
_labels[310]= "ant, emmet, pismire";
_labels[311]= "grasshopper, hopper";
_labels[312]= "cricket";
_labels[313]= "walking stick, walkingstick, stick insect";
_labels[314]= "cockroach, roach";
_labels[315]= "mantis, mantid";
_labels[316]= "cicada, cicala";
_labels[317]= "leafhopper";
_labels[318]= "lacewing, lacewing fly";
_labels[319]= "dragonfly, darning needle, devils darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk";
_labels[320]= "damselfly";
_labels[321]= "admiral";
_labels[322]= "ringlet, ringlet butterfly";
_labels[323]= "monarch, monarch butterfly, milkweed butterfly, Danaus plexippus";
_labels[324]= "cabbage butterfly";
_labels[325]= "sulphur butterfly, sulfur butterfly";
_labels[326]= "lycaenid, lycaenid butterfly";
_labels[327]= "starfish, sea star";
_labels[328]= "sea urchin";
_labels[329]= "sea cucumber, holothurian";
_labels[330]= "wood rabbit, cottontail, cottontail rabbit";
_labels[331]= "hare";
_labels[332]= "Angora, Angora rabbit";
_labels[333]= "hamster";
_labels[334]= "porcupine, hedgehog";
_labels[335]= "fox squirrel, eastern fox squirrel, Sciurus niger";
_labels[336]= "marmot";
_labels[337]= "beaver";
_labels[338]= "guinea pig, Cavia cobaya";
_labels[339]= "sorrel";
_labels[340]= "zebra";
_labels[341]= "hog, pig, grunter, squealer, Sus scrofa";
_labels[342]= "wild boar, boar, Sus scrofa";
_labels[343]= "warthog";
_labels[344]= "hippopotamus, hippo, river horse, Hippopotamus amphibius";
_labels[345]= "ox";
_labels[346]= "water buffalo, water ox, Asiatic buffalo, Bubalus bubalis";
_labels[347]= "bison";
_labels[348]= "ram, tup";
_labels[349]= "bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis";
_labels[350]= "ibex, Capra ibex";
_labels[351]= "hartebeest";
_labels[352]= "impala, Aepyceros melampus";
_labels[353]= "gazelle";
_labels[354]= "Arabian camel, dromedary, Camelus dromedarius";
_labels[355]= "llama";
_labels[356]= "weasel";
_labels[357]= "mink";
_labels[358]= "polecat, fitch, foulmart, foumart, Mustela putorius";
_labels[359]= "black-footed ferret, ferret, Mustela nigripes";
_labels[360]= "otter";
_labels[361]= "skunk, polecat, wood pussy";
_labels[362]= "badger";
_labels[363]= "armadillo";
_labels[364]= "three-toed sloth, ai, Bradypus tridactylus";
_labels[365]= "orangutan, orang, orangutang, Pongo pygmaeus";
_labels[366]= "gorilla, Gorilla gorilla";
_labels[367]= "chimpanzee, chimp, Pan troglodytes";
_labels[368]= "gibbon, Hylobates lar";
_labels[369]= "siamang, Hylobates syndactylus, Symphalangus syndactylus";
_labels[370]= "guenon, guenon monkey";
_labels[371]= "patas, hussar monkey, Erythrocebus patas";
_labels[372]= "baboon";
_labels[373]= "macaque";
_labels[374]= "langur";
_labels[375]= "colobus, colobus monkey";
_labels[376]= "proboscis monkey, Nasalis larvatus";
_labels[377]= "marmoset";
_labels[378]= "capuchin, ringtail, Cebus capucinus";
_labels[379]= "howler monkey, howler";
_labels[380]= "titi, titi monkey";
_labels[381]= "spider monkey, Ateles geoffroyi";
_labels[382]= "squirrel monkey, Saimiri sciureus";
_labels[383]= "Madagascar cat, ring-tailed lemur, Lemur catta";
_labels[384]= "indri, indris, Indri indri, Indri brevicaudatus";
_labels[385]= "Indian elephant, Elephas maximus";
_labels[386]= "African elephant, Loxodonta africana";
_labels[387]= "lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens";
_labels[388]= "giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca";
_labels[389]= "barracouta, snoek";
_labels[390]= "eel";
_labels[391]= "coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch";
_labels[392]= "rock beauty, Holocanthus tricolor";
_labels[393]= "anemone fish";
_labels[394]= "sturgeon";
_labels[395]= "gar, garfish, garpike, billfish, Lepisosteus osseus";
_labels[396]= "lionfish";
_labels[397]= "puffer, pufferfish, blowfish, globefish";
_labels[398]= "abacus";
_labels[399]= "abaya";
_labels[400]= "academic gown, academic robe, judges robe";
_labels[401]= "accordion, piano accordion, squeeze box";
_labels[402]= "acoustic guitar";
_labels[403]= "aircraft carrier, carrier, flattop, attack aircraft carrier";
_labels[404]= "airliner";
_labels[405]= "airship, dirigible";
_labels[406]= "altar";
_labels[407]= "ambulance";
_labels[408]= "amphibian, amphibious vehicle";
_labels[409]= "analog clock";
_labels[410]= "apiary, bee house";
_labels[411]= "apron";
_labels[412]= "ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin";
_labels[413]= "assault rifle, assault gun";
_labels[414]= "backpack, back pack, knapsack, packsack, rucksack, haversack";
_labels[415]= "bakery, bakeshop, bakehouse";
_labels[416]= "balance beam, beam";
_labels[417]= "balloon";
_labels[418]= "ballpoint, ballpoint pen, ballpen, Biro";
_labels[419]= "Band Aid";
_labels[420]= "banjo";
_labels[421]= "bannister, banister, balustrade, balusters, handrail";
_labels[422]= "barbell";
_labels[423]= "barber chair";
_labels[424]= "barbershop";
_labels[425]= "barn";
_labels[426]= "barometer";
_labels[427]= "barrel, cask";
_labels[428]= "barrow, garden cart, lawn cart, wheelbarrow";
_labels[429]= "baseball";
_labels[430]= "basketball";
_labels[431]= "bassinet";
_labels[432]= "bassoon";
_labels[433]= "bathing cap, swimming cap";
_labels[434]= "bath towel";
_labels[435]= "bathtub, bathing tub, bath, tub";
_labels[436]= "beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon";
_labels[437]= "beacon, lighthouse, beacon light, pharos";
_labels[438]= "beaker";
_labels[439]= "bearskin, busby, shako";
_labels[440]= "beer bottle";
_labels[441]= "beer glass";
_labels[442]= "bell cote, bell cot";
_labels[443]= "bib";
_labels[444]= "bicycle-built-for-two, tandem bicycle, tandem";
_labels[445]= "bikini, two-piece";
_labels[446]= "binder, ring-binder";
_labels[447]= "binoculars, field glasses, opera glasses";
_labels[448]= "birdhouse";
_labels[449]= "boathouse";
_labels[450]= "bobsled, bobsleigh, bob";
_labels[451]= "bolo tie, bolo, bola tie, bola";
_labels[452]= "bonnet, poke bonnet";
_labels[453]= "bookcase";
_labels[454]= "bookshop, bookstore, bookstall";
_labels[455]= "bottlecap";
_labels[456]= "bow";
_labels[457]= "bow tie, bow-tie, bowtie";
_labels[458]= "brass, memorial tablet, plaque";
_labels[459]= "brassiere, bra, bandeau";
_labels[460]= "breakwater, groin, groyne, mole, bulwark, seawall, jetty";
_labels[461]= "breastplate, aegis, egis";
_labels[462]= "broom";
_labels[463]= "bucket, pail";
_labels[464]= "buckle";
_labels[465]= "bulletproof vest";
_labels[466]= "bullet train, bullet";
_labels[467]= "butcher shop, meat market";
_labels[468]= "cab, hack, taxi, taxicab";
_labels[469]= "caldron, cauldron";
_labels[470]= "candle, taper, wax light";
_labels[471]= "cannon";
_labels[472]= "canoe";
_labels[473]= "can opener, tin opener";
_labels[474]= "cardigan";
_labels[475]= "car mirror";
_labels[476]= "carousel, carrousel, merry-go-round, roundabout, whirligig";
_labels[477]= "carpenters kit, tool kit";
_labels[478]= "carton";
_labels[479]= "car wheel";
_labels[480]= "cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM";
_labels[481]= "cassette";
_labels[482]= "cassette player";
_labels[483]= "castle";
_labels[484]= "catamaran";
_labels[485]= "CD player";
_labels[486]= "cello, violoncello";
_labels[487]= "cellular telephone, cellular phone, cellphone, cell, mobile phone";
_labels[488]= "chain";
_labels[489]= "chainlink fence";
_labels[490]= "chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour";
_labels[491]= "chain saw, chainsaw";
_labels[492]= "chest";
_labels[493]= "chiffonier, commode";
_labels[494]= "chime, bell, gong";
_labels[495]= "china cabinet, china closet";
_labels[496]= "Christmas stocking";
_labels[497]= "church, church building";
_labels[498]= "cinema, movie theater, movie theatre, movie house, picture palace";
_labels[499]= "cleaver, meat cleaver, chopper";
_labels[500]= "cliff dwelling";
_labels[501]= "cloak";
_labels[502]= "clog, geta, patten, sabot";
_labels[503]= "cocktail shaker";
_labels[504]= "coffee mug";
_labels[505]= "coffeepot";
_labels[506]= "coil, spiral, volute, whorl, helix";
_labels[507]= "combination lock";
_labels[508]= "computer keyboard, keypad";
_labels[509]= "confectionery, confectionary, candy store";
_labels[510]= "container ship, containership, container vessel";
_labels[511]= "convertible";
_labels[512]= "corkscrew, bottle screw";
_labels[513]= "cornet, horn, trumpet, trump";
_labels[514]= "cowboy boot";
_labels[515]= "cowboy hat, ten-gallon hat";
_labels[516]= "cradle";
_labels[517]= "crane";
_labels[518]= "crash helmet";
_labels[519]= "crate";
_labels[520]= "crib, cot";
_labels[521]= "Crock Pot";
_labels[522]= "croquet ball";
_labels[523]= "crutch";
_labels[524]= "cuirass";
_labels[525]= "dam, dike, dyke";
_labels[526]= "desk";
_labels[527]= "desktop computer";
_labels[528]= "dial telephone, dial phone";
_labels[529]= "diaper, nappy, napkin";
_labels[530]= "digital clock";
_labels[531]= "digital watch";
_labels[532]= "dining table, board";
_labels[533]= "dishrag, dishcloth";
_labels[534]= "dishwasher, dish washer, dishwashing machine";
_labels[535]= "disk brake, disc brake";
_labels[536]= "dock, dockage, docking facility";
_labels[537]= "dogsled, dog sled, dog sleigh";
_labels[538]= "dome";
_labels[539]= "doormat, welcome mat";
_labels[540]= "drilling platform, offshore rig";
_labels[541]= "drum, membranophone, tympan";
_labels[542]= "drumstick";
_labels[543]= "dumbbell";
_labels[544]= "Dutch oven";
_labels[545]= "electric fan, blower";
_labels[546]= "electric guitar";
_labels[547]= "electric locomotive";
_labels[548]= "entertainment center";
_labels[549]= "envelope";
_labels[550]= "espresso maker";
_labels[551]= "face powder";
_labels[552]= "feather boa, boa";
_labels[553]= "file, file cabinet, filing cabinet";
_labels[554]= "fireboat";
_labels[555]= "fire engine, fire truck";
_labels[556]= "fire screen, fireguard";
_labels[557]= "flagpole, flagstaff";
_labels[558]= "flute, transverse flute";
_labels[559]= "folding chair";
_labels[560]= "football helmet";
_labels[561]= "forklift";
_labels[562]= "fountain";
_labels[563]= "fountain pen";
_labels[564]= "four-poster";
_labels[565]= "freight car";
_labels[566]= "French horn, horn";
_labels[567]= "frying pan, frypan, skillet";
_labels[568]= "fur coat";
_labels[569]= "garbage truck, dustcart";
_labels[570]= "gasmask, respirator, gas helmet";
_labels[571]= "gas pump, gasoline pump, petrol pump, island dispenser";
_labels[572]= "goblet";
_labels[573]= "go-kart";
_labels[574]= "golf ball";
_labels[575]= "golfcart, golf cart";
_labels[576]= "gondola";
_labels[577]= "gong, tam-tam";
_labels[578]= "gown";
_labels[579]= "grand piano, grand";
_labels[580]= "greenhouse, nursery, glasshouse";
_labels[581]= "grille, radiator grille";
_labels[582]= "grocery store, grocery, food market, market";
_labels[583]= "guillotine";
_labels[584]= "hair slide";
_labels[585]= "hair spray";
_labels[586]= "half track";
_labels[587]= "hammer";
_labels[588]= "hamper";
_labels[589]= "hand blower, blow dryer, blow drier, hair dryer, hair drier";
_labels[590]= "hand-held computer, hand-held microcomputer";
_labels[591]= "handkerchief, hankie, hanky, hankey";
_labels[592]= "hard disc, hard disk, fixed disk";
_labels[593]= "harmonica, mouth organ, harp, mouth harp";
_labels[594]= "harp";
_labels[595]= "harvester, reaper";
_labels[596]= "hatchet";
_labels[597]= "holster";
_labels[598]= "home theater, home theatre";
_labels[599]= "honeycomb";
_labels[600]= "hook, claw";
_labels[601]= "hoopskirt, crinoline";
_labels[602]= "horizontal bar, high bar";
_labels[603]= "horse cart, horse-cart";
_labels[604]= "hourglass";
_labels[605]= "iPod";
_labels[606]= "iron, smoothing iron";
_labels[607]= "jack-o-lantern";
_labels[608]= "jean, blue jean, denim";
_labels[609]= "jeep, landrover";
_labels[610]= "jersey, T-shirt, tee shirt";
_labels[611]= "jigsaw puzzle";
_labels[612]= "jinrikisha, ricksha, rickshaw";
_labels[613]= "joystick";
_labels[614]= "kimono";
_labels[615]= "knee pad";
_labels[616]= "knot";
_labels[617]= "lab coat, laboratory coat";
_labels[618]= "ladle";
_labels[619]= "lampshade, lamp shade";
_labels[620]= "laptop, laptop computer";
_labels[621]= "lawn mower, mower";
_labels[622]= "lens cap, lens cover";
_labels[623]= "letter opener, paper knife, paperknife";
_labels[624]= "library";
_labels[625]= "lifeboat";
_labels[626]= "lighter, light, igniter, ignitor";
_labels[627]= "limousine, limo";
_labels[628]= "liner, ocean liner";
_labels[629]= "lipstick, lip rouge";
_labels[630]= "Loafer";
_labels[631]= "lotion";
_labels[632]= "loudspeaker, speaker, speaker unit, loudspeaker system, speaker system";
_labels[633]= "loupe, jewelers loupe";
_labels[634]= "lumbermill, sawmill";
_labels[635]= "magnetic compass";
_labels[636]= "mailbag, postbag";
_labels[637]= "mailbox, letter box";
_labels[638]= "maillot";
_labels[639]= "maillot, tank suit";
_labels[640]= "manhole cover";
_labels[641]= "maraca";
_labels[642]= "marimba, xylophone";
_labels[643]= "mask";
_labels[644]= "matchstick";
_labels[645]= "maypole";
_labels[646]= "maze, labyrinth";
_labels[647]= "measuring cup";
_labels[648]= "medicine chest, medicine cabinet";
_labels[649]= "megalith, megalithic structure";
_labels[650]= "microphone, mike";
_labels[651]= "microwave, microwave oven";
_labels[652]= "military uniform";
_labels[653]= "milk can";
_labels[654]= "minibus";
_labels[655]= "miniskirt, mini";
_labels[656]= "minivan";
_labels[657]= "missile";
_labels[658]= "mitten";
_labels[659]= "mixing bowl";
_labels[660]= "mobile home, manufactured home";
_labels[661]= "Model T";
_labels[662]= "modem";
_labels[663]= "monastery";
_labels[664]= "monitor";
_labels[665]= "moped";
_labels[666]= "mortar";
_labels[667]= "mortarboard";
_labels[668]= "mosque";
_labels[669]= "mosquito net";
_labels[670]= "motor scooter, scooter";
_labels[671]= "mountain bike, all-terrain bike, off-roader";
_labels[672]= "mountain tent";
_labels[673]= "mouse, computer mouse";
_labels[674]= "mousetrap";
_labels[675]= "moving van";
_labels[676]= "muzzle";
_labels[677]= "nail";
_labels[678]= "neck brace";
_labels[679]= "necklace";
_labels[680]= "nipple";
_labels[681]= "notebook, notebook computer";
_labels[682]= "obelisk";
_labels[683]= "oboe, hautboy, hautbois";
_labels[684]= "ocarina, sweet potato";
_labels[685]= "odometer, hodometer, mileometer, milometer";
_labels[686]= "oil filter";
_labels[687]= "organ, pipe organ";
_labels[688]= "oscilloscope, scope, cathode-ray oscilloscope, CRO";
_labels[689]= "overskirt";
_labels[690]= "oxcart";
_labels[691]= "oxygen mask";
_labels[692]= "packet";
_labels[693]= "paddle, boat paddle";
_labels[694]= "paddlewheel, paddle wheel";
_labels[695]= "padlock";
_labels[696]= "paintbrush";
_labels[697]= "pajama, pyjama, pjs, jammies";
_labels[698]= "palace";
_labels[699]= "panpipe, pandean pipe, syrinx";
_labels[700]= "paper towel";
_labels[701]= "parachute, chute";
_labels[702]= "parallel bars, bars";
_labels[703]= "park bench";
_labels[704]= "parking meter";
_labels[705]= "passenger car, coach, carriage";
_labels[706]= "patio, terrace";
_labels[707]= "pay-phone, pay-station";
_labels[708]= "pedestal, plinth, footstall";
_labels[709]= "pencil box, pencil case";
_labels[710]= "pencil sharpener";
_labels[711]= "perfume, essence";
_labels[712]= "Petri dish";
_labels[713]= "photocopier";
_labels[714]= "pick, plectrum, plectron";
_labels[715]= "pickelhaube";
_labels[716]= "picket fence, paling";
_labels[717]= "pickup, pickup truck";
_labels[718]= "pier";
_labels[719]= "piggy bank, penny bank";
_labels[720]= "pill bottle";
_labels[721]= "pillow";
_labels[722]= "ping-pong ball";
_labels[723]= "pinwheel";
_labels[724]= "pirate, pirate ship";
_labels[725]= "pitcher, ewer";
_labels[726]= "plane, carpenters plane, woodworking plane";
_labels[727]= "planetarium";
_labels[728]= "plastic bag";
_labels[729]= "plate rack";
_labels[730]= "plow, plough";
_labels[731]= "plunger, plumbers helper";
_labels[732]= "Polaroid camera, Polaroid Land camera";
_labels[733]= "pole";
_labels[734]= "police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria";
_labels[735]= "poncho";
_labels[736]= "pool table, billiard table, snooker table";
_labels[737]= "pop bottle, soda bottle";
_labels[738]= "pot, flowerpot";
_labels[739]= "potters wheel";
_labels[740]= "power drill";
_labels[741]= "prayer rug, prayer mat";
_labels[742]= "printer";
_labels[743]= "prison, prison house";
_labels[744]= "projectile, missile";
_labels[745]= "projector";
_labels[746]= "puck, hockey puck";
_labels[747]= "punching bag, punch bag, punching ball, punchball";
_labels[748]= "purse";
_labels[749]= "quill, quill pen";
_labels[750]= "quilt, comforter, comfort, puff";
_labels[751]= "racer, race car, racing car";
_labels[752]= "racket, racquet";
_labels[753]= "radiator";
_labels[754]= "radio, wireless";
_labels[755]= "radio telescope, radio reflector";
_labels[756]= "rain barrel";
_labels[757]= "recreational vehicle, RV, R.V.";
_labels[758]= "reel";
_labels[759]= "reflex camera";
_labels[760]= "refrigerator, icebox";
_labels[761]= "remote control, remote";
_labels[762]= "restaurant, eating house, eating place, eatery";
_labels[763]= "revolver, six-gun, six-shooter";
_labels[764]= "rifle";
_labels[765]= "rocking chair, rocker";
_labels[766]= "rotisserie";
_labels[767]= "rubber eraser, rubber, pencil eraser";
_labels[768]= "rugby ball";
_labels[769]= "rule, ruler";
_labels[770]= "running shoe";
_labels[771]= "safe";
_labels[772]= "safety pin";
_labels[773]= "saltshaker, salt shaker";
_labels[774]= "sandal";
_labels[775]= "sarong";
_labels[776]= "sax, saxophone";
_labels[777]= "scabbard";
_labels[778]= "scale, weighing machine";
_labels[779]= "school bus";
_labels[780]= "schooner";
_labels[781]= "scoreboard";
_labels[782]= "screen, CRT screen";
_labels[783]= "screw";
_labels[784]= "screwdriver";
_labels[785]= "seat belt, seatbelt";
_labels[786]= "sewing machine";
_labels[787]= "shield, buckler";
_labels[788]= "shoe shop, shoe-shop, shoe store";
_labels[789]= "shoji";
_labels[790]= "shopping basket";
_labels[791]= "shopping cart";
_labels[792]= "shovel";
_labels[793]= "shower cap";
_labels[794]= "shower curtain";
_labels[795]= "ski";
_labels[796]= "ski mask";
_labels[797]= "sleeping bag";
_labels[798]= "slide rule, slipstick";
_labels[799]= "sliding door";
_labels[800]= "slot, one-armed bandit";
_labels[801]= "snorkel";
_labels[802]= "snowmobile";
_labels[803]= "snowplow, snowplough";
_labels[804]= "soap dispenser";
_labels[805]= "soccer ball";
_labels[806]= "sock";
_labels[807]= "solar dish, solar collector, solar furnace";
_labels[808]= "sombrero";
_labels[809]= "soup bowl";
_labels[810]= "space bar";
_labels[811]= "space heater";
_labels[812]= "space shuttle";
_labels[813]= "spatula";
_labels[814]= "speedboat";
_labels[815]= "spider web, spiders web";
_labels[816]= "spindle";
_labels[817]= "sports car, sport car";
_labels[818]= "spotlight, spot";
_labels[819]= "stage";
_labels[820]= "steam locomotive";
_labels[821]= "steel arch bridge";
_labels[822]= "steel drum";
_labels[823]= "stethoscope";
_labels[824]= "stole";
_labels[825]= "stone wall";
_labels[826]= "stopwatch, stop watch";
_labels[827]= "stove";
_labels[828]= "strainer";
_labels[829]= "streetcar, tram, tramcar, trolley, trolley car";
_labels[830]= "stretcher";
_labels[831]= "studio couch, day bed";
_labels[832]= "stupa, tope";
_labels[833]= "submarine, pigboat, sub, U-boat";
_labels[834]= "suit, suit of clothes";
_labels[835]= "sundial";
_labels[836]= "sunglass";
_labels[837]= "sunglasses, dark glasses, shades";
_labels[838]= "sunscreen, sunblock, sun blocker";
_labels[839]= "suspension bridge";
_labels[840]= "swab, swob, mop";
_labels[841]= "sweatshirt";
_labels[842]= "swimming trunks, bathing trunks";
_labels[843]= "swing";
_labels[844]= "switch, electric switch, electrical switch";
_labels[845]= "syringe";
_labels[846]= "table lamp";
_labels[847]= "tank, army tank, armored combat vehicle, armoured combat vehicle";
_labels[848]= "tape player";
_labels[849]= "teapot";
_labels[850]= "teddy, teddy bear";
_labels[851]= "television, television system";
_labels[852]= "tennis ball";
_labels[853]= "thatch, thatched roof";
_labels[854]= "theater curtain, theatre curtain";
_labels[855]= "thimble";
_labels[856]= "thresher, thrasher, threshing machine";
_labels[857]= "throne";
_labels[858]= "tile roof";
_labels[859]= "toaster";
_labels[860]= "tobacco shop, tobacconist shop, tobacconist";
_labels[861]= "toilet seat";
_labels[862]= "torch";
_labels[863]= "totem pole";
_labels[864]= "tow truck, tow car, wrecker";
_labels[865]= "toyshop";
_labels[866]= "tractor";
_labels[867]= "trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi";
_labels[868]= "tray";
_labels[869]= "trench coat";
_labels[870]= "tricycle, trike, velocipede";
_labels[871]= "trimaran";
_labels[872]= "tripod";
_labels[873]= "triumphal arch";
_labels[874]= "trolleybus, trolley coach, trackless trolley";
_labels[875]= "trombone";
_labels[876]= "tub, vat";
_labels[877]= "turnstile";
_labels[878]= "typewriter keyboard";
_labels[879]= "umbrella";
_labels[880]= "unicycle, monocycle";
_labels[881]= "upright, upright piano";
_labels[882]= "vacuum, vacuum cleaner";
_labels[883]= "vase";
_labels[884]= "vault";
_labels[885]= "velvet";
_labels[886]= "vending machine";
_labels[887]= "vestment";
_labels[888]= "viaduct";
_labels[889]= "violin, fiddle";
_labels[890]= "volleyball";
_labels[891]= "waffle iron";
_labels[892]= "wall clock";
_labels[893]= "wallet, billfold, notecase, pocketbook";
_labels[894]= "wardrobe, closet, press";
_labels[895]= "warplane, military plane";
_labels[896]= "washbasin, handbasin, washbowl, lavabo, wash-hand basin";
_labels[897]= "washer, automatic washer, washing machine";
_labels[898]= "water bottle";
_labels[899]= "water jug";
_labels[900]= "water tower";
_labels[901]= "whiskey jug";
_labels[902]= "whistle";
_labels[903]= "wig";
_labels[904]= "window screen";
_labels[905]= "window shade";
_labels[906]= "Windsor tie";
_labels[907]= "wine bottle";
_labels[908]= "wing";
_labels[909]= "wok";
_labels[910]= "wooden spoon";
_labels[911]= "wool, woolen, woollen";
_labels[912]= "worm fence, snake fence, snake-rail fence, Virginia fence";
_labels[913]= "wreck";
_labels[914]= "yawl";
_labels[915]= "yurt";
_labels[916]= "web site, website, internet site, site";
_labels[917]= "comic book";
_labels[918]= "crossword puzzle, crossword";
_labels[919]= "street sign";
_labels[920]= "traffic light, traffic signal, stoplight";
_labels[921]= "book jacket, dust cover, dust jacket, dust wrapper";
_labels[922]= "menu";
_labels[923]= "plate";
_labels[924]= "guacamole";
_labels[925]= "consomme";
_labels[926]= "hot pot, hotpot";
_labels[927]= "trifle";
_labels[928]= "ice cream, icecream";
_labels[929]= "ice lolly, lolly, lollipop, popsicle";
_labels[930]= "French loaf";
_labels[931]= "bagel, beigel";
_labels[932]= "pretzel";
_labels[933]= "cheeseburger";
_labels[934]= "hotdog, hot dog, red hot";
_labels[935]= "mashed potato";
_labels[936]= "head cabbage";
_labels[937]= "broccoli";
_labels[938]= "cauliflower";
_labels[939]= "zucchini, courgette";
_labels[940]= "spaghetti squash";
_labels[941]= "acorn squash";
_labels[942]= "butternut squash";
_labels[943]= "cucumber, cuke";
_labels[944]= "artichoke, globe artichoke";
_labels[945]= "bell pepper";
_labels[946]= "cardoon";
_labels[947]= "mushroom";
_labels[948]= "Granny Smith";
_labels[949]= "strawberry";
_labels[950]= "orange";
_labels[951]= "lemon";
_labels[952]= "fig";
_labels[953]= "pineapple, ananas";
_labels[954]= "banana";
_labels[955]= "jackfruit, jak, jack";
_labels[956]= "custard apple";
_labels[957]= "pomegranate";
_labels[958]= "hay";
_labels[959]= "carbonara";
_labels[960]= "chocolate sauce, chocolate syrup";
_labels[961]= "dough";
_labels[962]= "meat loaf, meatloaf";
_labels[963]= "pizza, pizza pie";
_labels[964]= "potpie";
_labels[965]= "burrito";
_labels[966]= "red wine";
_labels[967]= "espresso";
_labels[968]= "cup";
_labels[969]= "eggnog";
_labels[970]= "alp";
_labels[971]= "bubble";
_labels[972]= "cliff, drop, drop-off";
_labels[973]= "coral reef";
_labels[974]= "geyser";
_labels[975]= "lakeside, lakeshore";
_labels[976]= "promontory, headland, head, foreland";
_labels[977]= "sandbar, sand bar";
_labels[978]= "seashore, coast, seacoast, sea-coast";
_labels[979]= "valley, vale";
_labels[980]= "volcano";
_labels[981]= "ballplayer, baseball player";
_labels[982]= "groom, bridegroom";
_labels[983]= "scuba diver";
_labels[984]= "rapeseed";
_labels[985]= "daisy";
_labels[986]= "yellow ladys slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum";
_labels[987]= "corn";
_labels[988]= "acorn";
_labels[989]= "hip, rose hip, rosehip";
_labels[990]= "buckeye, horse chestnut, conker";
_labels[991]= "coral fungus";
_labels[992]= "agaric";
_labels[993]= "gyromitra";
_labels[994]= "stinkhorn, carrion fungus";
_labels[995]= "earthstar";
_labels[996]= "hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa";
_labels[997]= "bolete";
_labels[998]= "ear, spike, capitulum";
_labels[999]= "toilet tissue, toilet paper, bathroom tissue";
}
}
std::string ImageNetLabels::imagenet_labelstring( int i ) {
assert( i>=0 && i<1000 );
return _labels[i];
}
\ No newline at end of file
#ifndef IMAGENETLABELS_H
#define IMAGENETLABELS_H
#include <iostream>
#include <string>
#include <vector>
class ImageNetLabels
{
private:
std::vector<std::string> _labels;
public:
ImageNetLabels();
std::string imagenet_labelstring(int i);
};
#endif
\ No newline at end of file
1. Dependencies:
1. OpenCV
`sudo apt-get install -y libopencv-dev`
`sudo apt-get install g++-9`
2. First time directory preparation:
`cmake -H. -Bbuild`
3. Consecutive builds:
`cmake --build build`
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file example.c
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include <net/if.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <regex>
#include <dirent.h>
#include <linux/limits.h>
#include <time.h>
#include <queue>
#include <opencv2/opencv.hpp>
#include <opencv2/video/video.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <fstream>
#include <hailo/hailort.h>
#include "example_utils.hpp"
#include "ImageNetLabels.hpp"
#define NOF_STREAMS (5)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
using namespace std;
using namespace cv;
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
queue<Mat> input_image_queue;
pthread_mutex_t input_image_queue_m = PTHREAD_MUTEX_INITIALIZER;
queue< vector<uint8_t> > post_infer_queue[NOF_STREAMS-1];
pthread_mutex_t post_infer_queue_m[NOF_STREAMS-1] = PTHREAD_MUTEX_INITIALIZER;
string classification_post_process(vector<float32_t>& tensor, unsigned offset=0, float threshold=0.3)
{
int max_idx;
static ImageNetLabels obj;
max_idx = argmax(softmax(tensor));
if (tensor[max_idx] < threshold) return "N\\A";
return obj.imagenet_labelstring(max_idx);
}
cv::Mat _aspect_preserving_resize(const cv::Mat &image, int target_width)
{
cv::Mat output;
int min_dim = ( image.cols >= image.rows ) ? image.rows : image.cols;
float scale = ( ( float ) target_width ) / min_dim;
cv::resize( image, output, cv::Size(int(image.cols*scale), int(image.rows*scale)));
return output;
}
cv::Mat _center_crop(cv::Mat& image, cv::Size& input_size)
{
cv::Rect myROI(int(image.cols/2-input_size.width/2), int(image.rows/2-input_size.height/2), input_size.width, input_size.height);
cv::Mat croppedImage = image(myROI);
return croppedImage;
}
cv::Mat classification_pre_process(const cv::Mat& image, cv::Size& input_size)
{
cv::Mat output(input_size, CV_8UC3);
int min_input_size = int(input_size.height * 1.14);
output = _aspect_preserving_resize(image, min_input_size);
return _center_crop(output, input_size);
}
bool source_is_npy(string& path) {
const vector<string> suffixs = {"npy", "NPY"};
for (string suffix : suffixs) {
if (regex_search(path, regex(string(suffix) + "$")))
return true;
}
return false;
}
void* _frame_lib_thread(void *args) {
video_thread_args_t *v_args = (video_thread_args_t*)args;
cv::Mat org_frame;
vector<cv::String> file_names;
cv::Mat pp_frame(v_args->input_stream_info->hw_shape.height, v_args->input_stream_info->hw_shape.height, CV_8UC3);
unsigned int idx=0;
cv::Size input_size;
// std::ofstream outFile("tx_images.cpp.txt");
cout << BOLDCYAN << "-I-----------------------------------------------" << endl
<< "-I- [Frames-thread] Source: " << v_args->video_path << endl
<< "-I- [Frames-thread] Output shape (" << v_args->input_stream_info->hw_shape.height << ", " << v_args->input_stream_info->hw_shape.height << ")" << endl
<< "-I-----------------------------------------------"
<< RESET << endl;
cv::glob(v_args->video_path, file_names, false);
input_size.width = v_args->input_stream_info->hw_shape.width;
input_size.height = v_args->input_stream_info->hw_shape.height;
for (std::string file : file_names) {
if (not(file.ends_with(".jpg") || file.ends_with(".png"))) {
continue;
}
org_frame = cv::imread(file);
if (org_frame.channels() == 3) {
cv::cvtColor(org_frame, org_frame, cv::COLOR_BGR2RGB);
}
cout << "-I- [Frames-thread] Getting frame #"<< idx++ << ":" << file << endl;
pp_frame = classification_pre_process(org_frame, input_size);
// outFile << "TX Image "<< idx << " " << file << endl;
// outFile << pp_frame << endl;
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame.clone());
pthread_mutex_unlock(&input_image_queue_m);
}
// Mark the final frame
pp_frame.data[0] = 17;
pp_frame.data[1] = 71;
pp_frame.data[2] = 17;
pp_frame.data[3] = 71;
idx++;
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame.clone());
pthread_mutex_unlock(&input_image_queue_m);
cout << BOLDCYAN << "-I-----------------------------------------------" << endl
<< "-I- [Frames-thread] FINISHED READING DIR - #" << idx-1 << endl
<< "-I-----------------------------------------------"
<< RESET << endl;
return NULL;
}
void* _video_source_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
video_thread_args_t *v_args = (video_thread_args_t*)args;
Mat org_frame;
Mat pp_frame(v_args->input_stream_info->hw_shape.height, v_args->input_stream_info->hw_shape.height, CV_8UC3);
unsigned int idx=0;
VideoCapture cap(v_args->video_path);
if (!cap.isOpened()) {
cout << "-E- Unable to open video stream" << endl;
status = HAILO_INTERNAL_FAILURE;
}
Size shape = Size((int) cap.get(CV_CAP_PROP_FRAME_WIDTH), (int) cap.get(CV_CAP_PROP_FRAME_HEIGHT));
cout << BOLDCYAN << "-I-----------------------------------------------" << endl;
cout << "-I- [Video-thread] Source: " << v_args->video_path << endl;
cout << "-I- [Video-thread] Input shape (" << shape.width <<", "<<shape.height<<")" << endl;
cout << "-I- [Video-thread] Output shape (" << v_args->input_stream_info->hw_shape.height << ", " << v_args->input_stream_info->hw_shape.height << ")" << endl;
cout << "-I-----------------------------------------------" << RESET << endl;
while (true && status==HAILO_SUCCESS) {
if (++idx%500==0)
cout << "-I- [Video-thread] Getting frame: "<< idx << endl;
cap >> org_frame;
if (org_frame.empty())
break;
resize(org_frame, pp_frame, pp_frame.size());
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame.clone());
pthread_mutex_unlock(&input_image_queue_m);
}
// Mark the final frame
pp_frame.data[0] = 17;
pp_frame.data[1] = 71;
pp_frame.data[2] = 17;
pp_frame.data[3] = 71;
idx++;
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame);
pthread_mutex_unlock(&input_image_queue_m);
cout << BOLDCYAN << "-I-----------------------------------------------" << endl;
cout << "-I- [Video-thread] FINISHED MOVIE STREAM - " << idx << endl;
cout << "-I-----------------------------------------------" << RESET << endl;
cap.release();
return (void *)status;
}
void* _send_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
unsigned lat_counter = 0;
struct timespec ts;
Mat curr_img(write_args->input_stream_info->shape.height, write_args->input_stream_info->shape.width, CV_8UC3);
int counter = 0;
vector<uint8_t> array;
array.resize(write_args->input_shape_size);
while (true) {
if (input_image_queue.empty()) {
cout << "-I- Waiting for the image queue to fill" << endl;
sleep(1);
continue;
}
pthread_mutex_lock(&input_image_queue_m);
curr_img = input_image_queue.front();
input_image_queue.pop();
pthread_mutex_unlock(&input_image_queue_m);
if (counter>10 && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
sent_clock_t[lat_counter++] = ts;
}
if (counter % 500==0) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] Send frame [%3d] 0x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, counter, curr_img.data[0], curr_img.data[1]);
}
counter++;
if (curr_img.data[0] == 17 && curr_img.data[1] == 71 && curr_img.data[2] == 17 && curr_img.data[3] == 71) {
cout << "-I- [TX-Thread] Received stop pattern - " << counter << endl;
sleep (1);
break;
}
if (curr_img.isContinuous()) {
int totalsz = curr_img.dataend-curr_img.datastart;
array.assign(curr_img.datastart, curr_img.datastart + totalsz);
} else {
int rowsz = CV_ELEM_SIZE(curr_img.type()) * curr_img.cols;
for (int i = 0; i < curr_img.rows; ++i) {
array.insert(array.end(), curr_img.ptr<uint8_t>(i), curr_img.ptr<uint8_t>(i) + rowsz);
}
}
// status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream, &src_data, 0, write_args->input_shape_size * sizeof(float32_t));
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream, array.data(), 0, write_args->input_shape_size * sizeof(uint8_t));
if (status != HAILO_SUCCESS) {
printf("-E- hailo_stream_sync_write_all_raw_buffer failed");
break;
}
}
write_args->status = status;
write_args->num_images = counter;
return NULL;
}
void* _recv_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
recv_thread_args_t *recv_args = (recv_thread_args_t *)args;
struct timespec ts;
ofstream outFile;
int lat_counter = 0;
int counter = 1;
string detection;
std::vector<uint8_t> recv_array;
printf("-I- Recv thread %d started\n", recv_args->tid);
if (recv_args->write_log==1) {
char *log_name = (char*)malloc(20 * sizeof(char));
sprintf(log_name, "tid_%d.log", recv_args->tid);
outFile = ofstream("rx_images.cpp.txt");
free(log_name);
}
recv_array.resize(recv_args->output_shape_size);
while (true) {
status = hailo_stream_sync_read_all_raw_buffer(recv_args->output_stream, recv_array.data(), 0, recv_args->output_shape_size * sizeof(uint8_t));
if (status != HAILO_SUCCESS) {
cout << "-E- hailo_stream_sync_read_all_raw_buffer failed" << endl;
break;
}
clock_gettime(CLOCK_REALTIME, &ts);
std::vector<float32_t> float32_tVec(recv_array.begin(), recv_array.end());
detection = classification_post_process(float32_tVec, 1);
printf("-I- [%10ld.%ld s] TID:%d Recv %3d: %s\n", (long)ts.tv_sec, ts.tv_nsec/1000000, recv_args->tid, counter, detection.c_str());
if (counter>10 && lat_counter < LATENCY_MEASUREMENTS) {
clock_gettime(CLOCK_REALTIME, &ts);
recv_clock_t[recv_args->tid][lat_counter++] = ts;
recv_args->lat_counter = lat_counter;
}
counter++;
if (recv_args->write_log==1) {
outFile << "RX " << counter << endl;
for (const auto &val : recv_array) outFile << val << " ";
outFile << endl;
}
}
recv_args->status = status;
return (void *)status;
}
bool source_is_video(string& path) {
const vector<string> suffixs = {"mkv", "avi", "webm"};
for (string suffix : suffixs) {
if (regex_search(path, regex(string(suffix) + "$")))
return true;
}
return false;
}
hailo_status infer(
hailo_input_stream input_stream, hailo_stream_info_t *all_stream_info,
hailo_output_stream *output_streams, int output_stream_cnt, int* num_imgs, int write_log,
string video_path, int* lat_counter, size_t input_size, size_t* output_size)
{
hailo_status status = HAILO_SUCCESS;
pthread_t write_thread = 1;
recv_thread_args_t recv_args[NOF_STREAMS-1];
video_thread_args_t video_args;
pthread_t recv_threads[NOF_STREAMS-1];
pthread_t video_thread = 2;
write_thread_args_t write_args;
write_args.input_stream_info = &all_stream_info[0];
write_args.input_stream = input_stream;
write_args.status = HAILO_SUCCESS;
write_args.output_streams_cnt = output_stream_cnt;
write_args.input_shape_size = input_size;
write_args.num_images = 0;
video_args.input_stream_info = &all_stream_info[0];
video_args.video_path = video_path.c_str();
for (int ii=0; ii<output_stream_cnt; ii++) {
recv_args[ii].output_stream_info = &all_stream_info[ii+1];
recv_args[ii].output_stream = output_streams[ii];
recv_args[ii].tid = ii;
recv_args[ii].status = HAILO_SUCCESS;
recv_args[ii].lat_counter = 0;
recv_args[ii].write_log = write_log;
recv_args[ii].output_shape_size = output_size[ii];
(void) pthread_create(&recv_threads[ii], NULL, _recv_thread, &recv_args[ii]);
};
if (source_is_video(video_path))
(void) pthread_create(&video_thread, NULL, _video_source_thread, &video_args);
else
(void) pthread_create(&video_thread, NULL, _frame_lib_thread, &video_args);
(void) pthread_create(&write_thread, NULL, _send_thread, &write_args);
pthread_join(video_thread, NULL);
pthread_join(write_thread, NULL);
if (HAILO_SUCCESS != write_args.status) {
printf("-E- write_thread failed\n");
status = HAILO_INTERNAL_FAILURE;
}
for (int ii=0; ii<output_stream_cnt; ii++) {
pthread_cancel(recv_threads[ii]);
printf("-I- Sending SIGSTOP to Recv thread #%d status=%d\n", recv_args[ii].tid, recv_args[ii].status);
if (HAILO_SUCCESS != recv_args[ii].status) {
printf("-E- Recv thread %d failed\n", recv_args[ii].tid);
status = HAILO_INTERNAL_FAILURE;
}
}
*num_imgs = write_args.num_images;
*lat_counter = recv_args[0].lat_counter;
return status;
}
double get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (ts.tv_nsec / 1000000));
return result;
}
double calc_latency(int count, int lat_counter) {
double result = 0;
double cur_rcv;
double cur_snd;
for (int j=0; j<LATENCY_MEASUREMENTS; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
result += (cur_rcv - cur_snd);
}
return result/lat_counter;
}
void print_inference_stats(struct timespec start_time, struct timespec end_time, hailo_stream_info_t *all_stream_infos, int output_stream_cnt,
int num_images, int lat_counter, size_t input_size, size_t* output_size) {
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
uint32_t send_frame_size = input_size;
uint32_t recv_frame_size = 0;
printf(BOLDGREEN);
printf("-I-----------------------------------------------\n");
printf("-I- Total time: %4.2lf sec\n", infer_time_secs);
printf("-I- Average FPS: %4.2lf\n", num_images / infer_time_secs);
printf("-I- Average Latency: %3.2lf ms\n", calc_latency(output_stream_cnt, lat_counter));
printf("-I- Send data rate: %-4.2lf Mbit/s\n",
(double)(num_images) * send_frame_size * mbit_per_byte / infer_time_secs);
for (int i=1; i<=output_stream_cnt; i++) {
recv_frame_size = output_size[i]; //hw_frame_size;
printf("-I- Recv[%d] data rate: %-4.2lf Mbit/s\n", i,
(double)(num_images) * recv_frame_size * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
const char** get_jlf_files_form_path(const char *dir_name, uint8_t *actual_number_of_jlfs_files) {
static char jlf_files[HAILO_MAX_NUMBER_OF_JLFS][PATH_MAX];
static const char *res_jlf_files[HAILO_MAX_NUMBER_OF_JLFS];
DIR *dir = NULL;
struct dirent *entry = NULL;
uint8_t i = 0;
dir = opendir(dir_name);
if (NULL == dir) {
return NULL;
}
entry = readdir(dir);
while (NULL != entry) {
if (entry->d_name[0] != '.') {
(void)snprintf(jlf_files[i], sizeof(jlf_files[i]), "%s%s", dir_name, entry->d_name);
res_jlf_files[i] = jlf_files[i];
i++;
}
entry = readdir(dir);
}
(void) closedir(dir);
*actual_number_of_jlfs_files = i;
return res_jlf_files;
}
const char* get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
void print_net_banner(hailo_stream_info_t *all_stream_infos, int cnt) {
printf(BOLDCYAN);
printf("-I-----------------------------------------------\n");
for (int ii=0; ii<cnt; ii++) {
printf("-I- %s[%d]: %s (%d, %d, %d) index:%d\n", get_direction_name(all_stream_infos[ii].direction), ii, all_stream_infos[ii].name, all_stream_infos[ii].shape.height, all_stream_infos[ii].shape.width,
all_stream_infos[ii].shape.features, all_stream_infos[0].index);
}
printf("-I-----------------------------------------------\n");
printf(RESET);
}
hailo_status print_debug_stats(hailo_device device) {
uint32_t address;
uint8_t* data = (uint8_t*)malloc(4);
uint32_t size = 4;
hailo_status status = HAILO_SUCCESS;
// rx_jabbers
address = 0x0010918C;
status = hailo_read_memory(device, address, data, size);
printf("\033[1;31m");
printf("-I-----------------------------------------------\n");
printf("-D- RX_JABBERS: 0x%d\n", *data);
// fcs_errors
address = 0x00109190;
status = hailo_read_memory(device, address, data, size);
printf("-D- FCS_ERRORS: 0x%d\n", *data);
printf("-I-----------------------------------------------\n");
printf(RESET);
return status;
}
hailo_status activate_input_stream(hailo_stream_info_t info, hailo_input_stream& input_stream, hailo_device device, hailo_jlf jlf, string iface, size_t* input_size) {
hailo_status status = HAILO_SUCCESS;
hailo_eth_input_stream_params_t input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
hailo_pcie_input_stream_params_t pcie_input_stream_params = HAILO_PCIE_STREAM_PARAMS_DEFAULT;
if (info.format.order == HAILO_FORMAT_ORDER_NC) {
input_stream_params.base_params.user_buffer_format.order = info.format.order;
pcie_input_stream_params.base_params.user_buffer_format.order = info.format.order;
}
cout << "-I- Setting input format.order to: " << input_stream_params.base_params.user_buffer_format.order << endl;
if (iface.compare("pcie") == 0) {
status = hailo_create_pcie_input_stream_from_jlf_by_index(device, jlf, info.index, &pcie_input_stream_params, &input_stream);
*input_size = hailo_get_host_frame_size(&info, &pcie_input_stream_params.base_params);
} else {
status = hailo_create_eth_input_stream_from_jlf_by_index(device, jlf, info.index, &input_stream_params, &input_stream);
*input_size = hailo_get_host_frame_size(&info, &input_stream_params.base_params);
}
status = hailo_activate_input_stream(device, input_stream);
return status;
}
hailo_status activate_output_stream(hailo_stream_info_t info, hailo_output_stream& output_stream, hailo_device device, hailo_jlf jlf, string iface, size_t* output_size) {
hailo_status status = HAILO_SUCCESS;
hailo_eth_output_stream_params_t output_stream_params = HAILO_ETH_OUTPUT_STREAM_PARAMS_DEFAULT;
hailo_pcie_output_stream_params_t pcie_output_stream_params = HAILO_PCIE_STREAM_PARAMS_DEFAULT;
if (info.format.order == HAILO_FORMAT_ORDER_NC ||
info.format.order == HAILO_FORMAT_ORDER_NHW ||
info.format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
output_stream_params.base_params.user_buffer_format.order = info.format.order;
pcie_output_stream_params.base_params.user_buffer_format.order = info.format.order;
}
cout << "-I- Setting output format.order to: " << output_stream_params.base_params.user_buffer_format.order << endl;
if (iface.compare("pcie") == 0) {
status = hailo_create_pcie_output_stream_from_jlf_by_index(device, jlf, info.index, &pcie_output_stream_params, &output_stream);
*output_size = hailo_get_host_frame_size(&info, &pcie_output_stream_params.base_params);
} else {
status = hailo_create_eth_output_stream_from_jlf_by_index(device, jlf, info.index, &output_stream_params, &output_stream);
*output_size = hailo_get_host_frame_size(&info, &output_stream_params.base_params);
}
status = hailo_activate_output_stream(device, output_stream);
return status;
}
int main(int argc, char **argv) {
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
hailo_eth_device_info_t device_info = {0};
hailo_pcie_device_info_t pcie_device_info = {0};
hailo_device device = NULL;
hailo_jlf jlf = NULL;
uint8_t jlf_buffer[48*1024];
uint8_t actual_number_of_jlfs_files = 0;
hailo_input_stream input_stream = NULL;
hailo_output_stream output_streams[NOF_STREAMS];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
size_t host_input_frame_size = 0;
size_t host_output_frame_size[NOF_STREAMS];
const char **jlf_files = NULL;
struct timespec start_time = {0};
struct timespec end_time = {0};
size_t number_of_streams = 0;
int output_stream_cnt = 0;
string jlf_dir = "./JLFs/";
int opt;
string iface = "pcie";
string video;
int lat_counter = 0;
int num_img = 0;
int debug = 0;
int write_log = 0;
while ((opt = getopt(argc, argv, "i:j:v:dl")) != -1) {
switch (opt) {
case 'j': jlf_dir = optarg; break;
case 'i': iface = optarg; break;
case 'd': debug = 1; break;
case 'v': video = optarg; break;
case 'l': write_log = 1; break;
case '?': fprintf (stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -j JLF-DIR -v Path/to/video\n\n", argv[0]);
fprintf(stderr, " -i INTERFACE The device interface, defaults to \'pcie\', for Ethernet put the host interface\n");
fprintf(stderr, " -j JLF-DIR The JLFs directory, defaults to \'./JLFs/\'\n");
fprintf(stderr, " -v Path/to/Video The path to the video file\n");
fprintf(stderr, " -d Read and print debug registers from FW\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
exit(EXIT_FAILURE);
}
}
printf(BOLDCYAN);
printf("-I- Running on interface: %s \n", iface.c_str());
printf("-I- Reading JLFs from: %s\n", jlf_dir.c_str());
printf(RESET);
if (iface.compare("pcie") == 0) {
status = hailo_scan_pcie_devices(&pcie_device_info, 1, &number_of_devices);
} else {
status = hailo_scan_ethernet_devices((char *)iface.c_str(), &device_info, 1, &number_of_devices, HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
}
if (0 == number_of_devices || status != HAILO_SUCCESS) {
printf("-E- No device found on the given interface\n");
return status;
}
if (iface.compare("pcie") == 0) {
status = hailo_create_pcie_device(&pcie_device_info, &device);
} else {
status = hailo_create_ethernet_device(&device_info, &device);
}
if (status != HAILO_SUCCESS) {
printf("-E- Failed to create eth_device\n");
return status;
}
jlf_files = get_jlf_files_form_path((char *)jlf_dir.c_str(), &actual_number_of_jlfs_files);
if (NULL == jlf_files) {
printf("-E- Failed to get jlf files from path\n");
(void) hailo_release_device(device);
return status;
}
status = hailo_create_jlf_files(jlf_files, actual_number_of_jlfs_files, jlf_buffer, sizeof(jlf_buffer), &jlf);
if (status != HAILO_SUCCESS) {
printf("-E- Failed to create jlf files\n");
(void) hailo_release_device(device);
return status;
}
status = hailo_configure_device_from_jlf(device, jlf, jlf_buffer, sizeof(jlf_buffer));
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to configure device from jlf");
// NEDEN
status = hailo_jlf_get_all_stream_infos(jlf, all_stream_infos, NOF_STREAMS, &number_of_streams);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to get all stream info");
for (size_t i=0;i<number_of_streams;i++) {
if (all_stream_infos[i].direction==HAILO_H2D_STREAM) {
activate_input_stream(all_stream_infos[i], input_stream, device, jlf, iface, &host_input_frame_size);
} else {
activate_output_stream(all_stream_infos[i], output_streams[output_stream_cnt], device, jlf, iface, &host_output_frame_size[output_stream_cnt]);
output_stream_cnt++;
}
}
if (status != HAILO_SUCCESS) {
printf("-E- Failed to activate streams\n");
return status;
}
print_net_banner(all_stream_infos, number_of_streams);
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
status = infer(input_stream, all_stream_infos, output_streams, output_stream_cnt, &num_img, write_log, video, &lat_counter, host_input_frame_size, host_output_frame_size);
REQUIRE_SUCCESS(status, l_release_output_stream, "Inference failure");
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
print_inference_stats(start_time, end_time, all_stream_infos, output_stream_cnt, num_img, lat_counter, host_input_frame_size, host_output_frame_size);
status = HAILO_SUCCESS;
l_release_output_stream:
for (int i=0;i<output_stream_cnt;i++) {
(void) hailo_release_output_stream(device, output_streams[i]);
}
if (debug==1) {
print_debug_stats(device);
REQUIRE_SUCCESS(status, l_release_input_stream, "Failed to read debug registers");
}
l_release_input_stream:
(void) hailo_release_input_stream(device, input_stream);
l_release_jlf:
(void) hailo_release_jlf(jlf);
(void) hailo_release_device(device);
return status;
}
#define FREE(var) \
do { \
if (NULL != (var)) { \
free(var); \
var = NULL; \
} \
} while(0)
#define REQUIRE_SUCCESS(status, label, msg) \
do \
{ \
if (HAILO_SUCCESS != (status)) \
{ \
printf(BOLDRED); \
printf("-E- %s : (%d)\n",msg, status); \
printf(RESET); \
goto label; \
} \
} while(0)
#define RESET "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
typedef struct write_thread_args_t {
hailo_stream_info_t *input_stream_info;
hailo_input_stream input_stream;
hailo_status status;
int output_streams_cnt;
int num_images;
} write_thread_args_t;
typedef struct video_thread_args_t {
hailo_stream_info_t *input_stream_info;
const char *video_path;
int num_images;
} video_thread_args_t;
typedef struct post_infer_thread_args_t {
hailo_output_stream output_stream;
hailo_stream_info_t *stream_info;
int tid;
int num_streams;
} post_infer_thread_args_t;
typedef struct recv_thread_args_t {
hailo_stream_info_t *output_stream_info;
hailo_output_stream output_stream;
hailo_status status;
int tid;
int lat_counter;
int num_streams;
int write_log;
int num_images;
} recv_thread_args_t;
\ No newline at end of file
#define FREE(var) \
do { \
if (NULL != (var)) { \
free(var); \
var = NULL; \
} \
} while(0)
#define REQUIRE_SUCCESS(status, label, msg) \
do \
{ \
if (HAILO_SUCCESS != (status)) \
{ \
printf(BOLDRED); \
printf("-E- %s : (%d)\n",msg, status); \
printf(RESET); \
goto label; \
} \
} while (0)
#define RESET "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
typedef struct write_thread_args_t {
hailo_stream_info_t *input_stream_info;
hailo_input_stream input_stream;
hailo_status status;
int output_streams_cnt;
int num_images;
size_t input_shape_size;
} write_thread_args_t;
typedef struct video_thread_args_t {
hailo_stream_info_t *input_stream_info;
const char *video_path;
int num_images;
} video_thread_args_t;
typedef struct post_infer_thread_args_t {
hailo_output_stream output_stream;
hailo_stream_info_t *stream_info;
int tid;
int num_streams;
} post_infer_thread_args_t;
typedef struct recv_thread_args_t {
hailo_stream_info_t *output_stream_info;
hailo_output_stream output_stream;
hailo_status status;
int tid;
int lat_counter;
int num_streams;
int write_log;
size_t output_shape_size;
} recv_thread_args_t;
// http://www.jclay.host/dev-journal/simple_cpp_argmax_argmin.html
template <typename T, typename A>
int argmax(std::vector<T, A> const& vec) {
return static_cast<int>(std::distance(vec.begin(), max_element(vec.begin(), vec.end())));
}
template <typename T, typename A>
std::vector<T, A> softmax(std::vector<T, A> const& vec) {
std::vector<T, A> result;
float m = -INFINITY;
float sum = 0.0;
for (const auto &val : vec) m = (val>m) ? val : m;
for (const auto &val : vec) sum += expf(val - m);
for (const auto &val : vec) result.push_back(expf(val-m)/sum);
return result;
}
\ No newline at end of file
cmake_minimum_required(VERSION 3.1)
project(cpp_agent)
message(STATUS "HAILORT_ROOT: $ENV{HAILORT_ROOT}")
set(HAILORT_ROOT $ENV{HAILORT_ROOT})
set(HAILORT_LIB $ENV{HAILORT_ROOT}/lib/${ARCH}/libhailort.so.$ENV{LIB_VER})
set(HAILORT_INCLUDE_DIR "$ENV{HAILORT_ROOT}/include")
set(COMPILE_OPTIONS_CPP -Werror -g -O0 -std=c++2a)
set(COMPILE_OPTIONS_CPP -Wall -Werror -O3 -DNDEBUG -std=c++2a)
include_directories(${HAILORT_INCLUDE_DIR} ./)
find_package(Threads)
find_package( OpenCV REQUIRED )
foreach(target runme.$ENV{LIB_VER})
add_executable(${target} example_device.cpp main.cpp)
# https://github.com/llohse/libnpy
target_include_directories(${target} PUBLIC /home/nadave/repos/libnpy)
target_compile_options(${target} PRIVATE ${COMPILE_OPTIONS_CPP})
target_link_libraries(${target} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${target} ${HAILORT_LIB})
target_link_libraries(${target} ${OpenCV_LIBS})
endforeach(target)
1. Dependencies:
1. OpenCV
`sudo apt-get install -y libopencv-dev`
`sudo apt-get install gcc-9 g++-9`
Install libnpy, if you want debug capability
git clone https://github.com/llohse/libnpy.git
2. Set HAILORT_ROOT environment variable, e.g.:
export HAILORT_ROOT=~/SDK/3.7.0/platform/hailort
2. Build the project
build.sh
#!/bin/bash
declare -A COMPILER=( [x86_64]=/usr/bin/gcc
[aarch64]=/usr/bin/aarch64-linux-gnu-gcc
[armv7l]=/usr/bin/arm-linux-gnueabi-gcc )
HAILORT_ROOT=/home/nadave/SDK/platform-sw/hailort
HAILORT_ROOT=/local/users/nadave/SDK/3.9.0/platform/hailort
for ARCH in x86_64
do
echo "-I- Building ${ARCH}"
mkdir -p build/${ARCH}
export CXX=g++-9
LIB_VER=2.9.0 HAILORT_ROOT=${HAILORT_ROOT} cmake -H. -Bbuild/${ARCH} -DARCH=${ARCH} -DCMAKE_C_COMPILER=${COMPILER[${ARCH}]}
cmake --build build/${ARCH}
done
if [[ -f "hailort.log" ]]; then
rm hailort.log
fi
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <thread>
#include <vector>
#include <regex>
#include <chrono>
#include <future>
#include <fstream>
#include <memory>
#include <example_device.hpp>
#include <example_utils.hpp>
#include <hailo/hailort.h>
#include <yolov5_processing.hpp>
#ifdef DEBUG
#include "npy.hpp"
#endif
using namespace std;
example_device::example_device(std::string& iface, std::string& hef_file, unsigned int num_imgs, int write_log, bool yolo_post, std::string source) {
cout << CYAN
<< "-I- Running on interface: " << iface << " " << num_imgs << " images" << endl
<< RESET;
example_device::yolo_post = yolo_post;
example_device::iface = iface;
example_device::hef_file = hef_file;
example_device::num_imgs = num_imgs;
example_device::write_log = write_log;
example_device::output_stream_cnt = NOF_STREAMS;
example_device::input_stream_cnt = 1;
example_device::source_path = source;
active_net_g = NULL;
if (yolo_post) {
qp_zp_scale = {0};
use_one_rx_thrd = true;
}
}
void example_device::init_qp_zp_struct() {
qp_zp_scale.qp_scale_1 = all_stream_infos[1].quant_info.qp_scale;
qp_zp_scale.qp_scale_2 = all_stream_infos[2].quant_info.qp_scale;
qp_zp_scale.qp_scale_3 = all_stream_infos[3].quant_info.qp_scale;
qp_zp_scale.qp_zp_1 = all_stream_infos[1].quant_info.qp_zp;
qp_zp_scale.qp_zp_2 = all_stream_infos[2].quant_info.qp_zp;
qp_zp_scale.qp_zp_3 = all_stream_infos[3].quant_info.qp_zp;
}
example_device::~example_device() {}
void example_device::print_net_banner() {
printf(GREEN);
printf("-I-----------------------------------------------\n");
for (size_t ii=0; ii<output_stream_cnt+input_stream_cnt; ii++) {
printf("-I- %s[%ld]: %s (%d, %d, %d)\n", get_direction_name(all_stream_infos[ii].direction), ii, all_stream_infos[ii].name, all_stream_infos[ii].shape.height, all_stream_infos[ii].shape.width,
all_stream_infos[ii].shape.features);
}
printf("-I-----------------------------------------------\n");
printf(RESET);
}
double example_device::get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (ts.tv_nsec / 1000000));
return result;
}
hailo_status example_device::create_eth_device() {
hailo_status status = HAILO_SUCCESS;
size_t number_of_devices = 0;
try {
status = hailo_scan_ethernet_devices(iface.c_str(), &device_info, 1, &number_of_devices, HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
if (0 == number_of_devices) {
cout << "-E- No device found on the given interface:" << iface << endl;
status = HAILO_INTERNAL_FAILURE;
}
if (status != HAILO_SUCCESS) return status;
status = hailo_create_ethernet_device(&device_info, &device);
if (status != HAILO_SUCCESS) return status;
} catch (std::exception const& e) {
std::cout << "-E- create device failed" << e.what() << std::endl;
return HAILO_INTERNAL_FAILURE;
}
return status;
}
hailo_status example_device::create_pcie_device() {
hailo_status status = HAILO_SUCCESS;
size_t number_of_devices = 0;
try {
status = hailo_scan_pcie_devices(pcie_device_info, NOF_DEVICES, &number_of_devices);
if (0 == number_of_devices) {
cout << "-E- No device found on the given interface:" << iface << endl;
status = HAILO_INTERNAL_FAILURE;
}
if (status != HAILO_SUCCESS) return status;
status = hailo_create_pcie_device(pcie_device_info, &device);
if (status != HAILO_SUCCESS) return status;
} catch (std::exception const& e) {
std::cout << "-E- create device failed" << e.what() << std::endl;
return HAILO_INTERNAL_FAILURE;
}
return status;
}
hailo_status example_device::print_debug_stats() {
uint32_t address;
std::vector<uint8_t> data(4);
uint32_t size = 4;
hailo_status status = HAILO_SUCCESS;
address = 0x0010918C;// rx_jabbers
status = hailo_read_memory(device, address, data.data(), size);
cout << CYAN
<< "-I-----------------------------------------------" << endl
<< "-D- RX_JABBERS: 0x" << data.data() << endl;
address = 0x00109190;// fcs_errors
status = hailo_read_memory(device, address, data.data(), size);
cout << "-D- FCS_ERRORS: 0x" << data.data() << endl
<< "-I-----------------------------------------------" << endl
<< RESET;
return status;
}
const char* example_device::get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
double example_device::calc_latency(int count) {
double result = 0;
double cur_rcv;
double cur_snd;
for (int j=0; j<LATENCY_MEASUREMENTS; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
result += (cur_rcv - cur_snd);
}
return result/LATENCY_MEASUREMENTS;
}
void example_device::print_inference_stats() {
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
cout << GREEN
<< "-I-----------------------------------------------" << endl
<< "-I- Total time: " << infer_time_secs << endl
<< "-I- Average FPS: " << (num_imgs * input_stream_cnt)/ infer_time_secs << endl
<< "-I- Send data rate: " << (double)(num_imgs) * host_input_frame_size * mbit_per_byte / infer_time_secs << " Mbit/s" << endl;
for (size_t i=0;i<output_stream_cnt;i++) {
printf("-I- Recv[%ld] data rate: %-4.2lf Mbit/s\n", i,
(double)(num_imgs) * host_output_frame_size[i] * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
template<class T>
void example_device::_send_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
std::vector<T> src_data;
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
struct timespec ts;
src_data.resize(write_args->host_input_frame_size);
if (src_data.empty()) {
cout << "-E- Failed to allocate buffers" << endl;
status = HAILO_OUT_OF_HOST_MEMORY;
} else {
for(size_t i = 0; i < write_args->host_input_frame_size; i++) {
src_data[i] = (T)(rand() % 256);
}
flag_100 = (uint32_t)write_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
for (uint32_t i = 1; i <= (uint32_t)write_args->num_images; i++) {
if ((i % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Send frame [%3d/%3d]\n", (long)ts.tv_sec, ts.tv_nsec/1000000, write_args->tid, i, write_args->num_images);
sent_clock_t[lat_counter++] = ts;
}
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream,
src_data.data(),
0,
write_args->host_input_frame_size);
if (status != HAILO_SUCCESS) {
cout << "-E- hailo_stream_sync_write_all_raw_buffer failed" << endl;
break;
}
}
}
write_args->status = status;
}
template<class T>
void example_device::_recv_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
recv_thread_args_t *recv_args = (recv_thread_args_t *)args;
struct timespec ts;
ofstream outFile;
std::vector<T> recv_array;
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
cout << CYAN << "-I- Recv thread " << recv_args->tid << " started" << RESET << endl;
if (yolo_post)
cout << CYAN << "-I- Recv thread: Doing YOLOv5 post-processing" << RESET << endl;
if (recv_args->write_log==1) {
string log_name = "rx_tid_0.log";
outFile = ofstream(log_name);
}
flag_100 = (uint32_t)recv_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
recv_array.resize(recv_args->host_output_frame_size);
for (uint32_t j = 1; j <= (uint32_t)recv_args->num_images; j++) {
status = hailo_stream_sync_read_all_raw_buffer(recv_args->output_stream, recv_array.data(), 0, recv_args->host_output_frame_size);
REQUIRE_SUCCESS(status, l_exit, "Failed at hailo_stream_sync_read_all_raw_buffer");
if ((j % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Recv [%3d/%3d] \n", (long)ts.tv_sec, ts.tv_nsec/1000000, recv_args->tid, j, recv_args->num_images);
recv_clock_t[recv_args->tid][lat_counter++] = ts;
}
}
l_exit:
recv_args->status = status;
}
void* example_device::_send_from_source_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
// unsigned lat_counter = 0;
struct timespec ts;
cv::Mat curr_img(all_stream_infos->shape.width, all_stream_infos->shape.width, CV_8UC3);
int counter = 0;
vector<uint8_t> array;
array.resize(host_input_frame_size);
while (true) {
if (input_image_queue.empty()) {
cout << "-I- Waiting for the image queue to fill" << endl;
sleep(1);
continue;
}
pthread_mutex_lock(&input_image_queue_m);
curr_img = input_image_queue.front();
input_image_queue.pop();
pthread_mutex_unlock(&input_image_queue_m);
if (counter % 500==0) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] Send frame [%3d] 0x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, counter, curr_img.data[0], curr_img.data[1]);
}
counter++;
if (curr_img.data[0] == 17 && curr_img.data[1] == 71 && curr_img.data[2] == 17 && curr_img.data[3] == 71) {
cout << "-I- [TX-Thread] Received stop pattern - " << counter << endl;
sleep (1);
break;
}
if (curr_img.isContinuous()) {
int totalsz = curr_img.dataend-curr_img.datastart;
array.assign(curr_img.datastart, curr_img.datastart + totalsz);
} else {
int rowsz = CV_ELEM_SIZE(curr_img.type()) * curr_img.cols;
for (int i = 0; i < curr_img.rows; ++i) {
array.insert(array.end(), curr_img.ptr<uint8_t>(i), curr_img.ptr<uint8_t>(i) + rowsz);
}
}
status = hailo_stream_sync_write_all_raw_buffer(input_stream, array.data(), 0, host_input_frame_size);
if (status != HAILO_SUCCESS) {
printf("-E- hailo_stream_sync_write_all_raw_buffer failed");
break;
}
}
write_args->status = status;
write_args->num_images = counter;
return NULL;
}
template<class T>
void example_device::_recv_thread1(std::future<void> &futureObj) {
hailo_status status = HAILO_SUCCESS;
std::vector< std::vector<T> > recv_array;
size_t counter = 0;
if (yolo_post)
cout << CYAN << "-I- Recv thread: Doing YOLOv5 post-processing" << RESET << endl;
recv_array.resize(output_stream_cnt);
for (size_t i=0; i<output_stream_cnt;++i)
recv_array[i].resize(host_output_frame_size[i]);
while (true) {
for (size_t i=0; i<output_stream_cnt;++i) {
status = hailo_stream_sync_read_all_raw_buffer(output_streams[i], recv_array[i].data(), 0, host_output_frame_size[i]);
if (status==HAILO_PCIE_DRIVER_FAIL) goto l_exit;
REQUIRE_SUCCESS(status, l_exit, "Failed at hailo_stream_sync_read_all_raw_buffer");
}
#ifdef DEBUG
size_t shape2 [] = {20, 20, 255};
cout << "-I- Saving logit ouput2 to cpp-output-2.npy" << endl;
npy::SaveArrayAsNumpy("cpp-output-2.npy", false, 3, shape2, recv_array[2]);
size_t shape1 [] = {40, 40, 255};
cout << "-I- Saving logit ouput1 to cpp-output-1.npy" << endl;
npy::SaveArrayAsNumpy("cpp-output-1.npy", false, 3, shape1, recv_array[1]);
size_t shape0 [] = {80, 80, 255};
cout << "-I- Saving logit ouput0 to cpp-output-0.npy" << endl;
npy::SaveArrayAsNumpy("cpp-output-0.npy", false, 3, shape0, recv_array[0]);
#endif
vector<float32_t> detections;
auto num_dets = get_detections(recv_array[0], recv_array[1], recv_array[2], qp_zp_scale, 0.2, detections);
if (num_dets > 0) {
#ifdef DBEUG
cout << "-I- Saving the detections to cpp_detections.npy: " << endl;
size_t shape [] = {4, 1};
npy::SaveArrayAsNumpy("cpp_detections.npy", false, 2, shape, detections);
#endif
cout << "-I- Num detections: " << num_dets << " Classes: [";
for (size_t i = 0; i < num_dets;i++)
cout << get_coco_name_from_int(detections[i*6+4]) << " ";
cout << "]" << endl;
}
counter++;
if (counter%100 == 0)
cout << CYAN << "-I- Received frame #"<< counter << RESET << endl;
}
l_exit:
cout << CYAN << "-I- Exit Recv thread code:"<< status << RESET << endl;
}
bool example_device::source_is_video(string& path) {
const vector<string> suffixs = {"mkv", "avi", "webm", "mp4"};
for (string suffix : suffixs) {
if (regex_search(path, regex(string(suffix) + "$")))
return true;
}
return false;
}
void* example_device::_frame_lib_thread(void *args) {
video_thread_args_t *v_args = (video_thread_args_t*)args;
cv::Mat org_frame;
vector< cv::String > file_names;
cv::Mat pp_frame(v_args->input_stream_info->hw_shape.height, v_args->input_stream_info->hw_shape.height, CV_8UC3);
unsigned int idx=0;
cv::Size input_size;
cout << BOLDCYAN << "-I-----------------------------------------------" << endl
<< "-I- [Frames-thread] Source: " << v_args->video_path << endl
<< "-I- [Frames-thread] Net input shape (" << v_args->input_stream_info->hw_shape.height <<
", " << v_args->input_stream_info->hw_shape.height <<
", " << v_args->input_stream_info->hw_shape.features << ")" << endl
<< "-I-----------------------------------------------"
<< RESET << endl;
cv::glob(v_args->video_path, file_names, false);
input_size.width = v_args->input_stream_info->hw_shape.width;
input_size.height = v_args->input_stream_info->hw_shape.height;
for (std::string file : file_names) {
if (not(file.ends_with(".jpg") || file.ends_with(".png"))) {
continue;
}
org_frame = cv::imread(file);
if (org_frame.channels() == 3) {
cv::cvtColor(org_frame, org_frame, cv::COLOR_BGR2RGB);
}
cout << "-I- [Frames-thread] Getting frame #"<< idx++ << ":" << file << endl;
// size_t shape [] = {640, 640, 3};
pp_frame = yolov5_pre_process(org_frame);
#ifdef DEBUG
cout << "-I- Saving the preprocessed image to cpp-prep-image.npy" << endl;
size_t shape [] = {640, 640, 3};
std::vector<float> image;
int totalsz = pp_frame.dataend-pp_frame.datastart;
image.assign(pp_frame.datastart, pp_frame.datastart + totalsz);
npy::SaveArrayAsNumpy("cpp-prep-image.npy", false, 3, shape, image);
#endif
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame.clone());
pthread_mutex_unlock(&input_image_queue_m);
}
// Mark the final frame
pp_frame.data[0] = 17;
pp_frame.data[1] = 71;
pp_frame.data[2] = 17;
pp_frame.data[3] = 71;
idx++;
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame.clone());
pthread_mutex_unlock(&input_image_queue_m);
cout << BOLDCYAN << "-I-----------------------------------------------" << endl
<< "-I- [Frames-thread] FINISHED READING DIR - #" << idx-1 << endl
<< "-I-----------------------------------------------"
<< RESET << endl;
return NULL;
}
void* example_device::_video_source_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
video_thread_args_t *v_args = (video_thread_args_t*)args;
cv::Mat org_frame;
cv::Mat pp_frame(v_args->input_stream_info->hw_shape.height, v_args->input_stream_info->hw_shape.height, CV_8UC3);
unsigned int idx=0;
cv::VideoCapture cap(v_args->video_path);
if (!cap.isOpened()) {
cout << "-E- Unable to open video stream" << endl;
status = HAILO_INTERNAL_FAILURE;
}
// cv::Size shape = cv::Size((int) cap.get(CV_CAP_PROP_FRAME_WIDTH), (int) cap.get(CV_CAP_PROP_FRAME_HEIGHT));
cout << BOLDCYAN << "-I-----------------------------------------------" << endl;
cout << "-I- [Video-thread] Source: " << v_args->video_path << endl;
cout << "-I- [Frames-thread] Net input shape (" << v_args->input_stream_info->hw_shape.height <<
", " << v_args->input_stream_info->hw_shape.height <<
", " << v_args->input_stream_info->hw_shape.features << ")" << endl;
cout << "-I-----------------------------------------------" << RESET << endl;
while (true && status==HAILO_SUCCESS) {
if (++idx%500==0)
cout << "-I- [Video-thread] Getting frame: "<< idx << endl;
cap >> org_frame;
if (org_frame.empty())
break;
resize(org_frame, pp_frame, pp_frame.size());
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame.clone());
pthread_mutex_unlock(&input_image_queue_m);
}
// Mark the final frame
pp_frame.data[0] = 17;
pp_frame.data[1] = 71;
pp_frame.data[2] = 17;
pp_frame.data[3] = 71;
idx++;
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame);
pthread_mutex_unlock(&input_image_queue_m);
cout << BOLDCYAN << "-I-----------------------------------------------" << endl;
cout << "-I- [Video-thread] FINISHED MOVIE STREAM - " << idx-1 << endl;
cout << "-I-----------------------------------------------" << RESET << endl;
cap.release();
return (void *)status;
}
template<class T>
hailo_status example_device::infer() {
hailo_status status = HAILO_SUCCESS;
std::vector<std::thread> recv_threads;
std::vector<std::thread> write_threads;
std::thread source_thread;
std::vector<recv_thread_args_t> recv_args;
std::vector<write_thread_args_t> write_args;
video_thread_args_t source_args;
std::promise<void> exitSignal;
std::future<void> futureObj = exitSignal.get_future();
write_threads.resize(input_stream_cnt);
write_args.resize(input_stream_cnt);
source_args.input_stream_info = &all_stream_infos[0];
source_args.video_path = source_path.c_str();
if (yolo_post) {
cout << CYAN << "-I- Creating YOLOv5 threads scheme (1\\1\\1)" << RESET << endl;
if (source_is_video(source_path))
source_thread = std::thread(&example_device::_video_source_thread, this, &source_args);
else
source_thread = std::thread(&example_device::_frame_lib_thread, this, &source_args);
write_threads[0] = std::thread(&example_device::_send_from_source_thread, this, &write_args[0]);
recv_threads.resize(1);
recv_threads[0] = std::thread(&example_device::_recv_thread1<T>, this, std::ref(futureObj));
recv_threads[0].detach();
} else {
for (size_t s=0;s<input_stream_cnt;s++) {
write_args[s].tid = s;
write_args[s].input_stream = input_stream;
write_args[s].status = HAILO_SUCCESS;
write_args[s].output_streams_cnt = output_stream_cnt;
write_args[s].num_images = num_imgs;
write_args[s].stream_info = all_stream_infos[s];
write_args[s].host_input_frame_size = host_input_frame_size;
write_threads[s] = std::thread(&example_device::_send_thread<T>, this, &write_args[s]);
}
recv_args.resize(output_stream_cnt);
recv_threads.resize(output_stream_cnt);
for (size_t s=0;s<output_stream_cnt;s++) {
cout << CYAN << "-I- Creating RECV Thread #" << s << RESET << endl;
recv_args[s].output_stream = output_streams[s];
recv_args[s].tid = s;
recv_args[s].status = HAILO_SUCCESS;
recv_args[s].num_images = num_imgs;
recv_args[s].write_log = write_log;
recv_args[s].stream_info = all_stream_infos[s+1];
recv_args[s].host_output_frame_size = host_output_frame_size[s];
recv_threads[s] = std::thread(&example_device::_recv_thread<T>, this, &recv_args[s]);
}
}
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
if (yolo_post)
source_thread.join();
for (auto& t: write_threads) t.join();
cout << CYAN << "-I- Finished 2 all threads" << RESET << endl;
if (yolo_post)
exitSignal.set_value();
// else
for (auto& t: recv_threads) if (t.joinable()) t.join();
cout << CYAN << "-I- Finished all threads" << RESET << endl;
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
for (auto& a: write_args) {
if (HAILO_SUCCESS != a.status) {
cout << "-E- write_thread failed" << endl;
status = HAILO_INTERNAL_FAILURE;
}
}
return status;
}
hailo_status example_device::create_and_load_hef()
{
hailo_status status = HAILO_SUCCESS;
size_t number_of_network_groups = 1;
status = hailo_create_hef_file(&hef, hef_file.c_str());
REQUIRE_SUCCESS(status, l_exit, "Failed to create hef file");
cout << CYAN << "-I- Loading HEF file from " << hef_file << RESET << endl;
status = hailo_configure_device_from_hef(device, hef, &network_group, &number_of_network_groups);
REQUIRE_SUCCESS(status, l_exit, "Failed to configure device from hef");
if (number_of_network_groups > 1) {
status = HAILO_UNINITIALIZED;
cout << "-E- Got network_group=" <<number_of_network_groups << endl;
REQUIRE_SUCCESS(status, l_exit, "Failed to extract network group, larger than 1");
}
l_exit:
return status;
}
template<class T>
hailo_status example_device::set_stream_infos(hailo_input_stream_params_by_name_t *input_stream_params, hailo_output_stream_params_by_name_t *output_stream_params)
{
hailo_status status = HAILO_SUCCESS;
size_t number_of_streams = 0;
bool quantized = false;
hailo_stream_transform_mode_t transform = HAILO_STREAM_TRANSFORM_COPY;
hailo_format_type_t format = HAILO_FORMAT_TYPE_UINT8;
if (std::is_same<T, float32_t>::value)
format = HAILO_FORMAT_TYPE_FLOAT32;
status = hailo_hef_get_all_stream_infos(hef, NULL, all_stream_infos, NOF_STREAMS, &number_of_streams);
REQUIRE_SUCCESS(status, l_exit, "Failed to get pcie_stream_infos");
cout << CYAN << "-I- Activating the input streams with transform=" << transform << ", quantized=" << quantized << RESET << endl;
status = hailo_make_input_stream_params(network_group, transform, quantized, format, input_stream_params, &input_stream_cnt);
REQUIRE_SUCCESS(status, l_exit, "Failed to get input stream params");
// Passing here quantized=true, this is unique to YOLOv5, where the post-processing function will take
// care of the scaling of the output, only on the BOXES that are above the IOU threashold.
format = HAILO_FORMAT_TYPE_UINT8;
quantized = true;
cout << CYAN << "-I- Activating the output streams with transform=" << transform << ", quantized=" << quantized << RESET << endl;
status = hailo_make_output_stream_params(network_group, transform, quantized, format, output_stream_params, &output_stream_cnt);
REQUIRE_SUCCESS(status, l_exit, "Failed to get input stream params");
l_exit:
return status;
}
hailo_status example_device::activate_network_group(hailo_input_stream_params_by_name_t *input_stream_params, hailo_output_stream_params_by_name_t *output_stream_params)
{
hailo_status status = HAILO_SUCCESS;
hailo_network_group_params_t network_group_params;
// for (int i = 0; i < output_stream_cnt;++i)
// output_stream_params[i].params.eth_params.base_params.buffers_threshold = 1;
// input_stream_params->params.eth_params.base_params.buffers_threshold = 1;
status = hailo_activate_network_group(network_group,
&network_group_params,
input_stream_params, // Input params
input_stream_cnt, // number of inputs
output_stream_params, // Output params
output_stream_cnt, // number of ouputs
&active_net_g);
REQUIRE_SUCCESS(status, l_exit, "Failed to activate network group");
l_exit:
return status;
}
template<class T>
hailo_status example_device::setup_device_for_inference() {
hailo_status status = HAILO_SUCCESS;
hailo_input_stream_params_by_name_t input_stream_params = {0};
hailo_output_stream_params_by_name_t output_stream_params[NOF_STREAMS];
if (iface.compare("pcie") == 0) {
status = create_pcie_device();
} else {
status = create_eth_device();
}
if (status!=HAILO_SUCCESS) return status;
status = create_and_load_hef();
if (status != HAILO_SUCCESS) {
cout << "-E- Failed to get all stream info" << endl;
release_hef();
return status;
}
status = set_stream_infos<T>(&input_stream_params, output_stream_params);
REQUIRE_SUCCESS(status, l_exit, "Failed get_stream_infos");
status = activate_network_group(&input_stream_params, output_stream_params);
REQUIRE_SUCCESS(status, l_exit, "Failed activate_network_group");
status = hailo_get_input_stream_by_name(active_net_g, all_stream_infos[0].name, &input_stream);
REQUIRE_SUCCESS(status, l_exit, "Failed get_input_stream_by_name");
host_input_frame_size = hailo_get_input_stream_frame_size(input_stream);
for (size_t i = 0; i < output_stream_cnt; ++i) {
status = hailo_get_output_stream_by_name(active_net_g, all_stream_infos[i+1].name, &output_streams[i]);
REQUIRE_SUCCESS(status, l_exit, "Failed get_output_stream_by_name");
host_output_frame_size[i] = hailo_get_output_stream_frame_size(output_streams[i]);
}
print_net_banner();
l_exit:
return status;
}
void example_device::release_hef() {
(void) hailo_release_hef(example_device::hef);
}
void example_device::release_device() {
(void) hailo_release_device(example_device::device);
}
void example_device::deactivate_network_group() {
(void) hailo_deactivate_network_group(active_net_g);
}
void example_device::run_inference() {
hailo_status status = HAILO_SUCCESS;
status = setup_device_for_inference<uint8_t>();
REQUIRE_SUCCESS(status, l_exit, "setup_device_for_inference failed");
if (yolo_post)
init_qp_zp_struct();
status = infer<uint8_t>();
deactivate_network_group();
example_device::print_inference_stats();
example_device::release_hef();
example_device::release_device();
l_exit:
cout << GREEN << "-I- Finished Gracefully" << RESET << endl;
}
#ifndef _EXAMPLE_DEVICE_H_
#define _EXAMPLE_DEVICE_H_
#include <time.h>
#include <net/if.h>
#include <vector>
#include <memory>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <dirent.h>
#include <linux/limits.h>
#include <example_utils.hpp>
#include <condition_variable>
#include <queue>
#include <future>
#include <opencv2/opencv.hpp>
#include <opencv2/video/video.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <hailo/hailort.h>
#define NOF_STREAMS (6)
#define NOF_DEVICES (2)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
#define MAX_OUTPUT_MUX_INFO_CAPACITY (16)
class example_device
{
private:
hailo_eth_device_info_t device_info;
hailo_pcie_device_info_t pcie_device_info[NOF_DEVICES];
hailo_device device;
hailo_hef hef;
hailo_network_group network_group;
hailo_activated_network_group active_net_g;
hailo_input_stream input_stream;
hailo_output_stream output_streams[NOF_STREAMS];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
struct timespec start_time;
struct timespec end_time;
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
std::string iface;
std::string hef_file;
unsigned int num_imgs;
int write_log;
bool yolo_post;
qp_zp_scale_t qp_zp_scale;
bool use_one_rx_thrd;
std::queue<cv::Mat> input_image_queue;
pthread_mutex_t input_image_queue_m = PTHREAD_MUTEX_INITIALIZER;
// std::queue< std::vector<uint8_t> > post_infer_queue[NOF_STREAMS-1];
// pthread_mutex_t post_infer_queue_m = PTHREAD_MUTEX_INITIALIZER;
void* _frame_lib_thread(void *args);
void* _video_source_thread(void *args);
void* _send_from_source_thread(void *args);
std::string source_path;
bool source_is_video(std::string& path);
template <class T> void _recv_thread1(std::future<void> &futureObj);
void init_qp_zp_struct();
hailo_status create_pcie_device();
hailo_status create_eth_device();
hailo_status print_debug_stats();
template<class T> hailo_status set_stream_infos(hailo_input_stream_params_by_name_t *input_stream_params, hailo_output_stream_params_by_name_t *output_stream_params);
const char* get_direction_name(hailo_stream_direction_t dir);
double calc_latency(int count);
template <class T> void _recv_thread(void *args);
template <class T> void _send_thread(void *args);
template <class T> hailo_status infer();
void deactivate_network_group();
void release_hef();
void release_device();
double get_time_from_ts(struct timespec ts);
public:
size_t output_stream_cnt;
size_t input_stream_cnt;
example_device(std::string& iface, std::string& hef_file, unsigned int num_imgs, int write_log, bool yolo_post, std::string source_path);
~example_device();
hailo_status create_and_load_hef();
void print_net_banner();
void print_inference_stats();
template <class T> hailo_status setup_device_for_inference();
void run_inference();
hailo_status activate_network_group(hailo_input_stream_params_by_name_t *input_stream_params, hailo_output_stream_params_by_name_t *output_stream_params);
size_t host_input_frame_size;
size_t host_output_frame_size[NOF_STREAMS];
};
#endif
#ifndef _EXAMPLE_UTILS_H_
#define _EXAMPLE_UTILS_H_
#include <hailo/hailort.h>
#define FREE(var) \
do \
{ \
if (NULL != (var)) \
{ \
free(var); \
var = NULL; \
} \
} while (0)
#define REQUIRE_SUCCESS(status, label, msg) \
do \
{ \
if (HAILO_SUCCESS != (status)) \
{ \
printf(BOLDRED); \
printf("-E- %s : (%d)\n",msg, status); \
printf(RESET); \
goto label; \
} \
} while (0)
typedef struct write_thread_args_t
{
hailo_stream_info_t input_stream_info;
hailo_input_stream input_stream;
hailo_status status;
hailo_stream_info_t stream_info;
int output_streams_cnt;
unsigned int num_images;
size_t host_input_frame_size;
int tid;
} write_thread_args_t;
typedef struct recv_thread_args_t
{
hailo_output_stream output_stream;
hailo_status status;
size_t host_output_frame_size;
hailo_stream_info_t stream_info;
unsigned int num_images;
int num_streams;
int write_log;
int tid;
} recv_thread_args_t;
typedef struct recv_thread1_args_t
{
hailo_output_stream *output_stream;
size_t *host_output_frame_size;
hailo_stream_info_t *stream_info;
unsigned int num_images;
int num_streams;
int write_log;
} recv_thread1_args_t;
typedef struct video_thread_args_t
{
hailo_stream_info_t *input_stream_info;
const char *video_path;
int num_images;
} video_thread_args_t;
typedef struct qp_zp_scale_t {
float32_t qp_zp_1;
float32_t qp_scale_1;
float32_t qp_zp_2;
float32_t qp_scale_2;
float32_t qp_zp_3;
float32_t qp_scale_3;
} qp_zp_scale_t;
#define RESET "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
#endif
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file main.cpp
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include "example_device.hpp"
#include "example_utils.hpp"
#include <iostream>
#include <thread>
#include <functional>
void thread_wrapper(std::string &iface, std::string &hef_file, unsigned int &num_img, int &write_log, bool &yolo_post, std::string &source_input)
{
example_device dev(iface, hef_file, num_img, write_log, yolo_post, source_input);
dev.run_inference();
}
int main(int argc, char **argv)
{
std::string hef = "";
std::string iface = "pcie";
std::string video_path = "";
bool yolo_post = false;
int opt;
unsigned int num_img = 100;
int write_log = 0;
while ((opt = getopt(argc, argv, "i:c:n:v:dly")) != -1)
{
switch (opt)
{
case 'c':
hef = optarg;
break;
case 'i':
iface = optarg;
break;
case 'n':
num_img = atoi(optarg);
break;
case 'l':
write_log = 1;
break;
case 'v':
video_path = optarg;
break;
case 'y':
yolo_post = true;
break;
case '?':
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -j JLF-DIR [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -c HEF The HEF Configuration file\n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -v VIDEO FILE Path to an input video file, relevant only in conjuction with the -y option\n");
fprintf(stderr, " -i INTERFACE The device interface, defaults to \'pcie\', if using Ethernet name the Host port\n");
fprintf(stderr, " -y Do YOLOv5 640x640 post-processing\n");
exit(EXIT_FAILURE);
}
}
try
{
std::cout << CYAN << "-I- TEST STARTS" << RESET << std::endl;
if (yolo_post==true && video_path.empty()) {
std::cout << RED << "-W- Received no input source (Video or images) and YOLOv5, aborting" << RESET << std::endl;
exit(0);
}
std::thread t0(thread_wrapper, std::ref(iface), std::ref(hef), std::ref(num_img), std::ref(write_log), std::ref(yolo_post), std::ref(video_path));
t0.join();
std::cout << CYAN << "-I- TEST ENDED" << RESET << std::endl;
}
catch (const std::exception &e)
{
std::cout << e.what();
}
}
#ifndef _YOLOV5_POSTPROCESS_H_
#define _YOLOV5_POSTPROCESS_H_
#include <vector>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <functional>
#include <example_utils.hpp>
#include <hailo/hailort.h>
#ifdef DEBUG
#include "npy.hpp"
#endif
constexpr int FEATURE_MAP_SIZE1 = 20;
constexpr int FEATURE_MAP_SIZE2 = 40;
constexpr int FEATURE_MAP_SIZE3 = 80;
constexpr int FEATURE_MAP_CHANNELS = 85;
constexpr int IMAGE_SIZE = 640;
constexpr int ANCHORS_NUM = 3;
constexpr float32_t IOU_THRESHOLD = 0.45f;
constexpr int MAX_BOXES = 100;
constexpr int CONF_CHANNEL_OFFSET = 4;
constexpr int CLASS_CHANNEL_OFFSET = 5;
struct DetectionObject {
float ymin, xmin, ymax, xmax, confidence;
int class_id;
DetectionObject(float32_t ymin, float32_t xmin, float32_t ymax, float32_t xmax, float32_t confidence, int class_id):
ymin(ymin), xmin(xmin), ymax(ymax), xmax(xmax), confidence(confidence), class_id(class_id)
{}
bool operator<(const DetectionObject &s2) const {
return this->confidence > s2.confidence;
}
};
float32_t fix_scale(float32_t input, float32_t qp_scale, float32_t qp_zp)
{
return (input - qp_zp) * qp_scale;
}
float32_t iou_calc(const DetectionObject &box_1, const DetectionObject &box_2) {
const float32_t width_of_overlap_area = std::min(box_1.xmax, box_2.xmax) - std::max(box_1.xmin, box_2.xmin);
const float32_t height_of_overlap_area = std::min(box_1.ymax, box_2.ymax) - std::max(box_1.ymin, box_2.ymin);
const float32_t positive_width_of_overlap_area = std::max(width_of_overlap_area, 0.0f);
const float32_t positive_height_of_overlap_area = std::max(height_of_overlap_area, 0.0f);
const float32_t area_of_overlap = positive_width_of_overlap_area * positive_height_of_overlap_area;
const float32_t box_1_area = (box_1.ymax - box_1.ymin) * (box_1.xmax - box_1.xmin);
const float32_t box_2_area = (box_2.ymax - box_2.ymin) * (box_2.xmax - box_2.xmin);
return area_of_overlap / (box_1_area + box_2_area - area_of_overlap);
}
void extract_boxes(std::vector<uint8_t> &fm, float32_t qp_zp, float32_t qp_scale, int feature_map_size,
int* anchors, std::vector<DetectionObject>& objects, float32_t& thr) {
float32_t confidence, x, y, h, w, xmin, ymin, xmax, ymax, conf_max = 0.0f;
int add = 0, anchor = 0, chosen_row = 0, chosen_col = 0, chosen_cls = -1;
float32_t cls_prob, prob_max;
// channels 0-3 are box coordinates, channel 4 is the confidence, and channels 5-84 are classes
for (int row = 0; row < feature_map_size; ++row) {
for (int col = 0; col < feature_map_size; ++col) {
prob_max = 0;
for (int a = 0; a < ANCHORS_NUM; ++a) {
add = FEATURE_MAP_CHANNELS * ANCHORS_NUM * feature_map_size * row + FEATURE_MAP_CHANNELS * ANCHORS_NUM * col + FEATURE_MAP_CHANNELS * a + CONF_CHANNEL_OFFSET;
confidence = fix_scale(fm[add], qp_scale, qp_zp);
for (int c = CLASS_CHANNEL_OFFSET; c < FEATURE_MAP_CHANNELS; ++c) {
add = FEATURE_MAP_CHANNELS * ANCHORS_NUM * feature_map_size * row + FEATURE_MAP_CHANNELS * ANCHORS_NUM * col + FEATURE_MAP_CHANNELS * a + c;
// final confidence: box confidence * class probability
cls_prob = fm[add];
if (cls_prob > prob_max) {
conf_max = fix_scale(cls_prob, qp_scale, qp_zp) * confidence;
chosen_cls = c - CLASS_CHANNEL_OFFSET + 1;
prob_max = cls_prob;
anchor = a;
chosen_row = row;
chosen_col = col;
}
}
}
if (conf_max >= thr) {
add = FEATURE_MAP_CHANNELS * ANCHORS_NUM * feature_map_size * chosen_row + FEATURE_MAP_CHANNELS * ANCHORS_NUM * chosen_col + FEATURE_MAP_CHANNELS * anchor;
x = (fix_scale(fm[add], qp_scale, qp_zp) * 2.0f - 0.5f + chosen_col) / feature_map_size;
y = (fix_scale(fm[add + 1], qp_scale, qp_zp) * 2.0f - 0.5f + chosen_row) / feature_map_size;
w = pow(2.0f * (fix_scale(fm[add + 2], qp_scale, qp_zp)), 2.0f) * anchors[anchor * 2] / IMAGE_SIZE;
h = pow(2.0f * (fix_scale(fm[add + 3], qp_scale, qp_zp)), 2.0f) * anchors[anchor * 2 + 1] / IMAGE_SIZE;
xmin = (x - (w / 2.0f)) * IMAGE_SIZE;
ymin = (y - (h / 2.0f)) * IMAGE_SIZE;
xmax = (x + (w / 2.0f)) * IMAGE_SIZE;
ymax = (y + (h / 2.0f)) * IMAGE_SIZE;
objects.push_back(DetectionObject(ymin, xmin, ymax, xmax, conf_max, chosen_cls));
}
}
}
}
size_t _decode(std::vector<uint8_t> &fm1, std::vector<uint8_t> &fm2, std::vector<uint8_t> &fm3, int* anchors1, int* anchors2, int* anchors3,
// xt::xarray<float32_t, xt::layout_type::row_major> _decode(std::vector<uint8_t> &fm1, std::vector<uint8_t> &fm2, std::vector<uint8_t> &fm3, int* anchors1, int* anchors2, int* anchors3,
qp_zp_scale_t qp_zp_scale, float32_t& thr, std::vector<float32_t> &results) {
size_t num_boxes = 0;
std::vector<DetectionObject> objects;
// std::vector<std::vector<float32_t>> results;
objects.reserve(MAX_BOXES);
// feature map1/2/3
extract_boxes(fm1, qp_zp_scale.qp_zp_1, qp_zp_scale.qp_scale_1, FEATURE_MAP_SIZE1, anchors1, objects, thr);
extract_boxes(fm2, qp_zp_scale.qp_zp_2, qp_zp_scale.qp_scale_2, FEATURE_MAP_SIZE2, anchors2, objects, thr);
extract_boxes(fm3, qp_zp_scale.qp_zp_3, qp_zp_scale.qp_scale_3, FEATURE_MAP_SIZE3, anchors3, objects, thr);
num_boxes = objects.size();
// filter by overlapping boxes
if (objects.size() > 0) {
std::sort(objects.begin(), objects.end());
for (unsigned int i = 0; i < objects.size(); ++i) {
if (objects[i].confidence <= thr)
continue;
for (unsigned int j = i + 1; j < objects.size(); ++j) {
if (objects[i].class_id == objects[j].class_id && objects[j].confidence >= thr) {
if (iou_calc(objects[i], objects[j]) >= IOU_THRESHOLD) {
objects[j].confidence = 0;
num_boxes -= 1;
}
}
}
}
}
// copy the results
if (num_boxes > 0) {
int box_ptr = 0;
// xt::xarray<int>::shape_type shape({num_boxes, 6});
// xt::xarray<float32_t, xt::layout_type::row_major> results(shape);
// results = (float32_t *)calloc(num_boxes * 6, sizeof(float32_t));
results.resize(num_boxes * 6);
for (const auto &obj: objects) {
if (obj.confidence >= thr) {
/*
results(box_ptr, 0) = obj.ymin / IMAGE_SIZE;
results(box_ptr, 1) = obj.xmin / IMAGE_SIZE;
results(box_ptr, 2) = obj.ymax / IMAGE_SIZE;
results(box_ptr, 3) = obj.xmax / IMAGE_SIZE;
results(box_ptr, 4) = (float32_t)obj.class_id;
results(box_ptr, 5) = obj.confidence;
*/
results[box_ptr*6 + 0] = obj.ymin / IMAGE_SIZE;
results[box_ptr*6 + 1] = obj.xmin / IMAGE_SIZE;
results[box_ptr*6 + 2] = obj.ymax / IMAGE_SIZE;
results[box_ptr*6 + 3] = obj.xmax / IMAGE_SIZE;
results[box_ptr*6 + 4] = (float32_t)obj.class_id;
results[box_ptr*6 + 5] = obj.confidence;
box_ptr += 1;
}
}
// return results;
return num_boxes;
} else {
// return xt::zeros<float32_t>({6});
results.resize(0);
// float32_t results[6] = {0, 0, 0, 0, 0, 0};
return 0;
}
}
/*
Given all parameters this function returns boxes with class and confidence
Inputs:
feature map1: 20x20x255
feature map2: 40x40x255
feature map3: 80x80x255
Outputs:
final boxes for display (Nx6) - ymin, xmin, ymax, xmax, class, conf
*/
size_t get_detections(std::vector<uint8_t> fm1, std::vector<uint8_t> fm2, std::vector<uint8_t> fm3,
// xt::xarray<float32_t> get_detections(std::vector<uint8_t> fm1, std::vector<uint8_t> fm2, std::vector<uint8_t> fm3,
qp_zp_scale_t qp_zp_scale, float32_t thr, std::vector<float32_t> &results) {
int anchors1[] = {116, 90, 156, 198, 373, 326};
int anchors2[] = {30, 61, 62, 45, 59, 119};
int anchors3[] = {10, 13, 16, 30, 33, 23};
return _decode(std::ref(fm1), std::ref(fm2), std::ref(fm3), anchors1, anchors2, anchors3, qp_zp_scale, thr, results);
}
//https://stackoverflow.com/questions/28562401/resize-an-image-to-a-square-but-keep-aspect-ratio-c-opencv
cv::Mat letterbox( const cv::Mat& img, int target_width = 640, int color = 114 )
{
int width = img.cols,
height = img.rows;
cv::Mat square( target_width, target_width, img.type(), cv::Scalar(color, color, color) );
int max_dim = ( width >= height ) ? width : height;
float32_t scale = ( ( float32_t ) target_width ) / max_dim;
cv::Rect roi;
if (width >= height) {
roi.width = target_width;
roi.x = 0;
roi.height = height * scale;
roi.y = ( target_width - roi.height ) / 2;
} else {
roi.y = 0;
roi.height = target_width;
roi.width = width * scale;
roi.x = ( target_width - roi.width ) / 2;
}
cv::resize( img, square( roi ), roi.size() );
return square;
}
typedef cv::Vec<uchar, 12> Vec12b;
cv::Mat yolov5_input_reshape(cv::Mat &input)
{
cv::Mat output( 320, 320, CV_8UC(12) );
int cols = input.cols;
int rows = input.rows;
for (int i = 0; i < cols; i+=2) {
for (int j = 0; j < rows; j+=2) {
Vec12b &output_pixel = output.at<Vec12b>(i/2, j/2);
for (int inner_i=0; inner_i<2; inner_i++) {
for (int inner_j=0; inner_j<2; inner_j++) {
cv::Vec3b &pixel = input.at<cv::Vec3b>(i+inner_i, j+inner_j);
output_pixel.val[(inner_i*2 + inner_j)* 3 + 0] = pixel.val[0];
output_pixel.val[(inner_i*2 + inner_j)* 3 + 1] = pixel.val[1];
output_pixel.val[(inner_i*2 + inner_j)* 3 + 2] = pixel.val[2];
}
}
}
}
return output;
}
cv::Mat yolov5_pre_process(cv::Mat &org_frame)
{
cv::Mat letter = letterbox(org_frame);
cv::imwrite("letter_boxed.jpg", letter);
// cv::Mat output = yolov5_input_reshape(letter);
// size_t shape [] = {320, 320, 12};
// npy::SaveArrayPointerAsNumpy("cpp-prep.npy", false, 3, shape, letter.data);
// cv::Mat output2 = letter.reshape(12/*Channels*/, 320/*Rows*/);
return letter;
}
std::string get_coco_name_from_int(int cls)
{
std::string result = "N/A";
switch(cls) {
case 0: result = "__background__";break;
case 1: result = "person";break;
case 2: result = "bicycle";break;
case 3: result = "car";break;
case 4: result = "motorcycle";break;
case 5: result = "airplane";break;
case 6: result = "bus";break;
case 7: result = "train";break;
case 8: result = "truck";break;
case 9: result = "boat";break;
case 10: result = "traffic light";break;
case 11: result = "fire hydrant";break;
case 12: result = "stop sign";break;
case 13: result = "parking meter";break;
case 14: result = "bench";break;
case 15: result = "bird";break;
case 16: result = "cat";break;
case 17: result = "dog";break;
case 18: result = "horse";break;
case 19: result = "sheep";break;
case 20: result = "cow";break;
case 21: result = "elephant";break;
case 22: result = "bear";break;
case 23: result = "zebra";break;
case 24: result = "giraffe";break;
case 25: result = "backpack";break;
case 26: result = "umbrella";break;
case 27: result = "handbag";break;
case 28: result = "tie";break;
case 29: result = "suitcase";break;
case 30: result = "frisbee";break;
case 31: result = "skis";break;
case 32: result = "snowboard";break;
case 33: result = "sports ball";break;
case 34: result = "kite";break;
case 35: result = "baseball bat";break;
case 36: result = "baseball glove";break;;
case 37: result = "skateboard";break;
case 38: result = "surfboard";break;
case 39: result = "tennis racket";break;
case 40: result = "bottle";break;
case 41: result = "wine glass";break;
case 42: result = "cup";break;
case 43: result = "fork";break;
case 44: result = "knife";break;
case 45: result = "spoon";break;
case 46: result = "bowl";break;
case 47: result = "banana";break;
case 48: result = "apple";break;
case 49: result = "sandwich";break;
case 50: result = "orange";break;
case 51: result = "broccoli";break;
case 52: result = "carrot";break;
case 53: result = "hot dog";break;
case 54: result = "pizza";break;
case 55: result = "donut";break;
case 56: result = "cake";break;
case 57: result = "chair";break;
case 58: result = "couch";break;
case 59: result = "potted plant";break;
case 60: result = "bed";break;
case 61: result = "dining table";break;
case 62: result = "toilet";break;
case 63: result = "tv";break;
case 64: result = "laptop";break;
case 65: result = "mouse";break;
case 66: result = "remote";break;
case 67: result = "keyboard";break;
case 68: result = "cell phone";break;
case 69: result = "microwave";break;
case 70: result = "oven";break;
case 71: result = "toaster";break;
case 72: result = "sink";break;
case 73: result = "refrigerator";break;
case 74: result = "book";break;
case 75: result = "clock";break;
case 76: result = "vase";break;
case 77: result = "scissors";break;
case 78: result = "teddy bear";break;
case 79: result = "hair drier";break;
case 80: result = "toothbrush";break;
}
return result;
}
#endif
#!/usr/bin/env python3
import os
import time
import argparse as ap
import numpy as np
from zenlog import logging as logger
from colorama import Fore
from tqdm import trange
import ctypes
from multiprocessing import Process, Value, Array
from hailo_platform import HEF, HailoPcieObject, InputStreamParams, OutputStreamParams, FormatType
from hailo_platform import HailoUdpControllerObject, HailoPcieObject, SendPipeline, RecvPipeline
from hailo_platform.drivers.hailort.pyhailort import PcieDevice, HailoRTException
def arg_prep():
parser = ap.ArgumentParser()
parser.add_argument('--hef', help='Point to the HEF')
parser.add_argument('--mode', help='Choose the communication mode [hw-only|full]', type=str, default='full')
parser.add_argument('--iterations', help='How many repeasts on the picture stream (Default:100)', type=int, default=100)
parser.add_argument('--power', help='Enable Power measurement', default=False, action='store_true')
parser.add_argument('--source', help='Specify image or video source', default=None)
parser.add_argument('--interface', help='Specify the physical interface, pcie or udp', default='pcie')
parser.add_argument('--fps', help='Emulate a source FPS', type=int, default='0')
# parser.add_argument('--ip', help='Set the IP of the Hailo device', type=str, default='10.0.0.100')
args = parser.parse_args()
return args
def _pre_infer_hef(stream, input_data):
dst_buffer = ctypes.create_string_buffer(stream.stream_information.hw_frame_size)
stream.transform(input_data, ctypes.addressof(dst_buffer), False)
return dst_buffer.raw
def _recv_process_hw_only_hef(output_streams, iterations, end_time, recv_times):
logger.info('RECV process HW-only Started')
local_recv_times = list()
outputs = dict()
for i in trange(iterations, desc='INFO:Recv...', position=0, bar_format="{l_bar}%s{bar}%s{r_bar}" % (Fore.GREEN, Fore.RESET)):
try:
for j, output_stream in enumerate(output_streams):
outputs[j] = output_stream.recv()
if i<100 and j==0:
local_recv_times.append(time.time())
except HailoRTException as e:
if e.args and '0x4' in e.args and i>iterations*0.9:
pass
for i, t in enumerate(local_recv_times):
recv_times[i] = t
end_time.value = time.time()
def _recv_process_full_hef(activated_network, iterations, end_time, recv_times):
logger.info('RECV process Full Started')
with RecvPipeline(activated_network) as recv_pipeline:
output_streams = [recv_pipeline.get_output_by_name(output_name) for output_name in activated_network.target.sorted_output_layer_names]
[logger.info("Output: {}".format(name)) for name in activated_network.target.sorted_output_layer_names]
outputs = dict()
for i in trange(iterations, desc='INFO:Recv...', position=0, bar_format="{l_bar}%s{bar}%s{r_bar}" % (Fore.GREEN, Fore.RESET)):
logger.debug("[{}] Recv frame {}/{}".format(time.time(), i, iterations))
for j, output_stream in enumerate(output_streams):
outputs[j] = output_stream.recv()
if i<100:
recv_times[i] = time.time()
end_time.value = time.time()
logger.debug("[{}] Finished Recving {} frames".format(end_time.value, iterations))
def _send_process_hw_only_hef(input_streams, iterations, fps, send_times):
logger.info('SEND process HW-only Started')
local_send_times = list()
if fps>0.0:
logger.info("Emulate source FPS: {}".format(fps))
data_per_input = [_pre_infer_hef(s, np.random.randint(256, size=(1,) + shape, dtype=np.uint8)) for s, shape in input_streams.items()]
# [logger.info("Input: {} with shape: {}".format(name, shape)) for name, shape in input_streams.items()]
for i in range(iterations):
try:
for intput_stream in input_streams.keys():
if fps>0:
time.sleep(1.0/fps)
if i<100:
local_send_times.append(time.time())
intput_stream.send(data_per_input[0])
except HailoRTException as e:
if e.args and '0x4' in e.args and i>iterations*0.9:
pass
for i,t in enumerate(local_send_times):
send_times[i] = t
def _send_process_full_hef(activated_network, iterations, input_shapes, fps, send_times):
with SendPipeline(activated_network) as send_pipeline:
input_streams = {send_pipeline.get_input_by_name(input_name): shape
for input_name, shape in input_shapes.items()}
data_per_input = [np.random.randint(256, size=(1,) + shape, dtype=np.uint8) for _, shape in input_shapes.items()]
[logger.info("Input: {} with shape: {}".format(name, shape)) for name, shape in input_shapes.items()]
if fps>0.0:
logger.info("Emulate source FPS: {}".format(fps))
local_send_times = list()
for i in range(iterations):
try:
for input_stream, _ in input_streams.items():
logger.debug("[{}] Send frame {}/{}".format(time.time(), i, iterations))
if fps>0:
time.sleep(1.0/fps)
if i<100:
local_send_times.append(time.time())
input_stream.send(data_per_input[0])
except HailoRTException as e:
if e.args and '0x4' in e.args and i>iterations*0.9:
pass
for i,t in enumerate(local_send_times):
send_times[i] = t
def run_hef(target, hef, iterations, streaming_mode, fps):
logger.info("Loading HEF to target")
network = target.configure(hef)[0]
application_params = network.create_params()
# Explanation about definition of the streams-
# quantized - Whether to scale and zero-point the values from 0-255, if the input is uint8 can use as-is
# format_type - The input type UINT8, UINT16, FLOAT32, AUTO
input_streams_params = InputStreamParams.make_from_network_group(network, quantized=True, format_type=FormatType.UINT8)
output_streams_params = OutputStreamParams.make_from_network_group(network, quantized=True, format_type=FormatType.UINT8)
with network.activate(application_params, input_streams_params=input_streams_params,
output_streams_params=output_streams_params) as activated_network:
send_times = Array(ctypes.c_double, [0.0] * 100)
recv_times = Array(ctypes.c_double, [0.0] * 100)
end_time = Value(ctypes.c_double, 0.0)
if streaming_mode=='full':
input_shapes = {layer_info.name: layer_info.shape for layer_info in hef.get_input_layers_info()}
recv_process = Process(target=_recv_process_full_hef, args=(activated_network, iterations, end_time, recv_times))
send_process = Process(target=_send_process_full_hef, args=(activated_network, iterations, input_shapes, fps, send_times))
else:
input_streams = {activated_network.get_input_by_name(l.name): l.shape for l in hef.get_input_layers_info()}
send_process = Process(target=_send_process_hw_only_hef, args=(input_streams, iterations, fps, send_times))
output_streams = [activated_network.get_output_by_name(l.name) for l in hef.get_output_layers_info()]
recv_process = Process(target=_recv_process_hw_only_hef, args=(output_streams, iterations, end_time, recv_times))
start = time.time()
try:
logger.info("[{}] Starting Inference".format(start))
send_process.start()
recv_process.start()
except KeyboardInterrupt:
logger.info("Interrupted by the user, stopping..")
send_process.terminate()
recv_process.terminate()
except Exception:
logger.info("Exception happened, stopping..")
send_process.terminate()
recv_process.terminate()
finally:
send_process.join()
recv_process.join()
logger.info("[{}] Finished Inference".format(end_time.value))
latencies = [r-t for r,t in zip(recv_times, send_times)]
logger.info("-------------------------------------")
logger.info(" Infer Time: {:.3f} sec".format(end_time.value - start))
logger.info(" Average FPS: {:.3f}".format(iterations/(end_time.value - start)))
logger.info(" Average Latency: {:.3f} ms".format(np.average(latencies) * 1000.0))
logger.info("-------------------------------------")
def main():
logger.basicConfig(level=logger.INFO)
args = arg_prep()
logger.info('Reading HEF from: {}'.format(args.hef))
config = HEF(args.hef)
with HailoPcieObject() as target:
run_hef(target, config, args.iterations, args.mode, args.fps)
if __name__ == "__main__":
main()
cmake_minimum_required(VERSION 3.0.0)
# Setting the ARCH if not provided
if (NOT DEFINED ARCH)
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch_from_cmd)
string(STRIP ${arch_from_cmd} arch_from_cmd)
set(ARCH ${arch_from_cmd})
endif()
# Setting the CMAKE_C_COMPILER if not provided
if (${ARCH} STREQUAL "aarch64")
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "/usr/bin/aarch64-linux-gnu-gcc")
endif()
else()
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "/usr/bin/gcc")
endif()
endif()
set(HAILORT_ROOT $ENV{HAILORT_ROOT})
set (HAILORT_LIB ${HAILORT_ROOT}/lib/${ARCH}/libhailort.so.0.5.0)
# set(HAILORT_LIB "${HAILORT_ROOT}/../lib/linux.x86_64.release/libhailort.so.0.5.0")
set(HAILORT_INCLUDE_DIR ${HAILORT_ROOT}/include)
message(STATUS ${HAILORT_LIB})
message(STATUS ${HAILORT_INCLUDE_DIR})
set(COMPILE_OPTIONS_CPP -Werror -O3 -DNDEBUG -std=c++11)
set(COMPILE_OPTIONS -O3 -DNDEBUG)
include_directories(${HAILORT_INCLUDE_DIR} "./")
find_package(Threads)
foreach(target example shortcut example_1rx_thread)
add_executable(${target} "${target}.c")
target_compile_options(${target} PRIVATE ${COMPILE_OPTIONS})
target_link_libraries(${target} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${target} ${HAILORT_LIB})
endforeach(target)
#find_package( OpenCV REQUIRED )
#include_directories( ${OpenCV_INCLUDE_DIRS} )
# add_executable(md_example example_device.cpp main.cpp)
# target_compile_options(md_example PRIVATE ${COMPILE_OPTIONS_CPP})
# target_link_libraries(md_example ${CMAKE_THREAD_LIBS_INIT})
# target_link_libraries(md_example ${HAILORT_LIB})
#target_link_libraries(md_example ${OpenCV_LIBS})
\ No newline at end of file
To Compile all targets to all architectures (x86, armv7l, aarch64):
`build.sh`
\ No newline at end of file
#!/bin/bash
declare -A COMPILER=( [x86_64]=/usr/bin/gcc
[aarch64]=/usr/bin/aarch64-linux-gnu-gcc
[armv7l]=/usr/bin/arm-linux-gnueabi-gcc )
HAILORT_ROOT=/home/${USER}/SDK/2.12.1/cpu_sdk/platform/hailort
for ARCH in x86_64 aarch64 armv7l
do
echo "-I- Building ${ARCH}"
HAILORT_LIB=${HAILORT_ROOT}/lib/${ARCH}/libhailort.so.0.5.0
mkdir -p build/${ARCH}
HAILORT_ROOT=${HAILORT_ROOT} cmake -H. -Bbuild/${ARCH} -DARCH=${ARCH} -DCMAKE_C_COMPILER=${COMPILER[${ARCH}]}
cmake --build build/${ARCH}
done
\ No newline at end of file
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file example.c
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include <net/if.h>
#include <pthread.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <linux/limits.h>
#include <time.h>
#include <hailo/hailort.h>
#include "example_utils.h"
#define NOF_STREAMS (6)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
unsigned int actual_measurments;
void* _send_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
uint8_t* src_data = (uint8_t*)malloc(write_args->host_frame_size);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
struct timespec ts;
if (NULL == src_data) {
printf("-E- Failed to allocate buffers\n");
status = HAILO_OUT_OF_HOST_MEMORY;
goto l_release_buffers;
}
for(size_t i = 0; i < write_args->host_frame_size; i++) {
//src_data[i] = (float32_t)(rand()%256);
src_data[i] = (uint8_t)(rand() % 256);
}
flag_100 = (uint32_t)write_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
for (uint32_t i = 1; i <= (uint32_t)write_args->num_images; i++) {
if ((i % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] Send frame [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, i, write_args->num_images, src_data[0], src_data[1], src_data[2], src_data[3]);
sent_clock_t[lat_counter++] = ts;
}
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream, src_data, 0, write_args->host_frame_size);
if (status != HAILO_SUCCESS) {
printf("-E- hailo_stream_sync_write_all_raw_buffer failed: %d",status);
break;
}
}
l_release_buffers:
FREE(src_data);
l_exit:
write_args->status = status;
return NULL;
}
void* _recv_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
recv_thread_args_t *recv_args = (recv_thread_args_t *)args;
struct timespec ts;
FILE *fp;
uint8_t *dst_data = (uint8_t*)malloc(recv_args->host_frame_size);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
printf("-I- Recv thread %d started\n", recv_args->tid);
if (recv_args->write_log==1) {
char *log_name = (char*)malloc(20 * sizeof(char));
sprintf(log_name, "tid_%d.log", recv_args->tid);
fp = fopen(log_name, "w");
free(log_name);
}
flag_100 = (uint32_t)recv_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
actual_measurments = 0;
for (uint32_t j = 1; j <= (uint32_t)recv_args->num_images; j++) {
status = hailo_stream_sync_read_all_raw_buffer(recv_args->output_stream, dst_data, 0, recv_args->host_frame_size);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_read_all_raw_buffer failed");
if ((j % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Recv [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, recv_args->tid, j, recv_args->num_images, dst_data[0], dst_data[1], dst_data[2], dst_data[3]);
recv_clock_t[recv_args->tid][lat_counter++] = ts;
actual_measurments++;
}
if (recv_args->write_log==1)
fprintf(fp, "%d Recv [%10ld.%ld s] %3d/%3d %x\n", recv_args->tid, (long)ts.tv_sec, ts.tv_nsec/1000000, j, recv_args->num_images, *dst_data);
}
if (recv_args->write_log==1)
fclose(fp);
l_exit:
free(dst_data);
recv_args->status = status;
return NULL;
}
hailo_status infer(
hailo_input_stream input_stream, hailo_stream_info_t *input_stream_info,
hailo_output_stream *output_streams, hailo_stream_info_t *output_streams_info,
int output_stream_cnt, int num_images, int write_log, hailo_eth_output_stream_params_t* params, hailo_eth_input_stream_params_t in_param)
{
hailo_status status = HAILO_SUCCESS;
pthread_t write_thread = 1;
recv_thread_args_t recv_args[NOF_STREAMS-1];
pthread_t recv_threads[NOF_STREAMS-1];
write_thread_args_t write_args = {
.input_stream_info = input_stream_info,
.input_stream = input_stream,
.status = HAILO_UNINITIALIZED,
.output_streams_cnt = output_stream_cnt,
.num_images = num_images,
.host_frame_size = hailo_get_host_frame_size(input_stream_info, &in_param.base_params)
};
for (int ii=0; ii<output_stream_cnt; ii++) {
recv_args[ii].output_stream_info = &output_streams_info[ii];
recv_args[ii].output_stream = output_streams[ii];
recv_args[ii].tid = ii;
recv_args[ii].status = HAILO_UNINITIALIZED;
recv_args[ii].num_images = num_images;
recv_args[ii].write_log = write_log;
recv_args[ii].host_frame_size = hailo_get_host_frame_size(&output_streams_info[ii], &params[ii].base_params);
(void) pthread_create(&recv_threads[ii], NULL, _recv_thread, &recv_args[ii]);
};
(void) pthread_create(&write_thread, NULL, _send_thread, &write_args);
pthread_join(write_thread, NULL);
if (HAILO_SUCCESS != write_args.status) {
printf("-E- write_thread failed\n");
status = HAILO_INTERNAL_FAILURE;
}
for (int ii=0; ii<output_stream_cnt; ii++) {
pthread_join(recv_threads[ii], NULL);
printf("-I- Closing Recv thread #%d: %d\n", recv_args[ii].tid, recv_args[ii].status);
if (HAILO_SUCCESS != recv_args[ii].status) {
printf("-E- Recv thread %d failed\n", recv_args[ii].tid);
status = HAILO_INTERNAL_FAILURE;
}
}
return status;
}
void print_net_banner(hailo_stream_info_t *all_stream_infos, int cnt) {
printf(BOLDCYAN);
printf("-I-----------------------------------------------\n");
printf("-I- Input: %s (%d, %d, %d)\n", all_stream_infos[0].name, all_stream_infos[0].shape.height, all_stream_infos[0].shape.width,
all_stream_infos[0].shape.features);
for (int ii=1; ii<=cnt; ii++) {
printf("-I- Output[%d]: %s (%d, %d, %d)\n", ii-1, all_stream_infos[ii].name, all_stream_infos[ii].shape.height, all_stream_infos[ii].shape.width,
all_stream_infos[ii].shape.features);
}
printf("-I-----------------------------------------------\n");
printf(RESET);
}
double get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (double)(ts.tv_nsec / 1000000.0));
return result;
}
double calc_latency(int count) {
double result = 0;
double cur_rcv;
double cur_snd;
for (int j=0; j<actual_measurments; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
result += (cur_rcv - cur_snd);
}
return result/actual_measurments;
}
void print_inference_stats(struct timespec start_time, struct timespec end_time, hailo_stream_info_t *all_stream_infos, int output_stream_cnt, int num_images, uint32_t latency_readout)
{
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
uint32_t send_frame_size = all_stream_infos[0].hw_frame_size;
uint32_t recv_frame_size = 0;
printf("-I- print stats\n");
printf(BOLDGREEN);
printf("-I-----------------------------------------------\n");
printf("-I- Total time: %4.2lf sec\n", infer_time_secs);
printf("-I- Average FPS: %4.2lf\n", num_images / infer_time_secs);
printf("-I- Average Latency: %3.2lf ms\n", calc_latency(output_stream_cnt));
#ifdef FW_LAT
printf("-I- FW latency (Beta): %3.2f ms\n", latency_readout/1000000.0f);
#endif
printf("-I- Send data rate: %-4.2lf Mbit/s\n",
(double)(num_images) * send_frame_size * mbit_per_byte / infer_time_secs);
for (int i=1; i<=output_stream_cnt; i++) {
recv_frame_size = all_stream_infos[i].hw_frame_size;
printf("-I- Recv[%d] data rate: %-4.2lf Mbit/s\n", i,
(double)(num_images) * recv_frame_size * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
const char** get_jlf_files_form_path(const char *dir_name, uint8_t *actual_number_of_jlfs_files) {
static char jlf_files[HAILO_MAX_NUMBER_OF_JLFS][PATH_MAX];
static const char *res_jlf_files[HAILO_MAX_NUMBER_OF_JLFS];
DIR *dir = NULL;
struct dirent *entry = NULL;
uint8_t i = 0;
dir = opendir(dir_name);
if (NULL == dir) {
return NULL;
}
entry = readdir(dir);
while (NULL != entry) {
if (entry->d_name[0] != '.') {
(void)snprintf(jlf_files[i], sizeof(jlf_files[i]), "%s%s", dir_name, entry->d_name);
res_jlf_files[i] = jlf_files[i];
i++;
}
entry = readdir(dir);
}
(void) closedir(dir);
*actual_number_of_jlfs_files = i;
return res_jlf_files;
}
const char* get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
hailo_status print_debug_stats(hailo_device device) {
uint32_t address;
uint8_t* data = (uint8_t*)malloc(4);
uint32_t size = 4;
hailo_status status = HAILO_SUCCESS;
// rx_jabbers
address = 0x0010918C;
status = hailo_read_memory(device, address, data, size);
printf(CYAN);
printf("-I-----------------------------------------------\n");
printf("-D- RX_JABBERS: 0x%d\n", *data);
// fcs_errors
address = 0x00109190;
status = hailo_read_memory(device, address, data, size);
printf("-D- FCS_ERRORS: 0x%d\n", *data);
printf("-I-----------------------------------------------\n");
printf(RESET);
free(data);
return status;
}
void set_default_output_stream_params(hailo_eth_output_stream_params_t* stream) {
stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
stream->device_port = 0;
stream->host_address.sin_family = AF_INET;
stream->host_address.sin_port = 0;
stream->host_address.sin_addr.s_addr = INADDR_ANY;
stream->is_sync_enabled = true;
memset(&stream->host_address.sin_zero, 0, sizeof(stream->host_address.sin_zero));
}
#ifdef FW_LAT
hailo_status set_latency_measurement(hailo_device device, int image_index, hailo_stream_info_t input_stream_info, hailo_stream_info_t output_stream_info)
{
return hailo_latency_measurement_config(device, 1, (image_index-1)*input_stream_info.hw_shape.height,
output_stream_info.hw_shape.height*image_index, input_stream_info.index, output_stream_info.index);
}
#endif
int main(int argc, char **argv)
{
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
hailo_eth_device_info_t device_info = {0};
hailo_device device = NULL;
hailo_jlf jlf = NULL;
uint8_t jlf_buffer[48*1024];
uint8_t actual_number_of_jlfs_files = 0;
hailo_input_stream input_stream = NULL;
hailo_output_stream output_streams[NOF_STREAMS];
hailo_eth_input_stream_params_t input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
hailo_eth_output_stream_params_t output_streams_params[NOF_STREAMS-1];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
hailo_stream_info_t output_streams_info[NOF_STREAMS-1];
const char **jlf_files = NULL;
struct timespec start_time = {0};
struct timespec end_time = {0};
size_t number_of_streams = 0;
uint8_t input_fifo_index = 0;
int output_stream_cnt = 0;
uint8_t output_fifo_indexes[NOF_STREAMS-1];
char *jlf_dir = "./JLFs/";
int opt;
char *iface = "eno2";
int num_img = 100;
int debug = 0;
int write_log = 0;
uint32_t latency_readout = 0;
while ((opt = getopt(argc, argv, "i:j:n:dl")) != -1) {
switch (opt) {
case 'j': jlf_dir = optarg; break;
case 'i': iface = optarg; break;
case 'n': num_img = atoi(optarg); break;
case 'd': debug = 1; break;
case 'l': write_log = 1; break;
case '?': fprintf (stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -j JLF-DIR [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -i INTERFACE The Ethernet interface, defaults to \'eno2\'\n");
fprintf(stderr, " -j JLF-DIR The JLFs directory, defaults to \'./JLFs/\'\n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -d Read and print debug registers from FW\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
exit(EXIT_FAILURE);
}
}
printf(BOLDCYAN);
printf("-I- Running on interface: %s %d images\n", iface, num_img);
printf("-I- Reading JLFs from: %s\n", jlf_dir);
printf(RESET);
status = hailo_scan_ethernet_devices(iface, &device_info, 1, &number_of_devices, HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for eth_devices");
if (0 == number_of_devices) {
printf("-E- No device found on the given interface\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_ethernet_device(&device_info, &device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_device");
jlf_files = get_jlf_files_form_path(jlf_dir, &actual_number_of_jlfs_files);
if (NULL == jlf_files) {
printf("-E- Failed to get jlf files from path\n");
status = HAILO_INTERNAL_FAILURE;
goto l_release_device;
}
status = hailo_create_jlf_files(jlf_files, actual_number_of_jlfs_files, jlf_buffer, sizeof(jlf_buffer), &jlf);
REQUIRE_SUCCESS(status, l_release_device, "Failed to create jlf files");
status = hailo_configure_device_from_jlf(device, jlf, jlf_buffer, sizeof(jlf_buffer));
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to configure device from jlf");
// NEDEN
status = hailo_jlf_get_all_stream_infos(jlf, all_stream_infos, NOF_STREAMS, &number_of_streams);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to get all stream info");
#ifdef FW_LAT
status = set_latency_measurement(device, num_img/2 /*Image index*/, all_stream_infos[0], all_stream_infos[1]);
#endif
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to activate latecny measurement in FW");
for (size_t i=0;i<number_of_streams;i++) {
printf("-D- [%d] direction:%-7s index=%d output_index=%d\n",(int)i, get_direction_name(all_stream_infos[i].direction), all_stream_infos[i].index, output_stream_cnt);
if (all_stream_infos[i].direction==HAILO_H2D_STREAM) {
input_fifo_index = all_stream_infos[i].index;
} else {
output_fifo_indexes[output_stream_cnt++] = all_stream_infos[i].index;
}
}
if (all_stream_infos[0].format.order == HAILO_FORMAT_ORDER_NC ||
all_stream_infos[0].format.order == HAILO_FORMAT_ORDER_NHW) {
input_stream_params.base_params.user_buffer_format.order = all_stream_infos[0].format.order;
}
// input_stream_params.base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_FLOAT32;
// input_stream_params.base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_NONE;
// input_stream_params.base_params.transform_mode = HAILO_STREAM_TRANSFORM_INPLACE;
status = hailo_create_eth_input_stream_from_jlf_by_index(device, jlf, input_fifo_index, &input_stream_params, &input_stream);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to create eth_input_stream");
status = hailo_activate_input_stream(device, input_stream);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to activate input stream");
// NEDEN - get all outputs
for (int i=0;i<output_stream_cnt;i++) {
set_default_output_stream_params(&output_streams_params[i]);
status = hailo_jlf_get_stream_info_by_index(jlf, output_fifo_indexes[i], HAILO_D2H_STREAM, &output_streams_info[i]);
REQUIRE_SUCCESS(status, l_release_output_stream, "-E- Failed to get eth_output_stream");
if (output_streams_info[i].format.order == HAILO_FORMAT_ORDER_NC ||
output_streams_info[i].format.order == HAILO_FORMAT_ORDER_NHW ||
output_streams_info[i].format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
output_streams_params[i].base_params.user_buffer_format.order = output_streams_info[i].format.order;
}
status = hailo_create_eth_output_stream_from_jlf_by_index(device, jlf, output_fifo_indexes[i], &output_streams_params[i], &output_streams[i]);
REQUIRE_SUCCESS(status, l_release_input_stream, "Failed to create eth_output_stream");
status = hailo_activate_output_stream(device, output_streams[i]);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to activate output stream");
}
//NEDEN: Assuming the input is always on index #0
print_net_banner(all_stream_infos, output_stream_cnt);
// Run inference and compare results
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
status = infer(input_stream, &all_stream_infos[0], output_streams, output_streams_info, output_stream_cnt, num_img, write_log, output_streams_params, input_stream_params);
#ifdef FW_LAT
status = hailo_latency_measurement_read(device, &latency_readout);
#endif
REQUIRE_SUCCESS(status, l_release_output_stream, "Inference failure");
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
print_inference_stats(start_time, end_time, all_stream_infos, output_stream_cnt, num_img, latency_readout);
status = HAILO_SUCCESS;
l_release_output_stream:
for (int i=0;i<output_stream_cnt;i++) {
(void) hailo_release_output_stream(device, output_streams[i]);
}
if (debug==1) {
print_debug_stats(device);
REQUIRE_SUCCESS(status, l_release_input_stream, "Failed to read debug registers");
}
l_release_input_stream:
(void) hailo_release_input_stream(device, input_stream);
l_release_jlf:
(void) hailo_release_jlf(jlf);
l_release_device:
(void) hailo_release_device(device);
l_exit:
return status;
}
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file example.c
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include <net/if.h>
#include <pthread.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <linux/limits.h>
#include <time.h>
#include <hailo/hailort.h>
#include "example_utils.h"
#define UNIQUE_FRAMES_COUNT (3)
#define NOF_STREAMS (5)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
void* _send_thread(void *args) {
hailo_status status = HAILO_UNINITIALIZED;
write_thread_args_t *write_args = (write_thread_args_t*)args;
uint8_t* src_data = (uint8_t*)malloc(write_args->input_stream_info->shape_size * UNIQUE_FRAMES_COUNT);
//float32_t* src_data = (float32_t*)malloc(write_args->input_stream_info->shape_size * UNIQUE_FRAMES_COUNT * sizeof(float32_t));
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
struct timespec ts;
if (NULL == src_data) {
printf("-E- Failed to allocate buffers\n");
status = HAILO_OUT_OF_HOST_MEMORY;
goto l_release_buffers;
}
for(size_t i = 0; i < write_args->input_stream_info->shape_size * UNIQUE_FRAMES_COUNT; i++) {
//src_data[i] = (float32_t)(rand()%256);
src_data[i] = (uint8_t)(rand() % 256);
}
flag_100 = (uint32_t)write_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
for (uint32_t i = 1; i <= (uint32_t)write_args->num_images; i++) {
if ((i % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] Send frame [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, i, write_args->num_images, src_data[0], src_data[1], src_data[2], src_data[3]);
sent_clock_t[lat_counter++] = ts;
}
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream,
src_data,
0, write_args->input_stream_info->shape_size);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_write_all_raw_buffer failed");
}
status = HAILO_SUCCESS;
l_release_buffers:
FREE(src_data);
l_exit:
write_args->status = status;
return NULL;
}
hailo_status infer(
hailo_input_stream input_stream, hailo_stream_info_t *input_stream_info,
hailo_output_stream *output_streams, hailo_stream_info_t *output_streams_info,
int output_stream_cnt, int num_images, int write_log)
{
hailo_status status = HAILO_SUCCESS;
pthread_t write_thread = 1;
FILE *fp;
char *log_name = (char*)malloc(20 * sizeof(char));
int len = 0;
struct timespec ts;
uint32_t flag_100 = 0;
uint8_t *dst_data;
unsigned lat_counter = 0;
printf("-I- write_log %d\n", write_log);
write_thread_args_t write_args = {
.input_stream_info = input_stream_info,
.input_stream = input_stream,
.status = HAILO_UNINITIALIZED,
.output_streams_cnt = output_stream_cnt,
.num_images = num_images
};
(void) pthread_create(&write_thread, NULL, _send_thread, &write_args);
flag_100 = (uint32_t)num_images / 100;
if (flag_100==0)
flag_100 = 1;
for (int i=0;i<output_stream_cnt;i++) {
if ((int)output_streams_info[i].hw_frame_size>len)
len = (int)output_streams_info[i].hw_frame_size;
}
dst_data = (uint8_t *)malloc(len);
for (uint32_t j = 1; j <= (uint32_t)num_images; j++) {
for (uint32_t jj = 0; jj < (uint32_t)output_stream_cnt; jj++) {
status = hailo_stream_sync_read_all_raw_buffer(output_streams[jj], dst_data, 0, output_streams_info[jj].hw_frame_size);
REQUIRE_SUCCESS(status, l_exit, "-E- hailo_stream_sync_read_all_raw_buffer failed");
if (j % flag_100==0) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] STREAM:%d Recv [%3d/%3d] %x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, jj, j, num_images, *dst_data);
if (lat_counter < LATENCY_MEASUREMENTS) {
recv_clock_t[jj][lat_counter++] = ts;
}
if (write_log==1)
fprintf(fp, "%d Recv [%10ld.%ld s] %3d/%3d %x\n", jj, (long)ts.tv_sec, ts.tv_nsec/1000000, j, num_images, *dst_data);
}
}
}
pthread_join(write_thread, NULL);
if (HAILO_SUCCESS != write_args.status) {
printf("-E- write_thread failed\n");
status = HAILO_INTERNAL_FAILURE;
}
l_exit:
FREE(dst_data);
return status;
}
void print_net_banner(hailo_stream_info_t *all_stream_infos, int cnt) {
printf(BOLDCYAN);
printf("-I-----------------------------------------------\n");
printf("-I- Input: %s (%d, %d, %d)\n", all_stream_infos[0].name, all_stream_infos[0].shape.height, all_stream_infos[0].shape.width,
all_stream_infos[0].shape.features);
for (int ii=1; ii<=cnt; ii++) {
printf("-I- Output[%d]: %s (%d, %d, %d)\n", ii-1, all_stream_infos[ii].name, all_stream_infos[ii].shape.height, all_stream_infos[ii].shape.width,
all_stream_infos[ii].shape.features);
}
printf("-I-----------------------------------------------\n");
printf(RESET);
}
double get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (ts.tv_nsec / 1000000));
return result;
}
double calc_latency(int count) {
double result = 0;
double cur_rcv;
double cur_snd;
for (int j=0; j<LATENCY_MEASUREMENTS; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
result += (cur_rcv - cur_snd);
}
return result/LATENCY_MEASUREMENTS;
}
void print_inference_stats(struct timespec start_time, struct timespec end_time, hailo_stream_info_t *all_stream_infos, int output_stream_cnt, int num_images)
{
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
uint32_t send_frame_size = all_stream_infos[0].hw_frame_size;
uint32_t recv_frame_size = 0;
printf(BOLDGREEN);
printf("-I-----------------------------------------------\n");
printf("-I- Total time: %4.2lf sec\n", infer_time_secs);
printf("-I- Average FPS: %4.2lf\n", num_images / infer_time_secs);
printf("-I- Average Latency: %3.2lf ms\n", calc_latency(output_stream_cnt));
printf("-I- Send data rate: %-4.2lf Mbit/s\n",
(double)(num_images) * send_frame_size * mbit_per_byte / infer_time_secs);
for (int i=1; i<=output_stream_cnt; i++) {
recv_frame_size = all_stream_infos[i].hw_frame_size;
printf("-I- Recv[%d] data rate: %-4.2lf Mbit/s\n", i,
(double)(num_images) * recv_frame_size * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
const char** get_jlf_files_form_path(const char *dir_name, uint8_t *actual_number_of_jlfs_files) {
static char jlf_files[HAILO_MAX_NUMBER_OF_JLFS][PATH_MAX];
static const char *res_jlf_files[HAILO_MAX_NUMBER_OF_JLFS];
DIR *dir = NULL;
struct dirent *entry = NULL;
uint8_t i = 0;
dir = opendir(dir_name);
if (NULL == dir) {
return NULL;
}
entry = readdir(dir);
while (NULL != entry) {
if (entry->d_name[0] != '.') {
(void)snprintf(jlf_files[i], sizeof(jlf_files[i]), "%s%s", dir_name, entry->d_name);
res_jlf_files[i] = jlf_files[i];
i++;
}
entry = readdir(dir);
}
(void) closedir(dir);
*actual_number_of_jlfs_files = i;
return res_jlf_files;
}
const char* get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
hailo_status print_debug_stats(hailo_device device) {
uint32_t address;
uint8_t* data = (uint8_t*)malloc(4);
uint32_t size = 4;
hailo_status status = HAILO_SUCCESS;
// rx_jabbers
address = 0x0010918C;
status = hailo_read_memory(device, address, data, size);
printf(CYAN);
printf("-I-----------------------------------------------\n");
printf("-D- RX_JABBERS: 0x%d\n", *data);
// fcs_errors
address = 0x00109190;
status = hailo_read_memory(device, address, data, size);
printf("-D- FCS_ERRORS: 0x%d\n", *data);
printf("-I-----------------------------------------------\n");
printf(RESET);
return status;
}
void set_default_output_stream_params(hailo_eth_output_stream_params_t* stream) {
// stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.transform_mode = HAILO_STREAM_NO_TRANSFORM;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
stream->device_port = 0;
stream->host_address.sin_family = AF_INET;
stream->host_address.sin_port = 0;
stream->host_address.sin_addr.s_addr = INADDR_ANY;
memset(&stream->host_address.sin_zero, 0, sizeof(stream->host_address.sin_zero));
}
int main(int argc, char **argv)
{
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
hailo_eth_device_info_t device_info = {0};
hailo_device device = NULL;
hailo_jlf jlf = NULL;
uint8_t jlf_buffer[48*1024];
uint8_t actual_number_of_jlfs_files = 0;
hailo_input_stream input_stream = NULL;
hailo_output_stream output_streams[NOF_STREAMS];
hailo_eth_input_stream_params_t input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
hailo_eth_output_stream_params_t output_streams_params[NOF_STREAMS-1];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
hailo_stream_info_t output_streams_info[NOF_STREAMS-1];
const char **jlf_files = NULL;
struct timespec start_time = {0};
struct timespec end_time = {0};
size_t number_of_streams = 0;
uint8_t input_fifo_index = 0;
int output_stream_cnt = 0;
uint8_t output_fifo_indexes[NOF_STREAMS-1];
char *jlf_dir = "./JLFs/";
int opt;
char *iface = "eno2";
int num_img = 100;
int debug = 0;
int write_log = 0;
while ((opt = getopt(argc, argv, "i:j:n:dl")) != -1) {
switch (opt) {
case 'j': jlf_dir = optarg; break;
case 'i': iface = optarg; break;
case 'n': num_img = atoi(optarg); break;
case 'd': debug = 1; break;
case 'l': write_log = 1; break;
case '?': fprintf (stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -j JLF-DIR [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -i INTERFACE The Ethernet interface, defaults to \'eno2\'\n");
fprintf(stderr, " -j JLF-DIR The JLFs directory, defaults to \'./JLFs/\'\n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -d Read and print debug registers from FW\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
exit(EXIT_FAILURE);
}
}
printf("\033[1;36m");
printf("-I- Running on interface: %s %d images\n", iface, num_img);
printf("-I- Reading JLFs from: %s\n", jlf_dir);
printf("\033[0m");
status = hailo_scan_ethernet_devices(iface, &device_info, 1, &number_of_devices, HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for eth_devices");
if (0 == number_of_devices) {
printf("-E- No device found on the given interface\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_ethernet_device(&device_info, &device);
REQUIRE_SUCCESS(status, l_exit, "-E- Failed to create eth_device");
jlf_files = get_jlf_files_form_path(jlf_dir, &actual_number_of_jlfs_files);
if (NULL == jlf_files) {
printf("-E- Failed to get jlf files from path\n");
status = HAILO_INTERNAL_FAILURE;
goto l_release_device;
}
status = hailo_create_jlf_files(jlf_files, actual_number_of_jlfs_files, jlf_buffer, sizeof(jlf_buffer), &jlf);
REQUIRE_SUCCESS(status, l_release_device, "Failed to create jlf files");
status = hailo_configure_device_from_jlf(device, jlf, jlf_buffer, sizeof(jlf_buffer));
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to configure device from jlf");
// NEDEN
status = hailo_jlf_get_all_stream_infos(jlf, all_stream_infos, NOF_STREAMS, &number_of_streams);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to get all stream info");
for (size_t i=0;i<number_of_streams;i++) {
printf("-D- [%d] direction:%-7s index=%d output_index=%d\n",(int)i, get_direction_name(all_stream_infos[i].direction), all_stream_infos[i].index, output_stream_cnt);
if (all_stream_infos[i].direction==HAILO_H2D_STREAM) {
input_fifo_index = all_stream_infos[i].index;
} else {
output_fifo_indexes[output_stream_cnt++] = all_stream_infos[i].index;
}
}
// If the Input layer is a Dense, need to change the stream config to NC
// Assuming that the input layer name is something like fc1
if (strstr(all_stream_infos[0].name, "fc") != NULL) {
input_stream_params.base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NC;
printf("-I- Setting input as FC layer\n");
}
// input_stream_params.base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_FLOAT32;
// input_stream_params.base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_NONE;
// Create and activate streams
status = hailo_create_eth_input_stream_from_jlf_by_index(device, jlf, input_fifo_index, &input_stream_params, &input_stream);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to create eth_input_stream");
status = hailo_activate_input_stream(device, input_stream);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to activate input stream");
// NEDEN - get all outputs
for (int i=0;i<output_stream_cnt;i++) {
set_default_output_stream_params(&output_streams_params[i]);
// output_streams_params[i].base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_FLOAT32;
// output_streams_params[i].base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_NONE;
status = hailo_jlf_get_stream_info_by_index(jlf, output_fifo_indexes[i], HAILO_D2H_STREAM, &output_streams_info[i]);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to get eth_output_stream");
if ((strstr(output_streams_info[i].name, "fc") != NULL) || (strstr(output_streams_info[i].name, "softmax") != NULL)) {
output_streams_params[i].base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NC;
printf("-I- Setting output %d as FC layer\n",(int)i);
}
status = hailo_create_eth_output_stream_from_jlf_by_index(device, jlf, output_fifo_indexes[i], &output_streams_params[i], &output_streams[i]);
REQUIRE_SUCCESS(status, l_release_input_stream, "Failed to create eth_output_stream");
status = hailo_activate_output_stream(device, output_streams[i]);
REQUIRE_SUCCESS(status, l_release_output_stream, "-E- Failed to activate output stream");
}
//NEDEN: Assuming the input is always on index #0
print_net_banner(all_stream_infos, output_stream_cnt);
// Run inference and compare results
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
status = infer(input_stream, &all_stream_infos[0], output_streams, output_streams_info, output_stream_cnt, num_img, write_log);
REQUIRE_SUCCESS(status, l_release_output_stream, "-E- Inference failure");
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
print_inference_stats(start_time, end_time, all_stream_infos, output_stream_cnt, num_img);
status = HAILO_SUCCESS;
l_release_output_stream:
for (int i=0;i<output_stream_cnt;i++) {
(void) hailo_release_output_stream(device, output_streams[i]);
}
if (debug==1) {
print_debug_stats(device);
REQUIRE_SUCCESS(status, l_release_input_stream, "-E- Failed to read debug registers");
}
l_release_input_stream:
(void) hailo_release_input_stream(device, input_stream);
l_release_jlf:
(void) hailo_release_jlf(jlf);
l_release_device:
(void) hailo_release_device(device);
l_exit:
return status;
}
#include <hailo/hailort.h>
#define FREE(var) \
do \
{ \
if (NULL != (var)) \
{ \
free(var); \
var = NULL; \
} \
} while (0)
#define REQUIRE_SUCCESS(status, label, msg) \
do \
{ \
if (HAILO_SUCCESS != (status)) \
{ \
printf(BOLDRED); \
printf("-E- %s : (%d)\n",msg, status); \
printf(RESET); \
goto label; \
} \
} while (0)
typedef struct write_thread_args_t
{
hailo_stream_info_t *input_stream_info;
hailo_input_stream input_stream;
hailo_status status;
int output_streams_cnt;
unsigned int num_images;
size_t host_frame_size;
} write_thread_args_t;
typedef struct recv_thread_args_t
{
hailo_stream_info_t *output_stream_info;
hailo_output_stream output_stream;
hailo_status status;
int tid;
unsigned int num_images;
int num_streams;
int write_log;
size_t host_frame_size;
} recv_thread_args_t;
typedef struct video_thread_args_t
{
hailo_stream_info_t *input_stream_info;
const char *video_path;
int num_images;
} video_thread_args_t;
#define RESET "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
\ No newline at end of file
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file main.cpp
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include "example_device.hpp"
#include <iostream>
#include <thread>
#include <functional>
#define NOF_DEVICES (2)
void thread_wrapper(std::string &iface, std::string &jlf_dir, unsigned int &num_img)
{
example_device dev(iface, jlf_dir, num_img, 0, 0);
dev.run_inference();
}
int main(int argc, char **argv)
{
std::string jlf_dir;
int opt;
std::string iface;
std::string iface2;
unsigned int num_img = 100;
int debug = 0;
int write_log = 0;
while ((opt = getopt(argc, argv, "i:j:w:n:k:dl")) != -1)
{
switch (opt)
{
case 'j':
jlf_dir = optarg;
break;
case 'i':
iface = optarg;
break;
case 'k':
iface2 = optarg;
break;
case 'n':
num_img = atoi(optarg);
break;
case 'd':
debug = 1;
break;
case 'l':
write_log = 1;
break;
case '?':
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -j JLF-DIR [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -i INTERFACE The Ethernet interface, defaults to \'eno2\'\n");
fprintf(stderr, " -j JLF-DIR The JLFs directory, defaults to \'./JLFs/\'\n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -d Read and print debug registers from FW\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
exit(EXIT_FAILURE);
}
}
try
{
std::cout << "-I- TEST STARTS" << std::endl;
std::thread t0(thread_wrapper, std::ref(iface), std::ref(jlf_dir), std::ref(num_img));
if (!iface2.empty())
{
std::cout << "-I- TEST STARTS" << std::endl;
std::thread t1(thread_wrapper, std::ref(iface2), std::ref(jlf_dir), std::ref(num_img));
t1.join();
}
t0.join();
}
catch (const std::exception &e)
{
std::cout << e.what();
}
}
\ No newline at end of file
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file example.c
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include <net/if.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <linux/limits.h>
#include <time.h>
#include <hailo/hailort.h>
#define INFER_FRAME_COUNT (5000)
#define UNIQUE_FRAMES_COUNT (3)
#define NSEC_IN_SEC (1e+9)
#define JLF_DIR "shortcut_50_2928_1/"
#define FREE(var) \
do { \
if (NULL != (var)) { \
free(var); \
var = NULL; \
} \
} while(0)
#define REQUIRE_SUCCESS(status, label, ...) \
do { \
if (HAILO_SUCCESS != (status)) { \
printf(__VA_ARGS__); \
printf("\n"); \
goto label; \
} \
} while(0)
typedef struct write_thread_args_t {
uint8_t *src_data;
size_t host_frame_size;
hailo_input_stream input_stream;
hailo_status status;
} write_thread_args_t;
void* write_thread_func(void *args)
{
hailo_status status = HAILO_UNINITIALIZED;
write_thread_args_t *write_args = (write_thread_args_t*)args;
for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream,
(uint8_t*)write_args->src_data + (i % UNIQUE_FRAMES_COUNT) * write_args->host_frame_size,
0, write_args->host_frame_size);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_write_all_raw_buffer failed");
}
status = HAILO_SUCCESS;
l_exit:
write_args->status = status;
return NULL;
}
hailo_status read_and_compare(
hailo_output_stream output_stream, size_t host_output_frame_size, uint8_t *dst_data,
size_t host_input_frame_size, uint8_t *src_data)
{
hailo_status status = HAILO_UNINITIALIZED;
int cmp_result = -1;
for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
status = hailo_stream_sync_read_all_raw_buffer(output_stream, dst_data, 0, host_output_frame_size);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_read_all_raw_buffer failed");
cmp_result = memcmp(src_data + (i % UNIQUE_FRAMES_COUNT) * host_input_frame_size, dst_data,
host_input_frame_size);
if (0 != cmp_result) {
printf("Diff in frame number %d\n", i);
// Still success
}
}
l_exit:
return status;
}
hailo_status infer(
hailo_input_stream input_stream, size_t host_input_frame_size, uint8_t *src_data,
hailo_output_stream output_stream, size_t host_output_frame_size, uint8_t *dst_data)
{
hailo_status status = HAILO_UNINITIALIZED;
pthread_t write_thread = 1;
write_thread_args_t write_args = {
.src_data = src_data,
.host_frame_size = host_input_frame_size,
.input_stream = input_stream,
.status = HAILO_UNINITIALIZED
};
// Run write
(void) pthread_create(&write_thread, NULL, write_thread_func, &write_args);
// Receive data in main thread and compare results
status = read_and_compare(output_stream, host_output_frame_size, dst_data, host_input_frame_size, src_data);
if (HAILO_SUCCESS != status) {
printf("read_and_compare failed\n");
status = HAILO_INTERNAL_FAILURE;
// Keep waiting for write thread
}
pthread_join(write_thread, NULL);
if (HAILO_SUCCESS != write_args.status) {
printf("write_thread failed");
status = HAILO_INTERNAL_FAILURE;
}
return status;
}
void print_inference_stats(struct timespec start_time, struct timespec end_time, uint32_t send_frame_size,
uint32_t recv_frame_size)
{
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1000.0f / 1000.0f;
printf("Inference time: %lf seconds\n", infer_time_secs);
printf("Inference fps: %lf\n", INFER_FRAME_COUNT / infer_time_secs);
printf("Inference send data rate: %lf Mbit/s\n",
(double)(INFER_FRAME_COUNT) * send_frame_size * mbit_per_byte / infer_time_secs);
printf("Inference recv data rate: %lf Mbit/s\n",
(double)(INFER_FRAME_COUNT) * recv_frame_size * mbit_per_byte / infer_time_secs);
}
const char** get_jlf_files_form_path(const char *dir_name, uint8_t *actual_number_of_jlfs_files)
{
static char jlf_files[HAILO_MAX_NUMBER_OF_JLFS][PATH_MAX];
static const char *res_jlf_files[HAILO_MAX_NUMBER_OF_JLFS];
DIR *dir = NULL;
struct dirent *entry = NULL;
uint8_t i = 0;
dir = opendir(dir_name);
if (NULL == dir) {
return NULL;
}
entry = readdir(dir);
while (NULL != entry) {
if (entry->d_name[0] != '.') {
(void)snprintf(jlf_files[i], sizeof(jlf_files[i]), "%s%s", dir_name, entry->d_name);
res_jlf_files[i] = jlf_files[i];
i++;
}
entry = readdir(dir);
}
(void) closedir(dir);
*actual_number_of_jlfs_files = i;
return res_jlf_files;
}
int main(int argc, char **argv)
{
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
hailo_eth_device_info_t device_info = {0};
hailo_device device = NULL;
hailo_jlf jlf = NULL;
uint8_t jlf_buffer[16*1024];
uint8_t actual_number_of_jlfs_files = 0;
hailo_input_stream input_stream = NULL;
hailo_output_stream output_stream = NULL;
hailo_eth_input_stream_params_t input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
hailo_eth_output_stream_params_t output_stream_params = HAILO_ETH_OUTPUT_STREAM_PARAMS_DEFAULT;
hailo_stream_info_t input_stream_info = {0};
hailo_stream_info_t output_stream_info = {0};
const char **jlf_files = NULL;
struct timespec start_time = {0};
struct timespec end_time = {0};
uint8_t *src_data = NULL;
uint8_t *dst_data = NULL;
if (2 != argc) {
printf("Wrong amount of arguments was provided (excpecting: 1, provided: %i)\n", (argc - 1));
goto l_exit;
}
status = hailo_scan_ethernet_devices(argv[1], &device_info, 1, &number_of_devices,
HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for eth_devices");
if (0 == number_of_devices) {
printf("No device found on the given interface\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_ethernet_device(&device_info, &device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_device");
jlf_files = get_jlf_files_form_path(JLF_DIR, &actual_number_of_jlfs_files);
if (NULL == jlf_files) {
printf("Failed to get jlf files from path\n");
status = HAILO_INTERNAL_FAILURE;
goto l_release_device;
}
status = hailo_create_jlf_files(jlf_files, actual_number_of_jlfs_files, jlf_buffer, sizeof(jlf_buffer), &jlf);
REQUIRE_SUCCESS(status, l_release_device, "Failed to create jlf files");
status = hailo_configure_device_from_jlf(device, jlf, jlf_buffer, sizeof(jlf_buffer));
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to configure device from jlf");
// Create and activate streams
status = hailo_create_eth_input_stream_from_jlf_by_index(device, jlf, 0, &input_stream_params, &input_stream);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to create eth_input_stream");
status = hailo_create_eth_output_stream_from_jlf_by_index(device, jlf, 1, &output_stream_params, &output_stream);
REQUIRE_SUCCESS(status, l_release_input_stream, "Failed to create eth_output_stream");
status = hailo_jlf_get_stream_info_by_index(jlf, 0, HAILO_H2D_STREAM, &input_stream_info);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to get eth_input_stream");
status = hailo_jlf_get_stream_info_by_index(jlf, 1, HAILO_D2H_STREAM, &output_stream_info);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to get eth_output_stream");
status = hailo_activate_input_stream(device, input_stream);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to activate input stream");
status = hailo_activate_output_stream(device, output_stream);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to activate output stream");
size_t host_input_frame_size = hailo_get_host_frame_size(&input_stream_info, &input_stream_params.base_params);
size_t host_output_frame_size = hailo_get_host_frame_size(&output_stream_info, &output_stream_params.base_params);
src_data = (uint8_t*)malloc(host_input_frame_size * UNIQUE_FRAMES_COUNT);
dst_data = (uint8_t*)malloc(host_output_frame_size);
if ((NULL == src_data) || (NULL == dst_data)) {
printf("Failed to allocate buffers\n");
status = HAILO_OUT_OF_HOST_MEMORY;
goto l_release_buffers;
}
for(size_t i = 0; i < host_input_frame_size * UNIQUE_FRAMES_COUNT; i++) {
src_data[i] = (uint8_t)(rand() % 256);
}
// Run inference and compare results
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
status = infer(
input_stream, host_input_frame_size, src_data,
output_stream, host_output_frame_size, dst_data);
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
REQUIRE_SUCCESS(status, l_release_buffers, "Inference failure");
print_inference_stats(start_time, end_time, input_stream_info.hw_frame_size,
output_stream_info.hw_frame_size);
status = HAILO_SUCCESS;
l_release_buffers:
FREE(dst_data);
FREE(src_data);
l_release_output_stream:
(void) hailo_release_output_stream(device, output_stream);
l_release_input_stream:
(void) hailo_release_input_stream(device, input_stream);
l_release_jlf:
(void) hailo_release_jlf(jlf);
l_release_device:
(void) hailo_release_device(device);
l_exit:
return status;
}
cmake_minimum_required(VERSION 3.0.0)
# Setting the ARCH if not provided
if (NOT DEFINED ARCH)
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch_from_cmd)
string(STRIP ${arch_from_cmd} arch_from_cmd)
set(ARCH ${arch_from_cmd})
endif()
# Setting the CMAKE_C_COMPILER if not provided
if (${ARCH} STREQUAL "aarch64")
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "/usr/bin/aarch64-linux-gnu-gcc")
endif()
else()
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "/usr/bin/gcc")
endif()
endif()
set(HAILORT_ROOT $ENV{HAILORT_ROOT})
set(HAILORT_LIB ${HAILORT_ROOT}/lib/${ARCH}/libhailort.so.2.1.0)
set(HAILORT_INCLUDE_DIR ${HAILORT_ROOT}/include)
message(STATUS ${HAILORT_LIB})
message(STATUS ${HAILORT_INCLUDE_DIR})
set(COMPILE_OPTIONS -DNDEBUG -O3)
find_package(Threads)
foreach(target example shortcut example_1rx_thread)
add_executable(${target} "${target}.c")
include_directories(${HAILORT_INCLUDE_DIR})
target_compile_options(${target} PRIVATE ${COMPILE_OPTIONS})
target_link_libraries(${target} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${target} ${HAILORT_LIB})
endforeach(target)
To Compile all targets to all architectures (x86, armv7l, aarch64):
`build.sh`
\ No newline at end of file
#!/bin/bash
declare -A COMPILER=( [x86_64]=/usr/bin/gcc
[aarch64]=/usr/bin/aarch64-linux-gnu-gcc
[armv7l]=/usr/bin/arm-linux-gnueabi-gcc )
HAILORT_ROOT=/home/nadave/SDK/3.1.0/platform/hailort
for ARCH in x86_64 aarch64 # armv7l
do
echo "-I- Building ${ARCH}"
mkdir -p build/${ARCH}
HAILORT_ROOT=${HAILORT_ROOT} cmake -H. -Bbuild/${ARCH} -DARCH=${ARCH} -DCMAKE_C_COMPILER=${COMPILER[${ARCH}]}
cmake --build build/${ARCH}
done
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file example.c
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include <net/if.h>
#include <pthread.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <linux/limits.h>
#include <time.h>
#include <hailo/hailort.h>
#include "example_utils.h"
#define NOF_STREAMS (15)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
unsigned int actual_measurments;
const char* get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
void* _send_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
uint8_t* src_data = (uint8_t*)malloc(write_args->host_frame_size);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
struct timespec ts;
if (NULL == src_data) {
printf("-E- Failed to allocate buffers\n");
status = HAILO_OUT_OF_HOST_MEMORY;
goto l_release_buffers;
}
for(size_t i = 0; i < write_args->host_frame_size; i++) {
src_data[i] = (uint8_t)(rand() % 256);
}
flag_100 = (uint32_t)write_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
for (uint32_t i = 1; i <= (uint32_t)write_args->num_images; i++) {
if ((i % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] Send frame [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, i, write_args->num_images, src_data[0], src_data[1], src_data[2], src_data[3]);
sent_clock_t[lat_counter++] = ts;
}
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream, src_data, 0, write_args->host_frame_size);
if (status != HAILO_SUCCESS) {
printf("-E- hailo_stream_sync_write_all_raw_buffer failed: %d",status);
break;
}
}
l_release_buffers:
FREE(src_data);
l_exit:
write_args->status = status;
return NULL;
}
void* _recv_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
recv_thread_args_t *recv_args = (recv_thread_args_t *)args;
struct timespec ts;
FILE *fp;
uint8_t *dst_data = (uint8_t*)malloc(recv_args->host_frame_size);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
printf("-I- Recv thread %d started\n", recv_args->tid);
if (recv_args->write_log==1) {
char *log_name = (char*)malloc(20 * sizeof(char));
sprintf(log_name, "tid_%d.log", recv_args->tid);
fp = fopen(log_name, "w");
free(log_name);
}
flag_100 = (uint32_t)recv_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
actual_measurments = 0;
for (uint32_t j = 1; j <= (uint32_t)recv_args->num_images; j++) {
status = hailo_stream_sync_read_all_raw_buffer(recv_args->output_stream, dst_data, 0, recv_args->host_frame_size);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_read_all_raw_buffer failed");
if ((j % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Recv [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, recv_args->tid, j, recv_args->num_images, dst_data[0], dst_data[1], dst_data[2], dst_data[3]);
recv_clock_t[recv_args->tid][lat_counter++] = ts;
actual_measurments++;
}
if (recv_args->write_log==1)
fprintf(fp, "%d Recv [%10ld.%ld s] %3d/%3d %x\n", recv_args->tid, (long)ts.tv_sec, ts.tv_nsec/1000000, j, recv_args->num_images, *dst_data);
}
if (recv_args->write_log==1)
fclose(fp);
l_exit:
free(dst_data);
recv_args->status = status;
return NULL;
}
hailo_status infer(
hailo_input_stream input_stream, hailo_output_stream *output_streams,
int output_stream_cnt, int num_images, int write_log, size_t* host_output_frame_size, size_t host_input_frame_size)
{
hailo_status status = HAILO_SUCCESS;
pthread_t write_thread = 1;
recv_thread_args_t recv_args[NOF_STREAMS-1];
pthread_t recv_threads[NOF_STREAMS-1];
write_thread_args_t write_args = {
.input_stream = input_stream,
.status = HAILO_UNINITIALIZED,
.output_streams_cnt = output_stream_cnt,
.num_images = num_images,
.host_frame_size = host_input_frame_size
};
for (int ii=0; ii<output_stream_cnt; ii++) {
recv_args[ii].output_stream = output_streams[ii];
recv_args[ii].tid = ii;
recv_args[ii].status = HAILO_UNINITIALIZED;
recv_args[ii].num_images = num_images;
recv_args[ii].write_log = write_log;
recv_args[ii].host_frame_size = host_output_frame_size[ii];
(void) pthread_create(&recv_threads[ii], NULL, _recv_thread, &recv_args[ii]);
};
(void) pthread_create(&write_thread, NULL, _send_thread, &write_args);
pthread_join(write_thread, NULL);
if (HAILO_SUCCESS != write_args.status) {
printf("-E- write_thread failed\n");
status = HAILO_INTERNAL_FAILURE;
}
for (int ii=0; ii<output_stream_cnt; ii++) {
pthread_join(recv_threads[ii], NULL);
printf("-I- Closing Recv thread #%d: %d\n", recv_args[ii].tid, recv_args[ii].status);
if (HAILO_SUCCESS != recv_args[ii].status) {
printf("-E- Recv thread %d failed\n", recv_args[ii].tid);
status = HAILO_INTERNAL_FAILURE;
}
}
return status;
}
void print_net_banner(hailo_stream_info_t *all_stream_infos, int cnt) {
printf(BOLDCYAN);
printf("-I-----------------------------------------------\n");
for (int ii=0; ii<=cnt; ii++) {
printf("-I- %s[%d]: %s (%d, %d, %d)\n", get_direction_name(all_stream_infos[ii].direction), ii, all_stream_infos[ii].name, all_stream_infos[ii].shape.height, all_stream_infos[ii].shape.width,
all_stream_infos[ii].shape.features);
}
printf("-I-----------------------------------------------\n");
printf(RESET);
}
double get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (double)(ts.tv_nsec / 1000000.0));
return result;
}
double calc_latency(int count) {
double result = 0;
double cur_rcv;
double cur_snd;
for (int j=0; j<actual_measurments; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
result += (cur_rcv - cur_snd);
}
return result/actual_measurments;
}
void print_inference_stats(struct timespec start_time, struct timespec end_time, hailo_stream_info_t *all_stream_infos, int output_stream_cnt, int num_images, uint32_t latency_readout)
{
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
uint32_t send_frame_size = all_stream_infos[0].hw_frame_size;
uint32_t recv_frame_size = 0;
printf(BOLDGREEN);
printf("-I-----------------------------------------------\n");
printf("-I- Total time: %4.2lf sec\n", infer_time_secs);
printf("-I- Average FPS: %4.2lf\n", num_images / infer_time_secs);
if (num_images==1)
printf("-I- Average Latency: %3.2lf ms\n", calc_latency(output_stream_cnt));
#ifdef FW_LAT
printf("-I- FW latency (Beta): %3.2f ms\n", latency_readout/1000000.0f);
#endif
printf("-I- Send data rate: %-4.2lf Mbit/s\n",
(double)(num_images) * send_frame_size * mbit_per_byte / infer_time_secs);
for (int i=1; i<=output_stream_cnt; i++) {
recv_frame_size = all_stream_infos[i].hw_frame_size;
printf("-I- Recv[%d] data rate: %-4.2lf Mbit/s\n", i,
(double)(num_images) * recv_frame_size * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
const char** get_jlf_files_form_path(const char *dir_name, uint8_t *actual_number_of_jlfs_files) {
static char jlf_files[HAILO_MAX_NUMBER_OF_JLFS][PATH_MAX];
static const char *res_jlf_files[HAILO_MAX_NUMBER_OF_JLFS];
DIR *dir = NULL;
struct dirent *entry = NULL;
uint8_t i = 0;
dir = opendir(dir_name);
if (NULL == dir) {
return NULL;
}
entry = readdir(dir);
while (NULL != entry) {
if (entry->d_name[0] != '.') {
(void)snprintf(jlf_files[i], sizeof(jlf_files[i]), "%s%s", dir_name, entry->d_name);
res_jlf_files[i] = jlf_files[i];
i++;
}
entry = readdir(dir);
}
(void) closedir(dir);
*actual_number_of_jlfs_files = i;
return res_jlf_files;
}
hailo_status print_debug_stats(hailo_device device) {
uint32_t address;
uint8_t* data = (uint8_t*)malloc(4);
uint32_t size = 4;
hailo_status status = HAILO_SUCCESS;
// rx_jabbers
address = 0x0010918C;
status = hailo_read_memory(device, address, data, size);
printf(CYAN);
printf("-I-----------------------------------------------\n");
printf("-D- RX_JABBERS: 0x%d\n", *data);
// fcs_errors
address = 0x00109190;
status = hailo_read_memory(device, address, data, size);
printf("-D- FCS_ERRORS: 0x%d\n", *data);
printf("-I-----------------------------------------------\n");
printf(RESET);
free(data);
return status;
}
void set_default_eth_output_stream_params(hailo_eth_output_stream_params_t* stream) {
stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
stream->device_port = 0;
stream->host_address.sin_family = AF_INET;
stream->host_address.sin_port = 0;
stream->host_address.sin_addr.s_addr = INADDR_ANY;
stream->is_sync_enabled = true;
memset(&stream->host_address.sin_zero, 0, sizeof(stream->host_address.sin_zero));
}
void set_default_pcie_output_stream_params(hailo_pcie_output_stream_params_t* stream) {
stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
}
#ifdef FW_LAT
hailo_status set_latency_measurement(hailo_device device, int image_index, hailo_stream_info_t input_stream_info, hailo_stream_info_t output_stream_info)
{
return hailo_latency_measurement_config(device, 1, (image_index-1)*input_stream_info.hw_shape.height,
output_stream_info.hw_shape.height*image_index, input_stream_info.index, output_stream_info.index);
}
#endif
hailo_status create_and_load_jlfs(hailo_device device, hailo_jlf *jlf, char* jlf_dir)
{
hailo_status status = HAILO_SUCCESS;
const char **jlf_files = NULL;
uint8_t actual_number_of_jlf_files = 0;
uint8_t jlf_buffer[96*1024];
jlf_files = get_jlf_files_form_path(jlf_dir, &actual_number_of_jlf_files);
if (NULL == jlf_files) {
printf("Failed to get jlf files from path\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_jlf_files(jlf_files, actual_number_of_jlf_files, jlf_buffer, sizeof(jlf_buffer), jlf);
REQUIRE_SUCCESS(status, l_exit, "Failed to create jlf files");
status = hailo_configure_device_from_jlf(device, *jlf, jlf_buffer, sizeof(jlf_buffer));
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to configure device from jlf");
status = HAILO_SUCCESS;
goto l_exit;
l_release_jlf:
(void) hailo_release_jlf(*jlf);
l_exit:
return status;
}
hailo_status initialize_eth_device(const char *interface_name, hailo_eth_device_info_t *eth_device_info,
hailo_device *device)
{
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
status = hailo_scan_ethernet_devices(interface_name, eth_device_info, 1, &number_of_devices,
HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for eth_devices");
if (0 == number_of_devices) {
printf("No eth_device found on the given interface\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_ethernet_device(eth_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_device");
status = HAILO_SUCCESS;
l_exit:
return status;
}
hailo_status initialize_pcie_device(hailo_pcie_device_info_t *pcie_device_info, hailo_device *device)
{
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
status = hailo_scan_pcie_devices(pcie_device_info, 1, &number_of_devices);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for pcie_devices");
if (0 == number_of_devices) {
printf("No pcie_device found\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_pcie_device(pcie_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create pcie_device");
status = HAILO_SUCCESS;
l_exit:
return status;
}
hailo_status create_and_activate_eth_streams(hailo_device device, hailo_jlf jlf, hailo_input_stream *input_stream,
hailo_stream_info_t *input_stream_info, hailo_eth_input_stream_params_t *input_stream_params,
hailo_output_stream *output_stream, hailo_stream_info_t *output_stream_info,
hailo_eth_output_stream_params_t *output_stream_params, int* output_stream_cnt)
{
hailo_status status = HAILO_UNINITIALIZED;
hailo_stream_info_t all_stream_infos[NOF_STREAMS] = {};
size_t number_of_streams = 0;
status = hailo_jlf_get_all_stream_infos(jlf, all_stream_infos, sizeof(all_stream_infos), &number_of_streams);
REQUIRE_SUCCESS(status, l_exit, "Failed to get eth_stream_infos");
for (size_t i = 0; i < number_of_streams; i++) {
if (HAILO_H2D_STREAM == all_stream_infos[i].direction) {
*input_stream_info = all_stream_infos[i];
// We need the following code the change the input format in case this is an FC layer
if (all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NC ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NHW) {
input_stream_params->base_params.user_buffer_format.order = all_stream_infos[i].format.order;
}
status = hailo_create_eth_input_stream_from_jlf_by_index(device, jlf, input_stream_info->index,
input_stream_params, input_stream);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_input_stream");
} else if (HAILO_D2H_STREAM == all_stream_infos[i].direction) {
*output_stream_cnt++;
*output_stream_info = all_stream_infos[i];
if (all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NC ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NHW ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
output_stream_params[i].base_params.user_buffer_format.order = all_stream_infos[i].format.order;
}
status = hailo_create_eth_output_stream_from_jlf_by_index(device, jlf, output_stream_info->index,
output_stream_params, output_stream);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_output_stream");
} else {
printf("Invalid stream direction.\n");
status = HAILO_INTERNAL_FAILURE;
}
}
status = hailo_activate_input_stream(device, *input_stream);
REQUIRE_SUCCESS(status, l_release_streams, "Failed to activate input stream");
status = hailo_activate_output_stream(device, *output_stream);
REQUIRE_SUCCESS(status, l_release_streams, "Failed to activate output stream");
status = HAILO_SUCCESS;
goto l_exit;
l_release_streams:
(void) hailo_release_output_stream(device, output_stream);
(void) hailo_release_input_stream(device, input_stream);
l_exit:
return status;
}
hailo_status create_and_activate_pcie_streams(hailo_device device, hailo_jlf jlf, hailo_input_stream *input_stream,
hailo_stream_info_t *streams_info, size_t* host_input_frame_size, hailo_output_stream *output_streams,
size_t* host_output_frame_size, int* output_stream_cnt)
{
hailo_status status = HAILO_SUCCESS;
hailo_pcie_input_stream_params_t pcie_input_stream_params = HAILO_PCIE_STREAM_PARAMS_DEFAULT;
hailo_pcie_output_stream_params_t pcie_output_stream_params[NOF_STREAMS];
hailo_stream_info_t all_stream_infos[NOF_STREAMS] = {};
size_t number_of_streams = 0;
status = hailo_jlf_get_all_stream_infos(jlf, all_stream_infos, sizeof(all_stream_infos), &number_of_streams);
REQUIRE_SUCCESS(status, l_exit, "Failed to get pcie_stream_infos");
for (size_t i = 0; i < number_of_streams; i++) {
streams_info[i] = all_stream_infos[i];
if (HAILO_H2D_STREAM == all_stream_infos[i].direction) {
// We need the following code the change the input format in case this is an FC layer
if (all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NC ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NHW) {
pcie_input_stream_params.base_params.user_buffer_format.order = all_stream_infos[i].format.order;
}
*host_input_frame_size = hailo_get_host_frame_size(&all_stream_infos[i], &pcie_input_stream_params.base_params);
status = hailo_create_pcie_input_stream_from_jlf_by_index(device, jlf, streams_info[i].index,
&pcie_input_stream_params, input_stream);
REQUIRE_SUCCESS(status, l_exit, "Failed to create pcie_input_stream");
status = hailo_activate_input_stream(device, *input_stream);
REQUIRE_SUCCESS(status, l_release_streams, "Failed to activate input stream");
} else if (HAILO_D2H_STREAM == all_stream_infos[i].direction) {
set_default_pcie_output_stream_params(&pcie_output_stream_params[*output_stream_cnt]);
if (all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NC ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NHW ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
pcie_output_stream_params[*output_stream_cnt].base_params.user_buffer_format.order = all_stream_infos[i].format.order;
}
host_output_frame_size[*output_stream_cnt] = hailo_get_host_frame_size(&streams_info[i], &pcie_output_stream_params[*output_stream_cnt].base_params);
status = hailo_create_pcie_output_stream_from_jlf_by_index(device, jlf, streams_info[i].index,
&pcie_output_stream_params[*output_stream_cnt], &output_streams[*output_stream_cnt]);
REQUIRE_SUCCESS(status, l_exit, "Failed to create pcie_output_stream");
status = hailo_activate_output_stream(device, output_streams[*output_stream_cnt]);
REQUIRE_SUCCESS(status, l_release_streams, "Failed to activate output stream");
*output_stream_cnt+=1;
} else {
printf("Invalid stream direction\n");
status = HAILO_INTERNAL_FAILURE;
}
}
l_release_streams:
if (status != HAILO_SUCCESS) {
for (int ii=0;ii<*output_stream_cnt;ii++)
(void) hailo_release_output_stream(device, output_streams[ii]);
(void) hailo_release_input_stream(device, input_stream);
}
l_exit:
return status;
}
hailo_status initiazlie_pcie_inference(hailo_device *device, hailo_input_stream *input_stream, hailo_stream_info_t *streams_info,
hailo_output_stream *output_streams, size_t *host_input_frame_size,
size_t *host_output_frame_size, char* jlf_dir, int* output_stream_cnt)
{
hailo_pcie_device_info_t pcie_device_info = {0};
hailo_jlf jlf = NULL;
hailo_status status = HAILO_UNINITIALIZED;
status = initialize_pcie_device(&pcie_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to initialize pcie_device");
status = create_and_load_jlfs(*device, &jlf, jlf_dir);
REQUIRE_SUCCESS(status, l_exit, "Failed to create and load jlfs");
status = create_and_activate_pcie_streams(*device, jlf, input_stream, streams_info,
host_input_frame_size, output_streams, host_output_frame_size, output_stream_cnt);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to create and activate pcie_streams");
status = HAILO_SUCCESS;
goto l_exit;
l_release_jlf:
(void) hailo_release_jlf(jlf);
l_exit:
return status;
}
hailo_status initizlie_eth_inference(const char* interface_name, hailo_device *device, hailo_input_stream *input_stream, hailo_stream_info_t *input_stream_info,
hailo_output_stream *output_stream, hailo_stream_info_t *output_stream_info, size_t *host_input_frame_size,
size_t *host_output_frame_size, char* jlf_dir, int* output_stream_cnt)
{
hailo_jlf *jlf = NULL;
hailo_status status = HAILO_UNINITIALIZED;
hailo_eth_device_info_t *eth_device_info = {0};
hailo_eth_input_stream_params_t eth_input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
hailo_eth_output_stream_params_t eth_output_stream_params = HAILO_ETH_OUTPUT_STREAM_PARAMS_DEFAULT;
status = initialize_eth_device(interface_name, eth_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to initialize eth_device");
status = create_and_load_jlfs(*device, jlf, jlf_dir);
REQUIRE_SUCCESS(status, l_exit, "Failed to create and load jlfs");
status = create_and_activate_eth_streams(*device, *jlf, input_stream, input_stream_info,
&eth_input_stream_params, output_stream, output_stream_info, &eth_output_stream_params, output_stream_cnt);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to create and activate eth_streams");
*host_input_frame_size = hailo_get_host_frame_size(input_stream_info, &eth_input_stream_params.base_params);
*host_output_frame_size = hailo_get_host_frame_size(output_stream_info, &eth_output_stream_params.base_params);
status = HAILO_SUCCESS;
goto l_exit;
l_release_jlf:
(void) hailo_release_jlf(*jlf);
l_exit:
return status;
}
int main(int argc, char **argv)
{
hailo_status status = HAILO_UNINITIALIZED;
hailo_device device = NULL;
hailo_input_stream input_stream = NULL;
hailo_output_stream output_streams[NOF_STREAMS];
// hailo_eth_input_stream_params_t input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
// hailo_eth_output_stream_params_t output_streams_params[NOF_STREAMS-1];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
// hailo_stream_info_t output_streams_info[NOF_STREAMS-1];
size_t host_input_frame_size = 0;
size_t host_output_frame_size[NOF_STREAMS];
struct timespec start_time = {0};
struct timespec end_time = {0};
size_t number_of_streams = 0;
uint8_t input_fifo_index = 0;
int output_stream_cnt = 0;
uint8_t output_fifo_indexes[NOF_STREAMS-1];
char *jlf_dir = "./JLFs/";
int opt;
char *iface = "pcie";
int num_img = 100;
int debug = 0;
int write_log = 0;
uint32_t latency_readout = 0;
while ((opt = getopt(argc, argv, "i:j:n:dl")) != -1) {
switch (opt) {
case 'j': jlf_dir = optarg; break;
case 'i': iface = optarg; break;
case 'n': num_img = atoi(optarg); break;
case 'd': debug = 1; break;
case 'l': write_log = 1; break;
case '?': fprintf (stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -j JLF-DIR [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -i INTERFACE The Interface, defaults to \'eno2\', can be also \'pcie\'\n");
fprintf(stderr, " -j JLF-DIR The JLFs directory, defaults to \'./JLFs/\'\n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -d Read and print debug registers from FW\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
exit(EXIT_FAILURE);
}
}
printf(BOLDCYAN);
printf("-I- Running on interface: %s %d images\n", iface, num_img);
printf("-I- Reading JLFs from: %s\n", jlf_dir);
printf(RESET);
if (strncmp("pcie", iface, 4) == 0) {
status = initiazlie_pcie_inference(&device, &input_stream, all_stream_infos, output_streams, &host_input_frame_size,
host_output_frame_size, jlf_dir, &output_stream_cnt);
} else {
status = initizlie_eth_inference(iface, &device, &input_stream, &all_stream_infos[0], output_streams, all_stream_infos, &host_input_frame_size,
host_output_frame_size, jlf_dir, &output_stream_cnt);
}
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for PCIe devices");
#ifdef FW_LAT
status = set_latency_measurement(device, num_img/2 /*Image index*/, all_stream_infos[0], all_stream_infos[1]);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to activate latecny measurement in FW");
#endif
print_net_banner(all_stream_infos, output_stream_cnt);
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
status = infer(input_stream, output_streams, output_stream_cnt, num_img, write_log, host_output_frame_size, host_input_frame_size);
#ifdef FW_LAT
status = hailo_latency_measurement_read(device, &latency_readout);
#endif
REQUIRE_SUCCESS(status, l_release_output_stream, "Inference failure");
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
print_inference_stats(start_time, end_time, all_stream_infos, output_stream_cnt, num_img, latency_readout);
status = HAILO_SUCCESS;
l_release_output_stream:
for (int i=0;i<output_stream_cnt;i++)
(void) hailo_release_output_stream(device, output_streams[i]);
if (debug==1) {
print_debug_stats(device);
REQUIRE_SUCCESS(status, l_release_input_stream, "Failed to read debug registers");
}
l_release_input_stream:
(void) hailo_release_input_stream(device, input_stream);
l_release_device:
(void) hailo_release_device(device);
l_exit:
printf(MAGENTA);
printf("-I- Finished gracefully\n");
printf(RESET);
return status;
}
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file example.c
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include <net/if.h>
#include <pthread.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <linux/limits.h>
#include <time.h>
#include <hailo/hailort.h>
#include "example_utils.h"
#define UNIQUE_FRAMES_COUNT (3)
#define NOF_STREAMS (5)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
void* _send_thread(void *args) {
hailo_status status = HAILO_UNINITIALIZED;
write_thread_args_t *write_args = (write_thread_args_t*)args;
uint8_t* src_data = (uint8_t*)malloc(write_args->input_stream_info->shape_size * UNIQUE_FRAMES_COUNT);
//float32_t* src_data = (float32_t*)malloc(write_args->input_stream_info->shape_size * UNIQUE_FRAMES_COUNT * sizeof(float32_t));
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
struct timespec ts;
if (NULL == src_data) {
printf("-E- Failed to allocate buffers\n");
status = HAILO_OUT_OF_HOST_MEMORY;
goto l_release_buffers;
}
for(size_t i = 0; i < write_args->input_stream_info->shape_size * UNIQUE_FRAMES_COUNT; i++) {
//src_data[i] = (float32_t)(rand()%256);
src_data[i] = (uint8_t)(rand() % 256);
}
flag_100 = (uint32_t)write_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
for (uint32_t i = 1; i <= (uint32_t)write_args->num_images; i++) {
if ((i % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] Send frame [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, i, write_args->num_images, src_data[0], src_data[1], src_data[2], src_data[3]);
sent_clock_t[lat_counter++] = ts;
}
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream,
src_data,
0, write_args->input_stream_info->shape_size);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_write_all_raw_buffer failed");
}
status = HAILO_SUCCESS;
l_release_buffers:
FREE(src_data);
l_exit:
write_args->status = status;
return NULL;
}
hailo_status infer(
hailo_input_stream input_stream, hailo_stream_info_t *input_stream_info,
hailo_output_stream *output_streams, hailo_stream_info_t *output_streams_info,
int output_stream_cnt, int num_images, int write_log)
{
hailo_status status = HAILO_SUCCESS;
pthread_t write_thread = 1;
FILE *fp;
char *log_name = (char*)malloc(20 * sizeof(char));
int len = 0;
struct timespec ts;
uint32_t flag_100 = 0;
uint8_t *dst_data;
unsigned lat_counter = 0;
printf("-I- write_log %d\n", write_log);
write_thread_args_t write_args = {
.input_stream_info = input_stream_info,
.input_stream = input_stream,
.status = HAILO_UNINITIALIZED,
.output_streams_cnt = output_stream_cnt,
.num_images = num_images
};
(void) pthread_create(&write_thread, NULL, _send_thread, &write_args);
flag_100 = (uint32_t)num_images / 100;
if (flag_100==0)
flag_100 = 1;
for (int i=0;i<output_stream_cnt;i++) {
if ((int)output_streams_info[i].hw_frame_size>len)
len = (int)output_streams_info[i].hw_frame_size;
}
dst_data = (uint8_t *)malloc(len);
for (uint32_t j = 1; j <= (uint32_t)num_images; j++) {
for (uint32_t jj = 0; jj < (uint32_t)output_stream_cnt; jj++) {
status = hailo_stream_sync_read_all_raw_buffer(output_streams[jj], dst_data, 0, output_streams_info[jj].hw_frame_size);
REQUIRE_SUCCESS(status, l_exit, "-E- hailo_stream_sync_read_all_raw_buffer failed");
if (j % flag_100==0) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] STREAM:%d Recv [%3d/%3d] %x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, jj, j, num_images, *dst_data);
if (lat_counter < LATENCY_MEASUREMENTS) {
recv_clock_t[jj][lat_counter++] = ts;
}
if (write_log==1)
fprintf(fp, "%d Recv [%10ld.%ld s] %3d/%3d %x\n", jj, (long)ts.tv_sec, ts.tv_nsec/1000000, j, num_images, *dst_data);
}
}
}
pthread_join(write_thread, NULL);
if (HAILO_SUCCESS != write_args.status) {
printf("-E- write_thread failed\n");
status = HAILO_INTERNAL_FAILURE;
}
l_exit:
FREE(dst_data);
return status;
}
void print_net_banner(hailo_stream_info_t *all_stream_infos, int cnt) {
printf(BOLDCYAN);
printf("-I-----------------------------------------------\n");
printf("-I- Input: %s (%d, %d, %d)\n", all_stream_infos[0].name, all_stream_infos[0].shape.height, all_stream_infos[0].shape.width,
all_stream_infos[0].shape.features);
for (int ii=1; ii<=cnt; ii++) {
printf("-I- Output[%d]: %s (%d, %d, %d)\n", ii-1, all_stream_infos[ii].name, all_stream_infos[ii].shape.height, all_stream_infos[ii].shape.width,
all_stream_infos[ii].shape.features);
}
printf("-I-----------------------------------------------\n");
printf(RESET);
}
double get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (ts.tv_nsec / 1000000));
return result;
}
double calc_latency(int count) {
double result = 0;
double cur_rcv;
double cur_snd;
for (int j=0; j<LATENCY_MEASUREMENTS; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
result += (cur_rcv - cur_snd);
}
return result/LATENCY_MEASUREMENTS;
}
void print_inference_stats(struct timespec start_time, struct timespec end_time, hailo_stream_info_t *all_stream_infos, int output_stream_cnt, int num_images)
{
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
uint32_t send_frame_size = all_stream_infos[0].hw_frame_size;
uint32_t recv_frame_size = 0;
printf(BOLDGREEN);
printf("-I-----------------------------------------------\n");
printf("-I- Total time: %4.2lf sec\n", infer_time_secs);
printf("-I- Average FPS: %4.2lf\n", num_images / infer_time_secs);
printf("-I- Average Latency: %3.2lf ms\n", calc_latency(output_stream_cnt));
printf("-I- Send data rate: %-4.2lf Mbit/s\n",
(double)(num_images) * send_frame_size * mbit_per_byte / infer_time_secs);
for (int i=1; i<=output_stream_cnt; i++) {
recv_frame_size = all_stream_infos[i].hw_frame_size;
printf("-I- Recv[%d] data rate: %-4.2lf Mbit/s\n", i,
(double)(num_images) * recv_frame_size * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
const char** get_jlf_files_form_path(const char *dir_name, uint8_t *actual_number_of_jlfs_files) {
static char jlf_files[HAILO_MAX_NUMBER_OF_JLFS][PATH_MAX];
static const char *res_jlf_files[HAILO_MAX_NUMBER_OF_JLFS];
DIR *dir = NULL;
struct dirent *entry = NULL;
uint8_t i = 0;
dir = opendir(dir_name);
if (NULL == dir) {
return NULL;
}
entry = readdir(dir);
while (NULL != entry) {
if (entry->d_name[0] != '.') {
(void)snprintf(jlf_files[i], sizeof(jlf_files[i]), "%s%s", dir_name, entry->d_name);
res_jlf_files[i] = jlf_files[i];
i++;
}
entry = readdir(dir);
}
(void) closedir(dir);
*actual_number_of_jlfs_files = i;
return res_jlf_files;
}
const char* get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
hailo_status print_debug_stats(hailo_device device) {
uint32_t address;
uint8_t* data = (uint8_t*)malloc(4);
uint32_t size = 4;
hailo_status status = HAILO_SUCCESS;
// rx_jabbers
address = 0x0010918C;
status = hailo_read_memory(device, address, data, size);
printf(CYAN);
printf("-I-----------------------------------------------\n");
printf("-D- RX_JABBERS: 0x%d\n", *data);
// fcs_errors
address = 0x00109190;
status = hailo_read_memory(device, address, data, size);
printf("-D- FCS_ERRORS: 0x%d\n", *data);
printf("-I-----------------------------------------------\n");
printf(RESET);
return status;
}
void set_default_output_stream_params(hailo_eth_output_stream_params_t* stream) {
// stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.transform_mode = HAILO_STREAM_NO_TRANSFORM;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
stream->device_port = 0;
stream->host_address.sin_family = AF_INET;
stream->host_address.sin_port = 0;
stream->host_address.sin_addr.s_addr = INADDR_ANY;
memset(&stream->host_address.sin_zero, 0, sizeof(stream->host_address.sin_zero));
}
int main(int argc, char **argv)
{
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
hailo_eth_device_info_t device_info = {0};
hailo_device device = NULL;
hailo_jlf jlf = NULL;
uint8_t jlf_buffer[48*1024];
uint8_t actual_number_of_jlfs_files = 0;
hailo_input_stream input_stream = NULL;
hailo_output_stream output_streams[NOF_STREAMS];
hailo_eth_input_stream_params_t input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
hailo_eth_output_stream_params_t output_streams_params[NOF_STREAMS-1];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
hailo_stream_info_t output_streams_info[NOF_STREAMS-1];
const char **jlf_files = NULL;
struct timespec start_time = {0};
struct timespec end_time = {0};
size_t number_of_streams = 0;
uint8_t input_fifo_index = 0;
int output_stream_cnt = 0;
uint8_t output_fifo_indexes[NOF_STREAMS-1];
char *jlf_dir = "./JLFs/";
int opt;
char *iface = "eno2";
int num_img = 100;
int debug = 0;
int write_log = 0;
while ((opt = getopt(argc, argv, "i:j:n:dl")) != -1) {
switch (opt) {
case 'j': jlf_dir = optarg; break;
case 'i': iface = optarg; break;
case 'n': num_img = atoi(optarg); break;
case 'd': debug = 1; break;
case 'l': write_log = 1; break;
case '?': fprintf (stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -j JLF-DIR [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -i INTERFACE The Ethernet interface, defaults to \'eno2\'\n");
fprintf(stderr, " -j JLF-DIR The JLFs directory, defaults to \'./JLFs/\'\n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -d Read and print debug registers from FW\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
exit(EXIT_FAILURE);
}
}
printf("\033[1;36m");
printf("-I- Running on interface: %s %d images\n", iface, num_img);
printf("-I- Reading JLFs from: %s\n", jlf_dir);
printf("\033[0m");
status = hailo_scan_ethernet_devices(iface, &device_info, 1, &number_of_devices, HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for eth_devices");
if (0 == number_of_devices) {
printf("-E- No device found on the given interface\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_ethernet_device(&device_info, &device);
REQUIRE_SUCCESS(status, l_exit, "-E- Failed to create eth_device");
jlf_files = get_jlf_files_form_path(jlf_dir, &actual_number_of_jlfs_files);
if (NULL == jlf_files) {
printf("-E- Failed to get jlf files from path\n");
status = HAILO_INTERNAL_FAILURE;
goto l_release_device;
}
status = hailo_create_jlf_files(jlf_files, actual_number_of_jlfs_files, jlf_buffer, sizeof(jlf_buffer), &jlf);
REQUIRE_SUCCESS(status, l_release_device, "Failed to create jlf files");
status = hailo_configure_device_from_jlf(device, jlf, jlf_buffer, sizeof(jlf_buffer));
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to configure device from jlf");
// NEDEN
status = hailo_jlf_get_all_stream_infos(jlf, all_stream_infos, NOF_STREAMS, &number_of_streams);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to get all stream info");
for (size_t i=0;i<number_of_streams;i++) {
printf("-D- [%d] direction:%-7s index=%d output_index=%d\n",(int)i, get_direction_name(all_stream_infos[i].direction), all_stream_infos[i].index, output_stream_cnt);
if (all_stream_infos[i].direction==HAILO_H2D_STREAM) {
input_fifo_index = all_stream_infos[i].index;
} else {
output_fifo_indexes[output_stream_cnt++] = all_stream_infos[i].index;
}
}
// If the Input layer is a Dense, need to change the stream config to NC
// Assuming that the input layer name is something like fc1
if (strstr(all_stream_infos[0].name, "fc") != NULL) {
input_stream_params.base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NC;
printf("-I- Setting input as FC layer\n");
}
// input_stream_params.base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_FLOAT32;
// input_stream_params.base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_NONE;
// Create and activate streams
status = hailo_create_eth_input_stream_from_jlf_by_index(device, jlf, input_fifo_index, &input_stream_params, &input_stream);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to create eth_input_stream");
status = hailo_activate_input_stream(device, input_stream);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to activate input stream");
// NEDEN - get all outputs
for (int i=0;i<output_stream_cnt;i++) {
set_default_output_stream_params(&output_streams_params[i]);
// output_streams_params[i].base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_FLOAT32;
// output_streams_params[i].base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_NONE;
status = hailo_jlf_get_stream_info_by_index(jlf, output_fifo_indexes[i], HAILO_D2H_STREAM, &output_streams_info[i]);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to get eth_output_stream");
if ((strstr(output_streams_info[i].name, "fc") != NULL) || (strstr(output_streams_info[i].name, "softmax") != NULL)) {
output_streams_params[i].base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NC;
printf("-I- Setting output %d as FC layer\n",(int)i);
}
status = hailo_create_eth_output_stream_from_jlf_by_index(device, jlf, output_fifo_indexes[i], &output_streams_params[i], &output_streams[i]);
REQUIRE_SUCCESS(status, l_release_input_stream, "Failed to create eth_output_stream");
status = hailo_activate_output_stream(device, output_streams[i]);
REQUIRE_SUCCESS(status, l_release_output_stream, "-E- Failed to activate output stream");
}
//NEDEN: Assuming the input is always on index #0
print_net_banner(all_stream_infos, output_stream_cnt);
// Run inference and compare results
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
status = infer(input_stream, &all_stream_infos[0], output_streams, output_streams_info, output_stream_cnt, num_img, write_log);
REQUIRE_SUCCESS(status, l_release_output_stream, "-E- Inference failure");
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
print_inference_stats(start_time, end_time, all_stream_infos, output_stream_cnt, num_img);
status = HAILO_SUCCESS;
l_release_output_stream:
for (int i=0;i<output_stream_cnt;i++) {
(void) hailo_release_output_stream(device, output_streams[i]);
}
if (debug==1) {
print_debug_stats(device);
REQUIRE_SUCCESS(status, l_release_input_stream, "-E- Failed to read debug registers");
}
l_release_input_stream:
(void) hailo_release_input_stream(device, input_stream);
l_release_jlf:
(void) hailo_release_jlf(jlf);
l_release_device:
(void) hailo_release_device(device);
l_exit:
return status;
}
#include <hailo/hailort.h>
#define FREE(var) \
do \
{ \
if (NULL != (var)) \
{ \
free(var); \
var = NULL; \
} \
} while (0)
#define REQUIRE_SUCCESS(status, label, msg) \
do \
{ \
if (HAILO_SUCCESS != (status)) \
{ \
printf(BOLDRED); \
printf("-E- %s : (%d)\n",msg, status); \
printf(RESET); \
goto label; \
} \
} while (0)
typedef struct write_thread_args_t
{
hailo_stream_info_t *input_stream_info;
hailo_input_stream input_stream;
hailo_status status;
int output_streams_cnt;
unsigned int num_images;
size_t host_frame_size;
} write_thread_args_t;
typedef struct recv_thread_args_t
{
hailo_stream_info_t *output_stream_info;
hailo_output_stream output_stream;
hailo_status status;
int tid;
unsigned int num_images;
int num_streams;
int write_log;
size_t host_frame_size;
} recv_thread_args_t;
typedef struct video_thread_args_t
{
hailo_stream_info_t *input_stream_info;
const char *video_path;
int num_images;
} video_thread_args_t;
#define RESET "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
\ No newline at end of file
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file example.c
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include <net/if.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <linux/limits.h>
#include <time.h>
#include <hailo/hailort.h>
#define INFER_FRAME_COUNT (5000)
#define UNIQUE_FRAMES_COUNT (3)
#define NSEC_IN_SEC (1e+9)
#define JLF_DIR "shortcut_50_2928_1/"
#define FREE(var) \
do { \
if (NULL != (var)) { \
free(var); \
var = NULL; \
} \
} while(0)
#define REQUIRE_SUCCESS(status, label, ...) \
do { \
if (HAILO_SUCCESS != (status)) { \
printf(__VA_ARGS__); \
printf("\n"); \
goto label; \
} \
} while(0)
typedef struct write_thread_args_t {
uint8_t *src_data;
size_t host_frame_size;
hailo_input_stream input_stream;
hailo_status status;
} write_thread_args_t;
void* write_thread_func(void *args)
{
hailo_status status = HAILO_UNINITIALIZED;
write_thread_args_t *write_args = (write_thread_args_t*)args;
for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream,
(uint8_t*)write_args->src_data + (i % UNIQUE_FRAMES_COUNT) * write_args->host_frame_size,
0, write_args->host_frame_size);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_write_all_raw_buffer failed");
}
status = HAILO_SUCCESS;
l_exit:
write_args->status = status;
return NULL;
}
hailo_status read_and_compare(
hailo_output_stream output_stream, size_t host_output_frame_size, uint8_t *dst_data,
size_t host_input_frame_size, uint8_t *src_data)
{
hailo_status status = HAILO_UNINITIALIZED;
int cmp_result = -1;
for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
status = hailo_stream_sync_read_all_raw_buffer(output_stream, dst_data, 0, host_output_frame_size);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_read_all_raw_buffer failed");
cmp_result = memcmp(src_data + (i % UNIQUE_FRAMES_COUNT) * host_input_frame_size, dst_data,
host_input_frame_size);
if (0 != cmp_result) {
printf("Diff in frame number %d\n", i);
// Still success
}
}
l_exit:
return status;
}
hailo_status infer(
hailo_input_stream input_stream, size_t host_input_frame_size, uint8_t *src_data,
hailo_output_stream output_stream, size_t host_output_frame_size, uint8_t *dst_data)
{
hailo_status status = HAILO_UNINITIALIZED;
pthread_t write_thread = 1;
write_thread_args_t write_args = {
.src_data = src_data,
.host_frame_size = host_input_frame_size,
.input_stream = input_stream,
.status = HAILO_UNINITIALIZED
};
// Run write
(void) pthread_create(&write_thread, NULL, write_thread_func, &write_args);
// Receive data in main thread and compare results
status = read_and_compare(output_stream, host_output_frame_size, dst_data, host_input_frame_size, src_data);
if (HAILO_SUCCESS != status) {
printf("read_and_compare failed\n");
status = HAILO_INTERNAL_FAILURE;
// Keep waiting for write thread
}
pthread_join(write_thread, NULL);
if (HAILO_SUCCESS != write_args.status) {
printf("write_thread failed");
status = HAILO_INTERNAL_FAILURE;
}
return status;
}
void print_inference_stats(struct timespec start_time, struct timespec end_time, uint32_t send_frame_size,
uint32_t recv_frame_size)
{
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1000.0f / 1000.0f;
printf("Inference time: %lf seconds\n", infer_time_secs);
printf("Inference fps: %lf\n", INFER_FRAME_COUNT / infer_time_secs);
printf("Inference send data rate: %lf Mbit/s\n",
(double)(INFER_FRAME_COUNT) * send_frame_size * mbit_per_byte / infer_time_secs);
printf("Inference recv data rate: %lf Mbit/s\n",
(double)(INFER_FRAME_COUNT) * recv_frame_size * mbit_per_byte / infer_time_secs);
}
const char** get_jlf_files_form_path(const char *dir_name, uint8_t *actual_number_of_jlfs_files)
{
static char jlf_files[HAILO_MAX_NUMBER_OF_JLFS][PATH_MAX];
static const char *res_jlf_files[HAILO_MAX_NUMBER_OF_JLFS];
DIR *dir = NULL;
struct dirent *entry = NULL;
uint8_t i = 0;
dir = opendir(dir_name);
if (NULL == dir) {
return NULL;
}
entry = readdir(dir);
while (NULL != entry) {
if (entry->d_name[0] != '.') {
(void)snprintf(jlf_files[i], sizeof(jlf_files[i]), "%s%s", dir_name, entry->d_name);
res_jlf_files[i] = jlf_files[i];
i++;
}
entry = readdir(dir);
}
(void) closedir(dir);
*actual_number_of_jlfs_files = i;
return res_jlf_files;
}
int main(int argc, char **argv)
{
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
hailo_eth_device_info_t device_info = {0};
hailo_device device = NULL;
hailo_jlf jlf = NULL;
uint8_t jlf_buffer[16*1024];
uint8_t actual_number_of_jlfs_files = 0;
hailo_input_stream input_stream = NULL;
hailo_output_stream output_stream = NULL;
hailo_eth_input_stream_params_t input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
hailo_eth_output_stream_params_t output_stream_params = HAILO_ETH_OUTPUT_STREAM_PARAMS_DEFAULT;
hailo_stream_info_t input_stream_info = {0};
hailo_stream_info_t output_stream_info = {0};
const char **jlf_files = NULL;
struct timespec start_time = {0};
struct timespec end_time = {0};
uint8_t *src_data = NULL;
uint8_t *dst_data = NULL;
if (2 != argc) {
printf("Wrong amount of arguments was provided (excpecting: 1, provided: %i)\n", (argc - 1));
goto l_exit;
}
status = hailo_scan_ethernet_devices(argv[1], &device_info, 1, &number_of_devices,
HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for eth_devices");
if (0 == number_of_devices) {
printf("No device found on the given interface\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_ethernet_device(&device_info, &device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_device");
jlf_files = get_jlf_files_form_path(JLF_DIR, &actual_number_of_jlfs_files);
if (NULL == jlf_files) {
printf("Failed to get jlf files from path\n");
status = HAILO_INTERNAL_FAILURE;
goto l_release_device;
}
status = hailo_create_jlf_files(jlf_files, actual_number_of_jlfs_files, jlf_buffer, sizeof(jlf_buffer), &jlf);
REQUIRE_SUCCESS(status, l_release_device, "Failed to create jlf files");
status = hailo_configure_device_from_jlf(device, jlf, jlf_buffer, sizeof(jlf_buffer));
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to configure device from jlf");
// Create and activate streams
status = hailo_create_eth_input_stream_from_jlf_by_index(device, jlf, 0, &input_stream_params, &input_stream);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to create eth_input_stream");
status = hailo_create_eth_output_stream_from_jlf_by_index(device, jlf, 1, &output_stream_params, &output_stream);
REQUIRE_SUCCESS(status, l_release_input_stream, "Failed to create eth_output_stream");
status = hailo_jlf_get_stream_info_by_index(jlf, 0, HAILO_H2D_STREAM, &input_stream_info);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to get eth_input_stream");
status = hailo_jlf_get_stream_info_by_index(jlf, 1, HAILO_D2H_STREAM, &output_stream_info);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to get eth_output_stream");
status = hailo_activate_input_stream(device, input_stream);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to activate input stream");
status = hailo_activate_output_stream(device, output_stream);
REQUIRE_SUCCESS(status, l_release_output_stream, "Failed to activate output stream");
size_t host_input_frame_size = hailo_get_host_frame_size(&input_stream_info, &input_stream_params.base_params);
size_t host_output_frame_size = hailo_get_host_frame_size(&output_stream_info, &output_stream_params.base_params);
src_data = (uint8_t*)malloc(host_input_frame_size * UNIQUE_FRAMES_COUNT);
dst_data = (uint8_t*)malloc(host_output_frame_size);
if ((NULL == src_data) || (NULL == dst_data)) {
printf("Failed to allocate buffers\n");
status = HAILO_OUT_OF_HOST_MEMORY;
goto l_release_buffers;
}
for(size_t i = 0; i < host_input_frame_size * UNIQUE_FRAMES_COUNT; i++) {
src_data[i] = (uint8_t)(rand() % 256);
}
// Run inference and compare results
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
status = infer(
input_stream, host_input_frame_size, src_data,
output_stream, host_output_frame_size, dst_data);
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
REQUIRE_SUCCESS(status, l_release_buffers, "Inference failure");
print_inference_stats(start_time, end_time, input_stream_info.hw_frame_size,
output_stream_info.hw_frame_size);
status = HAILO_SUCCESS;
l_release_buffers:
FREE(dst_data);
FREE(src_data);
l_release_output_stream:
(void) hailo_release_output_stream(device, output_stream);
l_release_input_stream:
(void) hailo_release_input_stream(device, input_stream);
l_release_jlf:
(void) hailo_release_jlf(jlf);
l_release_device:
(void) hailo_release_device(device);
l_exit:
return status;
}
cmake_minimum_required(VERSION 3.0.0)
# Setting the ARCH if not provided
if (NOT DEFINED ARCH)
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch_from_cmd)
string(STRIP ${arch_from_cmd} arch_from_cmd)
set(ARCH ${arch_from_cmd})
endif()
# Setting the CMAKE_C_COMPILER if not provided
if (${ARCH} STREQUAL "aarch64")
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "/usr/bin/aarch64-linux-gnu-gcc")
endif()
else()
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "/usr/bin/gcc")
endif()
endif()
set(HAILORT_ROOT $ENV{HAILORT_ROOT})
set(HAILORT_LIB /home/nadave/SDK/platform-sw/lib/linux.x86_64.debug/libhailort.so.2.4.0)
set(HAILORT_LIB ${HAILORT_ROOT}/lib/${ARCH}/libhailort.so.2.4.0)
set(HAILORT_INCLUDE_DIR /home/nadave/SDK/platform-sw/hailort/include/)
set(HAILORT_INCLUDE_DIR ${HAILORT_ROOT}/include)
message(STATUS ${HAILORT_LIB})
message(STATUS ${HAILORT_INCLUDE_DIR})
set(COMPILE_OPTIONS -Wall)
find_package(Threads)
foreach(target example example-hef)
add_executable(${target} "${target}.c")
include_directories(${HAILORT_INCLUDE_DIR})
target_compile_options(${target} PRIVATE ${COMPILE_OPTIONS})
target_link_libraries(${target} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${target} ${HAILORT_LIB})
endforeach(target)
To Compile all targets to all architectures (x86, armv7l, aarch64):
`build.sh`
\ No newline at end of file
#!/bin/bash
declare -A COMPILER=( [x86_64]=/usr/bin/gcc
[aarch64]=/usr/bin/aarch64-linux-gnu-gcc
[armv7l]=/usr/bin/arm-linux-gnueabi-gcc )
HAILORT_ROOT=/home/nadave/SDK/platform-sw/hailort
HAILORT_ROOT=/home/nadave/Platform/3.4.0/platform/hailort
for ARCH in x86_64 aarch64
do
echo "-I- Building ${ARCH}"
mkdir -p build/${ARCH}
HAILORT_ROOT=${HAILORT_ROOT} cmake -H. -Bbuild/${ARCH} -DARCH=${ARCH} -DCMAKE_C_COMPILER=${COMPILER[${ARCH}]}
cmake --build build/${ARCH}
done
if [[ -f "hailort.log" ]]; then
rm hailort.log
fi
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file example.c
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include <net/if.h>
#include <pthread.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <linux/limits.h>
#include <time.h>
#include <hailo/hailort.h>
#include "example_utils.h"
#define NOF_STREAMS (15)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
unsigned int actual_measurments;
const char* get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
void* _send_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
uint32_t input_size = write_args->frame_hw_size;
uint8_t* src_data = (uint8_t*)malloc(input_size);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
struct timespec ts;
float delay = 0.0;
printf("-I- Send Thread stated TX frame size:%d\n", input_size);
if (NULL == src_data) {
printf("-E- Failed to allocate buffers\n");
status = HAILO_OUT_OF_HOST_MEMORY;
goto l_release_buffers;
}
for(size_t i = 0; i < input_size; i++) {
src_data[i] = (uint8_t)(rand() % 256);
}
flag_100 = (uint32_t)write_args->num_images / 10;
if (flag_100==0)
flag_100 = 1;
if (write_args->source_fps > 0) {
delay = 1000000.0 / write_args->source_fps;
printf(CYAN);
printf("-I- Setting the delay to %f usec\n", delay);
printf(RESET);
}
for (uint32_t i = 1; i <= (uint32_t)write_args->num_images; i++) {
if (delay > 0.0)
usleep(delay);
if ((i % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] Send frame [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, i, write_args->num_images, src_data[0], src_data[1], src_data[2], src_data[3]);
sent_clock_t[lat_counter++] = ts;
}
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream, src_data, 0, input_size);
if (status != HAILO_SUCCESS) {
printf("-E- hailo_stream_sync_write_all_raw_buffer failed: %d\n",status);
break;
}
}
l_release_buffers:
FREE(src_data);
write_args->status = status;
return NULL;
}
double get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (double)(ts.tv_nsec / 1000000.0));
return result;
}
void* _recv_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
recv_thread_args_t *recv_args = (recv_thread_args_t *)args;
uint32_t datasize = recv_args->frame_hw_size;
struct timespec ts;
uint8_t *dst_data = (uint8_t*)malloc(datasize);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
printf("-I- Recv thread %d started, datasize: %d\n", recv_args->tid, datasize);
flag_100 = (uint32_t)recv_args->num_images / 10;
if (flag_100==0)
flag_100 = 1;
actual_measurments = 0;
for (uint32_t j = 1; j <= (uint32_t)recv_args->num_images; j++) {
status = hailo_stream_sync_read_all_raw_buffer(recv_args->output_stream, dst_data, 0, datasize);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_read_all_raw_buffer failed");
if ((j % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Recv [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, recv_args->tid, j, recv_args->num_images, dst_data[0], dst_data[1], dst_data[2], dst_data[3]);
recv_clock_t[recv_args->tid][lat_counter++] = ts;
actual_measurments++;
}
}
l_exit:
FREE(dst_data);
recv_args->status = status;
return NULL;
}
hailo_status infer(
hailo_input_stream input_stream, hailo_output_stream *output_streams, hailo_stream_info_t *all_strems_info,
int output_stream_cnt, int num_images, int write_log, size_t* host_output_frame_size, size_t host_input_frame_size, int source_fps)
{
hailo_status status = HAILO_SUCCESS;
pthread_t write_thread = 1;
recv_thread_args_t recv_args[NOF_STREAMS-1];
pthread_t recv_threads[NOF_STREAMS-1];
// struct timespec st, et;
// uint8_t* src_data = (uint8_t*)malloc(all_strems_info[0].hw_frame_size);
// uint8_t* dst_data = (uint8_t*)malloc(all_strems_info[1].hw_frame_size);
write_thread_args_t write_args = {
.input_stream = input_stream,
.status = HAILO_UNINITIALIZED,
.output_streams_cnt = output_stream_cnt,
.num_images = num_images,
.host_frame_size = host_input_frame_size,
.frame_hw_size = all_strems_info[0].hw_frame_size,
.source_fps = source_fps
};
for (int ii=0; ii<output_stream_cnt; ii++) {
recv_args[ii].output_stream = output_streams[ii];
recv_args[ii].tid = ii;
recv_args[ii].status = HAILO_UNINITIALIZED;
recv_args[ii].num_images = num_images;
recv_args[ii].write_log = write_log;
recv_args[ii].host_frame_size = host_output_frame_size[ii];
recv_args[ii].frame_hw_size = all_strems_info[ii+1].hw_frame_size;
(void) pthread_create(&recv_threads[ii], NULL, _recv_thread, &recv_args[ii]);
};
(void) pthread_create(&write_thread, NULL, _send_thread, &write_args);
pthread_join(write_thread, NULL);
if (HAILO_SUCCESS != write_args.status) {
printf("-E- write_thread failed\n");
status = HAILO_INTERNAL_FAILURE;
}
for (int ii=0; ii<output_stream_cnt; ii++) {
pthread_join(recv_threads[ii], NULL);
printf("-I- Closing Recv thread #%d: %d\n", recv_args[ii].tid, recv_args[ii].status);
if (HAILO_SUCCESS != recv_args[ii].status) {
printf("-E- Recv thread %d failed\n", recv_args[ii].tid);
status = HAILO_INTERNAL_FAILURE;
}
}
// for (uint32_t i = 1; i <= (uint32_t)num_images; i++) {
// clock_gettime(CLOCK_REALTIME, &st);
// status = hailo_stream_sync_write_all_raw_buffer(input_stream, src_data, 0, all_strems_info[0].hw_frame_size);
// status = hailo_stream_sync_read_all_raw_buffer(output_streams[0], dst_data, 0, all_strems_info[1].hw_frame_size);
// clock_gettime(CLOCK_REALTIME, &et);
// printf("-I- [%f ms] Infer [%3d/%3d]\n", get_time_from_ts(et)-get_time_from_ts(st), i, num_images);
// }
// FREE(src_data);
// FREE(dst_data);
return status;
}
void print_net_banner(hailo_stream_info_t *all_stream_infos, int cnt) {
printf(BOLDCYAN);
printf("-I-----------------------------------------------\n");
for (int ii=0; ii<=cnt; ii++) {
if (all_stream_infos[ii].format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
printf("-I- %s[%d]: %s (cls:%d, max_out:%d, bbox_params:%d, bbox_size:%d, total_size:%d)\n", get_direction_name(all_stream_infos[ii].direction), ii, all_stream_infos[ii].name,
all_stream_infos[ii].nms_params.number_of_classes,
all_stream_infos[ii].nms_params.max_output_size,
all_stream_infos[ii].nms_params.bbox_params,
all_stream_infos[ii].nms_params.bbox_size,
all_stream_infos[ii].nms_params.total_size);
} else {
printf("-I- %s[%d]: %s (%d, %d, %d)\n", get_direction_name(all_stream_infos[ii].direction), ii, all_stream_infos[ii].name, all_stream_infos[ii].shape.height, all_stream_infos[ii].shape.width,
all_stream_infos[ii].shape.features);
}
}
printf("-I-----------------------------------------------\n");
printf(RESET);
}
double calc_latency(int count, double precentile, int write_log) {
double cur_rcv;
double cur_snd;
double latencies[actual_measurments];
for (int j=0; j<actual_measurments; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
latencies[j] = (cur_rcv - cur_snd);
}
if ((precentile<0) || (precentile>1)) {
precentile = 0.5;
}
if (write_log>0) {
FILE *fp = fopen("latency_redouts.txt", "w");
for (int ii=0; ii<actual_measurments; ii++) {
fprintf(fp, "%f\n",latencies[ii]);
}
fclose(fp);
}
return latencies[(int)(precentile * actual_measurments)];
}
void print_inference_stats(struct timespec start_time, struct timespec end_time, hailo_stream_info_t *all_stream_infos, int output_stream_cnt,
int num_images, uint32_t latency_readout, int write_log, hailo_latency_measurement_result_t driver_lat)
{
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
uint32_t send_frame_size = all_stream_infos[0].hw_frame_size;
uint32_t recv_frame_size = 0;
printf(BOLDGREEN);
printf("-I-----------------------------------------------\n");
printf("-I- Total time: %4.2lf sec\n", infer_time_secs);
printf("-I- Average FPS: %4.2lf\n", num_images / infer_time_secs);
printf("-I- 95p Latency: %3.2lf ms\n", calc_latency(output_stream_cnt, 0.95, write_log));
printf("-I- Driver Latency: %3.2lf ms\n", driver_lat.avg_hw_latency_ms);
// if (num_images==1)
// printf("-I- Average Latency: %3.2lf ms\n", calc_latency(output_stream_cnt));
printf("-I- Send data rate: %-4.2lf Mbit/s\n",
(double)(num_images) * send_frame_size * mbit_per_byte / infer_time_secs);
for (int i=1; i<=output_stream_cnt; i++) {
recv_frame_size = all_stream_infos[i].hw_frame_size;
printf("-I- Recv[%d] data rate: %-4.2lf Mbit/s\n", i,
(double)(num_images) * recv_frame_size * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
void set_default_eth_output_stream_params(hailo_eth_output_stream_params_t* stream) {
stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
stream->device_port = 0;
stream->host_address.sin_family = AF_INET;
stream->host_address.sin_port = 0;
stream->host_address.sin_addr.s_addr = INADDR_ANY;
stream->base_params.buffers_threshold = 1;
// stream->is_sync_enabled = true;
memset(&stream->host_address.sin_zero, 0, sizeof(stream->host_address.sin_zero));
}
void set_default_pcie_output_stream_params(hailo_pcie_output_stream_params_t* stream) {
stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
}
hailo_status create_and_load_hef(hailo_device device, hailo_hef *hef, char* hef_file, hailo_network_group *network_group)
{
hailo_status status = HAILO_SUCCESS;
size_t number_of_network_groups = 1;
status = hailo_create_hef_file(hef, hef_file);
REQUIRE_SUCCESS(status, l_exit, "Failed to create hef file");
printf(MAGENTA);
printf("-I- Loading HEF file from %s\n", hef_file);
printf(RESET);
status = hailo_configure_device_from_hef(device, *hef, network_group, &number_of_network_groups);
REQUIRE_SUCCESS(status, l_exit, "Failed to configure device from hef");
if (number_of_network_groups > 1) {
status = HAILO_UNINITIALIZED;
printf("-E- Got network_group=%ld", number_of_network_groups);
REQUIRE_SUCCESS(status, l_exit, "Failed to extract network group, larger than 1");
}
l_exit:
return status;
}
hailo_status activate_network_group(hailo_network_group network_group, hailo_activated_network_group *active_net_g, hailo_input_stream_params_by_name_t *input_stream_params, hailo_output_stream_params_by_name_t *output_stream_param)
{
hailo_status status = HAILO_SUCCESS;
hailo_network_group_params_t network_group_params = {0};//HAILO_NETWORK_GROUP_PARAMS_DEFAULT;
size_t out_param_size = 4;
size_t in_param_size = 1;
hailo_stream_transform_mode_t transform_mode = HAILO_STREAM_NO_TRANSFORM;// HAILO_STREAM_TRANSOFRM_COPY
status = hailo_make_input_stream_params(network_group, transform_mode, true, HAILO_FORMAT_TYPE_UINT8, input_stream_params, &in_param_size);
REQUIRE_SUCCESS(status, l_exit, "Failed to create input_params");
status = hailo_make_output_stream_params(network_group, transform_mode, true, HAILO_FORMAT_TYPE_UINT8, output_stream_param, &out_param_size);
REQUIRE_SUCCESS(status, l_exit, "Failed to create output_params");
if (output_stream_param->params.pcie_params.base_params.user_buffer_format.order != HAILO_FORMAT_ORDER_HAILO_NMS)
network_group_params.latency = HAILO_LATENCY_MEASURE;
network_group_params.context_switch_batch_size = 1;
output_stream_param->params.eth_params.base_params.buffers_threshold = 1;
input_stream_params->params.eth_params.base_params.buffers_threshold = 1;
status = hailo_activate_network_group(network_group,
&network_group_params,
input_stream_params, // Input params
in_param_size, // number of inputs
output_stream_param, // Output params
out_param_size, // number of ouputs
active_net_g);
REQUIRE_SUCCESS(status, l_exit, "Failed to activate network group");
l_exit:
return status;
}
hailo_status initialize_eth_device(const char *interface_name, hailo_device *device)
{
hailo_status status = HAILO_SUCCESS;
hailo_eth_device_info_t eth_device_info = {0};
size_t number_of_devices = 0;
status = hailo_scan_ethernet_devices(interface_name, &eth_device_info, 1, &number_of_devices, HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for eth_devices");
if (0 == number_of_devices) {
printf("No eth_device found on the given interface\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_ethernet_device(&eth_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_device");
l_exit:
return status;
}
hailo_status initialize_pcie_device(hailo_pcie_device_info_t *pcie_device_info, hailo_device *device)
{
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
status = hailo_scan_pcie_devices(pcie_device_info, 2, &number_of_devices);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for pcie_devices");
if (0 == number_of_devices) {
printf("No pcie_device found\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_pcie_device(pcie_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create pcie_device");
status = HAILO_SUCCESS;
l_exit:
return status;
}
hailo_status get_host_in_out_frame_sizes(hailo_hef hef, hailo_stream_info_t *streams_info, size_t* host_input_frame_size,
size_t* host_output_frame_size, size_t* output_stream_cnt)
{
hailo_status status = HAILO_SUCCESS;
hailo_pcie_input_stream_params_t pcie_input_stream_params = HAILO_PCIE_STREAM_PARAMS_DEFAULT;
hailo_pcie_output_stream_params_t pcie_output_stream_params[NOF_STREAMS];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
size_t number_of_streams = 0;
status = hailo_hef_get_all_stream_infos(hef, NULL, all_stream_infos, sizeof(all_stream_infos), &number_of_streams);
for (size_t i = 0; i < number_of_streams; i++) {
streams_info[i] = all_stream_infos[i];
if (HAILO_H2D_STREAM == all_stream_infos[i].direction) {
// We need the following code the change the input format in case this is an FC layer
if (all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NC ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NHW) {
pcie_input_stream_params.base_params.user_buffer_format.order = all_stream_infos[i].format.order;
}
*host_input_frame_size = hailo_get_host_frame_size(&all_stream_infos[i], &pcie_input_stream_params.base_params);
} else if (HAILO_D2H_STREAM == all_stream_infos[i].direction) {
set_default_pcie_output_stream_params(&pcie_output_stream_params[*output_stream_cnt]);
if (all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NC ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NHW ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
pcie_output_stream_params[*output_stream_cnt].base_params.user_buffer_format.order = all_stream_infos[i].format.order;
pcie_output_stream_params[*output_stream_cnt].base_params.user_buffer_format.type = streams_info[i].format.type;
}
host_output_frame_size[*output_stream_cnt] = hailo_get_host_frame_size(&streams_info[i], &pcie_output_stream_params[*output_stream_cnt].base_params);
*output_stream_cnt+=1;
} else {
printf("Invalid stream direction\n");
status = HAILO_INTERNAL_FAILURE;
}
}
return status;
}
hailo_status initiazlie_inference(hailo_device *device, hailo_input_stream *input_stream, hailo_stream_info_t *streams_info,
hailo_output_stream *output_streams, size_t *host_input_frame_size, size_t *host_output_frame_size, char* hef_path, size_t* output_stream_cnt,
hailo_activated_network_group *active_net_g, const char *interface)
{
// NADAV: Added two devices to support multiple M.2 connected to the machine
hailo_pcie_device_info_t pcie_device_info[2];
hailo_hef hef = NULL;
hailo_status status = HAILO_SUCCESS;
hailo_network_group network_groups = NULL;
hailo_input_stream_params_by_name_t input_stream_params = {0};
hailo_output_stream_params_by_name_t output_stream_params[4];
if (strncmp("pcie", interface, 4) == 0) {
status = initialize_pcie_device(pcie_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to initialize PCIe device");
} else {
status = initialize_eth_device(interface, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to initialize Eth device");
}
status = create_and_load_hef(*device, &hef, hef_path, &network_groups);
REQUIRE_SUCCESS(status, l_exit, "Failed to create and load HEF");
status = activate_network_group(network_groups, active_net_g, &input_stream_params, output_stream_params);
REQUIRE_SUCCESS(status, l_release_hef, "Failed to activate network group and streams");
status = get_host_in_out_frame_sizes(hef, streams_info, host_input_frame_size, host_output_frame_size, output_stream_cnt);
REQUIRE_SUCCESS(status, l_release_hef, "Failed to create and activate pcie_streams");
status = hailo_get_input_stream_by_name(*active_net_g, streams_info[0].name, input_stream);
REQUIRE_SUCCESS(status, l_release_hef, "Failed getting stream info for input");
for (size_t i = 0; i < *output_stream_cnt; i++) {
status = hailo_get_output_stream_by_name(*active_net_g, streams_info[i+1].name, &output_streams[i]);
REQUIRE_SUCCESS(status, l_release_hef, "Failed getting stream info for output");
}
l_release_hef:
(void) hailo_release_hef(hef);
if (status != HAILO_SUCCESS) {
for (int ii=0;ii<*output_stream_cnt;ii++)
(void) hailo_release_output_stream(device, output_streams[ii]);
(void) hailo_release_input_stream(device, input_stream);
}
l_exit:
return status;
}
int main(int argc, char **argv)
{
hailo_status status = HAILO_SUCCESS;
hailo_device device = NULL;
hailo_input_stream input_stream = NULL;
hailo_output_stream output_streams[NOF_STREAMS];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
size_t host_input_frame_size = 0;
size_t host_output_frame_size[NOF_STREAMS];
struct timespec start_time = {0};
struct timespec end_time = {0};
size_t output_stream_cnt = 0;
char *config = "./JLFs/";
int opt;
char *iface = "pcie";
int num_img = 100;
int write_log = 0;
int source_fps = 0;
hailo_activated_network_group activated_network_group = NULL;
hailo_latency_measurement_result_t driver_result = {0};
uint32_t latency_readout = 0;
while ((opt = getopt(argc, argv, "f:i:c:n:l")) != -1) {
switch (opt) {
case 'c': config = optarg; break;
case 'i': iface = optarg; break;
case 'n': num_img = atoi(optarg); break;
case 'f': source_fps = atoi(optarg); break;
case 'l': write_log = 1; break;
case '?': fprintf (stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -c HEF [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -i INTERFACE The Interface, defaults to \'eno2\', can be also \'pcie\'\n");
fprintf(stderr, " -c HEF FILE The HEF config file \n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -f FPS Emulate the source FPS (defaults to inf.)\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
exit(EXIT_FAILURE);
}
}
printf(BOLDCYAN);
printf("-I- Running on interface: %s for %d images\n", iface, num_img);
printf(RESET);
status = initiazlie_inference(&device, &input_stream, all_stream_infos, output_streams, &host_input_frame_size,
host_output_frame_size, config, &output_stream_cnt, &activated_network_group, iface);
REQUIRE_SUCCESS(status, l_release_device, "Failed to initialize inference");
print_net_banner(all_stream_infos, output_stream_cnt);
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
status = infer(input_stream, output_streams, all_stream_infos, output_stream_cnt, num_img, write_log, host_output_frame_size, host_input_frame_size, source_fps);
REQUIRE_SUCCESS(status, l_release_output_stream, "Inference failure");
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
// Getting the latency from the driver
status = hailo_get_latency_measurement(activated_network_group, &driver_result);
print_inference_stats(start_time, end_time, all_stream_infos, output_stream_cnt, num_img, latency_readout, write_log, driver_result);
l_release_output_stream:
for (int i=0;i<output_stream_cnt;i++)
(void) hailo_release_output_stream(device, output_streams[i]);
(void) hailo_release_input_stream(device, input_stream);
l_release_device:
// (void) hailo_deactivate_network_group(activated_network_group);
if (device != NULL)
(void) hailo_release_device(device);
printf(MAGENTA);
printf("-I- Finished gracefully\n");
printf(RESET);
return status;
}
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file example.c
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include <net/if.h>
#include <pthread.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <linux/limits.h>
#include <time.h>
#include <hailo/hailort.h>
#include "example_utils.h"
#define NOF_STREAMS (15)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
unsigned int actual_measurments;
const char* get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
void* _send_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
uint32_t datasize = write_args->host_frame_size;
uint8_t* src_data = (uint8_t*)malloc(datasize);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
struct timespec ts;
FILE *fp;
float delay = 0.0;
if (NULL == src_data) {
printf("-E- Failed to allocate buffers\n");
status = HAILO_OUT_OF_HOST_MEMORY;
goto l_release_buffers;
}
for(size_t i = 0; i < datasize; i++) {
src_data[i] = (uint8_t)(rand() % 256);
}
printf("-I- Input datasize: %d\n", datasize);
if (write_args->write_log==1) {
char *log_name = (char*)malloc(20 * sizeof(char));
sprintf(log_name, "tx_tid_%d.log", write_args->tid);
fp = fopen(log_name, "w");
free(log_name);
}
flag_100 = (uint32_t)write_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
if (write_args->source_fps > 0) {
// Adding 20% to match the requested FPS
delay = 800000.0 / write_args->source_fps;
printf(CYAN);
printf("-I- Setting the delay to %f usec\n", delay);
printf(RESET);
}
for (uint32_t i = 1; i <= (uint32_t)write_args->num_images; i++) {
if (delay > 0.0)
usleep(delay);
if ((i % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] Send frame [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, i, write_args->num_images, src_data[0], src_data[1], src_data[2], src_data[3]);
sent_clock_t[lat_counter++] = ts;
}
if (write_args->write_log==1)
fprintf(fp, "%d Sending [%10ld.%ld s] %3d/%3d %x\n", write_args->tid, (long)ts.tv_sec, ts.tv_nsec/1000000, i, write_args->num_images, *src_data);
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream, src_data, 0, datasize);
if (status != HAILO_SUCCESS) {
printf("-E- hailo_stream_sync_write_all_raw_buffer failed: %d",status);
break;
}
}
if (write_args->write_log==1)
fclose(fp);
l_release_buffers:
FREE(src_data);
l_exit:
write_args->status = status;
return NULL;
}
void* _recv_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
recv_thread_args_t *recv_args = (recv_thread_args_t *)args;
uint32_t datasize = recv_args->host_frame_size;
struct timespec ts;
FILE *fp;
uint8_t *dst_data = (uint8_t*)malloc(datasize);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
printf("-I- Recv thread %d started, datasize: %d\n", recv_args->tid, datasize);
if (recv_args->write_log==1) {
char *log_name = (char*)malloc(20 * sizeof(char));
sprintf(log_name, "rx_tid_%d.log", recv_args->tid);
fp = fopen(log_name, "w");
free(log_name);
}
flag_100 = (uint32_t)recv_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
actual_measurments = 0;
for (uint32_t j = 1; j <= (uint32_t)recv_args->num_images; j++) {
status = hailo_stream_sync_read_all_raw_buffer(recv_args->output_stream, dst_data, 0, datasize);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_read_all_raw_buffer failed");
if ((j % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Recv [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, recv_args->tid, j, recv_args->num_images, dst_data[0], dst_data[1], dst_data[2], dst_data[3]);
recv_clock_t[recv_args->tid][lat_counter++] = ts;
actual_measurments++;
}
if (recv_args->write_log==1)
fprintf(fp, "%d Recv [%10ld.%ld s] %3d/%3d %x\n", recv_args->tid, (long)ts.tv_sec, ts.tv_nsec/1000000, j, recv_args->num_images, *dst_data);
}
if (recv_args->write_log==1)
fclose(fp);
l_exit:
free(dst_data);
recv_args->status = status;
return NULL;
}
hailo_status infer(
hailo_input_stream input_stream, hailo_output_stream *output_streams, int output_stream_cnt, int num_images, int write_log,
size_t* host_output_frame_size, size_t host_input_frame_size, hailo_stream_info_t *all_streams_info, int source_fps)
{
hailo_status status = HAILO_SUCCESS;
pthread_t write_thread = 1;
recv_thread_args_t recv_args[NOF_STREAMS-1];
pthread_t recv_threads[NOF_STREAMS-1];
write_thread_args_t write_args = {
.input_stream = input_stream,
.status = HAILO_UNINITIALIZED,
.output_streams_cnt = output_stream_cnt,
.num_images = num_images,
.host_frame_size = host_input_frame_size,
.write_log = write_log,
.frame_hw_size = all_streams_info[0].hw_frame_size,
.tid = 0,
.source_fps = source_fps
};
for (int ii=0; ii<output_stream_cnt; ii++) {
recv_args[ii].output_stream = output_streams[ii];
recv_args[ii].tid = ii;
recv_args[ii].status = HAILO_UNINITIALIZED;
recv_args[ii].num_images = num_images;
recv_args[ii].write_log = write_log;
recv_args[ii].frame_hw_size = all_streams_info[ii+1].hw_frame_size;
recv_args[ii].host_frame_size = host_output_frame_size[ii];
(void) pthread_create(&recv_threads[ii], NULL, _recv_thread, &recv_args[ii]);
};
(void) pthread_create(&write_thread, NULL, _send_thread, &write_args);
pthread_join(write_thread, NULL);
if (HAILO_SUCCESS != write_args.status) {
printf("-E- write_thread failed\n");
status = HAILO_INTERNAL_FAILURE;
}
for (int ii=0; ii<output_stream_cnt; ii++) {
pthread_join(recv_threads[ii], NULL);
printf("-I- Closing Recv thread #%d: %d\n", recv_args[ii].tid, recv_args[ii].status);
if (HAILO_SUCCESS != recv_args[ii].status) {
printf("-E- Recv thread %d failed\n", recv_args[ii].tid);
status = HAILO_INTERNAL_FAILURE;
}
}
return status;
}
void print_net_banner(hailo_stream_info_t *all_stream_infos, int cnt) {
printf(BOLDCYAN);
printf("-I-----------------------------------------------\n");
for (int ii=0; ii<=cnt; ii++) {
printf("-I- %s[%d]: %s (%d, %d, %d)\n", get_direction_name(all_stream_infos[ii].direction), ii, all_stream_infos[ii].name, all_stream_infos[ii].shape.height, all_stream_infos[ii].shape.width,
all_stream_infos[ii].shape.features);
}
printf("-I-----------------------------------------------\n");
printf(RESET);
}
double get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (double)(ts.tv_nsec / 1000000.0));
return result;
}
double calc_latency(int count) {
double result = 0;
double cur_rcv;
double cur_snd;
for (int j=0; j<actual_measurments; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
result += (cur_rcv - cur_snd);
}
return result/actual_measurments;
}
void print_inference_stats(struct timespec start_time, struct timespec end_time, hailo_stream_info_t *all_stream_infos, int output_stream_cnt, int num_images, uint32_t latency_readout)
{
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
uint32_t send_frame_size = all_stream_infos[0].hw_frame_size;
uint32_t recv_frame_size = 0;
printf(BOLDGREEN);
printf("-I-----------------------------------------------\n");
printf("-I- Total time: %4.2lf sec\n", infer_time_secs);
printf("-I- Average FPS: %4.2lf\n", num_images / infer_time_secs);
if (num_images==1)
printf("-I- Average Latency: %3.2lf ms\n", calc_latency(output_stream_cnt));
printf("-I- Send data rate: %-4.2lf Mbit/s\n",
(double)(num_images) * send_frame_size * mbit_per_byte / infer_time_secs);
for (int i=1; i<=output_stream_cnt; i++) {
recv_frame_size = all_stream_infos[i].hw_frame_size;
printf("-I- Recv[%d] data rate: %-4.2lf Mbit/s\n", i,
(double)(num_images) * recv_frame_size * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
const char** get_jlf_files_form_path(const char *dir_name, uint8_t *actual_number_of_jlfs_files) {
static char jlf_files[HAILO_MAX_NUMBER_OF_JLFS][PATH_MAX];
static const char *res_jlf_files[HAILO_MAX_NUMBER_OF_JLFS];
DIR *dir = NULL;
struct dirent *entry = NULL;
uint8_t i = 0;
dir = opendir(dir_name);
if (NULL == dir) {
return NULL;
}
entry = readdir(dir);
while (NULL != entry) {
if (entry->d_name[0] != '.') {
(void)snprintf(jlf_files[i], sizeof(jlf_files[i]), "%s%s", dir_name, entry->d_name);
res_jlf_files[i] = jlf_files[i];
i++;
}
entry = readdir(dir);
}
(void) closedir(dir);
*actual_number_of_jlfs_files = i;
return res_jlf_files;
}
void set_default_eth_output_stream_params(hailo_eth_output_stream_params_t* stream) {
stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
stream->device_port = 0;
stream->host_address.sin_family = AF_INET;
stream->host_address.sin_port = 0;
stream->host_address.sin_addr.s_addr = INADDR_ANY;
// stream->is_sync_enabled = true;
memset(&stream->host_address.sin_zero, 0, sizeof(stream->host_address.sin_zero));
}
void set_default_pcie_output_stream_params(hailo_pcie_output_stream_params_t* stream) {
stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
}
hailo_status create_and_load_jlfs(hailo_device device, hailo_jlf *jlf, char* jlf_dir)
{
hailo_status status = HAILO_SUCCESS;
const char **jlf_files = NULL;
uint8_t actual_number_of_jlf_files = 0;
uint8_t jlf_buffer[96*1024];
jlf_files = get_jlf_files_form_path(jlf_dir, &actual_number_of_jlf_files);
if (NULL == jlf_files) {
printf("Failed to get jlf files from path\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_jlf_files(jlf_files, actual_number_of_jlf_files, jlf_buffer, sizeof(jlf_buffer), jlf);
REQUIRE_SUCCESS(status, l_exit, "Failed to create jlf files");
status = hailo_configure_device_from_jlf(device, *jlf, jlf_buffer, sizeof(jlf_buffer));
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to configure device from jlf");
status = HAILO_SUCCESS;
goto l_exit;
l_release_jlf:
(void) hailo_release_jlf(*jlf);
l_exit:
return status;
}
hailo_status initialize_eth_device(const char *interface_name, hailo_eth_device_info_t *eth_device_info,
hailo_device *device)
{
hailo_status status = HAILO_UNINITIALIZED;
hailo_eth_device_info_t eth_device_info1 = {0};
size_t number_of_devices = 0;
status = hailo_scan_ethernet_devices(interface_name, &eth_device_info1, 1, &number_of_devices, HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for eth_devices");
if (0 == number_of_devices) {
printf("No eth_device found on the given interface\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_ethernet_device(&eth_device_info1, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_device");
printf("DEBUG: finished initialize_eth_device\n");
status = HAILO_SUCCESS;
l_exit:
return status;
}
hailo_status initialize_pcie_device(hailo_pcie_device_info_t *pcie_device_info, hailo_device *device)
{
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
status = hailo_scan_pcie_devices(pcie_device_info, 2, &number_of_devices);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for pcie_devices");
if (0 == number_of_devices) {
printf("No pcie_device found\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_pcie_device(pcie_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create pcie_device");
status = HAILO_SUCCESS;
l_exit:
return status;
}
hailo_status create_and_activate_eth_streams(hailo_device device, hailo_jlf jlf, hailo_input_stream *input_stream,
hailo_stream_info_t *streams_info, size_t* host_input_frame_size, hailo_output_stream *output_streams,
size_t* host_output_frame_size, int* output_stream_cnt)
{
hailo_status status = HAILO_SUCCESS;
hailo_eth_input_stream_params_t eth_input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
hailo_eth_output_stream_params_t eth_output_stream_params[NOF_STREAMS];
hailo_stream_info_t all_stream_infos[NOF_STREAMS] = {};
size_t number_of_streams = 0;
status = hailo_jlf_get_all_stream_infos(jlf, all_stream_infos, sizeof(all_stream_infos), &number_of_streams);
REQUIRE_SUCCESS(status, l_exit, "Failed to get eth_stream_infos");
for (size_t i = 0; i < number_of_streams; i++) {
streams_info[i] = all_stream_infos[i];
if (HAILO_H2D_STREAM == all_stream_infos[i].direction) {
// We need the following code the change the input format in case this is an FC layer
if (all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NC ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NHW) {
eth_input_stream_params.base_params.user_buffer_format.order = all_stream_infos[i].format.order;
}
*host_input_frame_size = hailo_get_host_frame_size(&all_stream_infos[i], &eth_input_stream_params.base_params);
status = hailo_create_eth_input_stream_from_jlf_by_index(device, jlf, streams_info[i].index,
&eth_input_stream_params, input_stream);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_input_stream");
status = hailo_activate_input_stream(device, *input_stream);
REQUIRE_SUCCESS(status, l_release_streams, "Failed to activate input stream");
} else if (HAILO_D2H_STREAM == all_stream_infos[i].direction) {
set_default_eth_output_stream_params(&eth_output_stream_params[*output_stream_cnt]);
if (all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NC ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NHW ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
eth_output_stream_params[*output_stream_cnt].base_params.user_buffer_format.order = all_stream_infos[i].format.order;
}
host_output_frame_size[*output_stream_cnt] = hailo_get_host_frame_size(&streams_info[i], &eth_output_stream_params[*output_stream_cnt].base_params);
status = hailo_create_eth_output_stream_from_jlf_by_index(device, jlf, streams_info[i].index,
&eth_output_stream_params[*output_stream_cnt], &output_streams[*output_stream_cnt]);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_output_stream");
status = hailo_activate_output_stream(device, output_streams[*output_stream_cnt]);
REQUIRE_SUCCESS(status, l_release_streams, "Failed to activate output stream");
*output_stream_cnt+=1;
} else {
printf("Invalid stream direction\n");
status = HAILO_INTERNAL_FAILURE;
}
}
l_release_streams:
if (status != HAILO_SUCCESS) {
for (int ii=0;ii<*output_stream_cnt;ii++)
(void) hailo_release_output_stream(device, output_streams[ii]);
(void) hailo_release_input_stream(device, input_stream);
}
l_exit:
return status;
}
hailo_status create_and_activate_pcie_streams(hailo_device device, hailo_jlf jlf, hailo_input_stream *input_stream,
hailo_stream_info_t *streams_info, size_t* host_input_frame_size, hailo_output_stream *output_streams,
size_t* host_output_frame_size, int* output_stream_cnt)
{
hailo_status status = HAILO_SUCCESS;
hailo_pcie_input_stream_params_t pcie_input_stream_params = HAILO_PCIE_STREAM_PARAMS_DEFAULT;
hailo_pcie_output_stream_params_t pcie_output_stream_params[NOF_STREAMS];
hailo_stream_info_t all_stream_infos[NOF_STREAMS] = {};
size_t number_of_streams = 0;
status = hailo_jlf_get_all_stream_infos(jlf, all_stream_infos, sizeof(all_stream_infos), &number_of_streams);
REQUIRE_SUCCESS(status, l_exit, "Failed to get pcie_stream_infos");
for (size_t i = 0; i < number_of_streams; i++) {
streams_info[i] = all_stream_infos[i];
if (HAILO_H2D_STREAM == all_stream_infos[i].direction) {
// We need the following code the change the input format in case this is an FC layer
if (all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NC ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NHW) {
pcie_input_stream_params.base_params.user_buffer_format.order = all_stream_infos[i].format.order;
//pcie_input_stream_params.base_params.transform_mode = HAILO_STREAM_NO_TRANSFORM;
}
*host_input_frame_size = hailo_get_host_frame_size(&all_stream_infos[i], &pcie_input_stream_params.base_params);
status = hailo_create_pcie_input_stream_from_jlf_by_index(device, jlf, streams_info[i].index,
&pcie_input_stream_params, input_stream);
REQUIRE_SUCCESS(status, l_exit, "Failed to create pcie_input_stream");
status = hailo_activate_input_stream(device, *input_stream);
REQUIRE_SUCCESS(status, l_release_streams, "Failed to activate input stream");
} else if (HAILO_D2H_STREAM == all_stream_infos[i].direction) {
set_default_pcie_output_stream_params(&pcie_output_stream_params[*output_stream_cnt]);
if (all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NC ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_NHW ||
all_stream_infos[i].format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
pcie_output_stream_params[*output_stream_cnt].base_params.user_buffer_format.order = all_stream_infos[i].format.order;
}
host_output_frame_size[*output_stream_cnt] = hailo_get_host_frame_size(&streams_info[i], &pcie_output_stream_params[*output_stream_cnt].base_params);
status = hailo_create_pcie_output_stream_from_jlf_by_index(device, jlf, streams_info[i].index,
&pcie_output_stream_params[*output_stream_cnt], &output_streams[*output_stream_cnt]);
REQUIRE_SUCCESS(status, l_exit, "Failed to create pcie_output_stream");
status = hailo_activate_output_stream(device, output_streams[*output_stream_cnt]);
REQUIRE_SUCCESS(status, l_release_streams, "Failed to activate output stream");
*output_stream_cnt+=1;
} else {
printf("Invalid stream direction\n");
status = HAILO_INTERNAL_FAILURE;
}
}
l_release_streams:
if (status != HAILO_SUCCESS) {
for (int ii=0;ii<*output_stream_cnt;ii++)
(void) hailo_release_output_stream(device, output_streams[ii]);
(void) hailo_release_input_stream(device, input_stream);
}
l_exit:
return status;
}
hailo_status initiazlie_pcie_inference(hailo_device *device, hailo_input_stream *input_stream, hailo_stream_info_t *streams_info,
hailo_output_stream *output_streams, size_t *host_input_frame_size,
size_t *host_output_frame_size, char* jlf_dir, int* output_stream_cnt)
{
hailo_pcie_device_info_t pcie_device_info[2];// = {0};
hailo_jlf jlf = NULL;
hailo_status status = HAILO_UNINITIALIZED;
status = initialize_pcie_device(pcie_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to initialize pcie_device");
status = create_and_load_jlfs(*device, &jlf, jlf_dir);
REQUIRE_SUCCESS(status, l_exit, "Failed to create and load jlfs");
status = create_and_activate_pcie_streams(*device, jlf, input_stream, streams_info,
host_input_frame_size, output_streams, host_output_frame_size, output_stream_cnt);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to create and activate pcie_streams");
status = HAILO_SUCCESS;
goto l_exit;
l_release_jlf:
(void) hailo_release_jlf(jlf);
l_exit:
return status;
}
hailo_status initizlie_eth_inference(const char* interface_name, hailo_device *device, hailo_input_stream *input_stream, hailo_stream_info_t *streams_info,
hailo_output_stream *output_streams, size_t *host_input_frame_size,
size_t *host_output_frame_size, char* jlf_dir, int* output_stream_cnt)
{
hailo_jlf jlf = NULL;
hailo_status status = HAILO_UNINITIALIZED;
hailo_eth_device_info_t *eth_device_info = {0};
hailo_eth_input_stream_params_t eth_input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
hailo_eth_output_stream_params_t eth_output_stream_params = HAILO_ETH_OUTPUT_STREAM_PARAMS_DEFAULT;
status = initialize_eth_device(interface_name, eth_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to initialize eth_device");
status = create_and_load_jlfs(*device, &jlf, jlf_dir);
REQUIRE_SUCCESS(status, l_exit, "Failed to create and load jlfs");
status = create_and_activate_eth_streams(*device, jlf, input_stream, streams_info,
host_input_frame_size, output_streams, host_output_frame_size, output_stream_cnt);
REQUIRE_SUCCESS(status, l_release_jlf, "Failed to create and activate eth_streams");
//*host_input_frame_size = hailo_get_host_frame_size(input_stream_info, &eth_input_stream_params.base_params);
//*host_output_frame_size = hailo_get_host_frame_size(output_stream_info, &eth_output_stream_params.base_params);
status = HAILO_SUCCESS;
goto l_exit;
l_release_jlf:
(void) hailo_release_jlf(jlf);
l_exit:
return status;
}
int main(int argc, char **argv)
{
hailo_status status = HAILO_UNINITIALIZED;
hailo_device device = NULL;
hailo_input_stream input_stream = NULL;
hailo_output_stream output_streams[NOF_STREAMS];
// hailo_eth_input_stream_params_t input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
// hailo_eth_output_stream_params_t output_streams_params[NOF_STREAMS-1];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
// hailo_stream_info_t output_streams_info[NOF_STREAMS-1];
size_t host_input_frame_size = 0;
size_t host_output_frame_size[NOF_STREAMS];
struct timespec start_time = {0};
struct timespec end_time = {0};
size_t number_of_streams = 0;
uint8_t input_fifo_index = 0;
int output_stream_cnt = 0;
uint8_t output_fifo_indexes[NOF_STREAMS-1];
char *jlf_dir = "./JLFs/";
int opt;
char *iface = "pcie";
int num_img = 100;
int debug = 0;
int write_log = 0;
int source_fps = 0;
uint32_t latency_readout = 0;
while ((opt = getopt(argc, argv, "f:i:j:n:dl")) != -1) {
switch (opt) {
case 'j': jlf_dir = optarg; break;
case 'i': iface = optarg; break;
case 'n': num_img = atoi(optarg); break;
case 'f': source_fps = atoi(optarg); break;
case 'l': write_log = 1; break;
case '?': fprintf (stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -j JLF-DIR [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -i INTERFACE The Interface, defaults to \'eno2\', can be also \'pcie\'\n");
fprintf(stderr, " -j JLF-DIR The JLFs directory, defaults to \'./JLFs/\'\n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -f FPS Emulate source FPS, defaults to infinity\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
exit(EXIT_FAILURE);
}
}
printf(BOLDCYAN);
printf("-I- Running on interface: %s %d images\n", iface, num_img);
printf("-I- Reading JLFs from: %s\n", jlf_dir);
printf(RESET);
if (strncmp("pcie", iface, 4) == 0) {
status = initiazlie_pcie_inference(&device, &input_stream, all_stream_infos, output_streams, &host_input_frame_size,
host_output_frame_size, jlf_dir, &output_stream_cnt);
} else {
status = initizlie_eth_inference(iface, &device, &input_stream, all_stream_infos, output_streams, &host_input_frame_size,
host_output_frame_size, jlf_dir, &output_stream_cnt);
}
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for PCIe devices");
print_net_banner(all_stream_infos, output_stream_cnt);
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
status = infer(input_stream, output_streams, output_stream_cnt, num_img, write_log, host_output_frame_size, host_input_frame_size, all_stream_infos, source_fps);
#ifdef FW_LAT
status = hailo_latency_measurement_read(device, &latency_readout);
#endif
REQUIRE_SUCCESS(status, l_release_output_stream, "Inference failure");
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
print_inference_stats(start_time, end_time, all_stream_infos, output_stream_cnt, num_img, latency_readout);
status = HAILO_SUCCESS;
l_release_output_stream:
for (int i=0;i<output_stream_cnt;i++)
(void) hailo_release_output_stream(device, output_streams[i]);
l_release_input_stream:
(void) hailo_release_input_stream(device, input_stream);
l_release_device:
(void) hailo_release_device(device);
l_exit:
printf(MAGENTA);
printf("-I- Finished gracefully\n");
printf(RESET);
return status;
}
#include <hailo/hailort.h>
#define FREE(var) \
do \
{ \
if (NULL != (var)) \
{ \
free(var); \
var = NULL; \
} \
} while (0)
#define REQUIRE_SUCCESS(status, label, msg) \
do \
{ \
if (HAILO_SUCCESS != (status)) \
{ \
printf(BOLDRED); \
printf("-E- %s : (%d)\n",msg, status); \
printf(RESET); \
goto label; \
} \
} while (0)
typedef struct write_thread_args_t
{
hailo_stream_info_t *input_stream_info;
hailo_input_stream input_stream;
hailo_status status;
int output_streams_cnt;
unsigned int num_images;
size_t host_frame_size;
} write_thread_args_t;
typedef struct recv_thread_args_t
{
hailo_stream_info_t *output_stream_info;
hailo_output_stream output_stream;
hailo_status status;
int tid;
unsigned int num_images;
int num_streams;
int write_log;
size_t host_frame_size;
} recv_thread_args_t;
typedef struct video_thread_args_t
{
hailo_stream_info_t *input_stream_info;
const char *video_path;
int num_images;
} video_thread_args_t;
#define RESET "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
\ No newline at end of file
cmake_minimum_required(VERSION 3.0.0)
# Setting the ARCH if not provided
if (NOT DEFINED ARCH)
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch_from_cmd)
string(STRIP ${arch_from_cmd} arch_from_cmd)
set(ARCH ${arch_from_cmd})
endif()
set(HAILORT_ROOT $ENV{HAILORT_ROOT})
set(HAILORT_VER $ENV{HAILORT_VER})
set(HAILORT_LIB ${HAILORT_ROOT}/../lib/linux.${ARCH}.release/libhailort.so.${HAILORT_VER})
set(HAILORT_LIB ${HAILORT_ROOT}/lib/${ARCH}/libhailort.so.${HAILORT_VER})
set(HAILORT_INCLUDE_DIR ${HAILORT_ROOT}/include)
message(STATUS ${HAILORT_LIB})
message(STATUS ${HAILORT_INCLUDE_DIR})
set(COMPILE_OPTIONS -Wall -g -O0)
find_package(Threads)
foreach(target example-hef)
add_executable(${target}.${HAILORT_VER} "${target}.c")
include_directories(${HAILORT_INCLUDE_DIR})
target_compile_options(${target}.${HAILORT_VER} PRIVATE ${COMPILE_OPTIONS})
target_link_libraries(${target}.${HAILORT_VER} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${target}.${HAILORT_VER} ${HAILORT_LIB})
endforeach(target)
To Compile all targets to all architectures (x86, armv7l, aarch64):
`build.sh`
\ No newline at end of file
#!/bin/bash
declare -A COMPILER=( [x86_64]=/usr/bin/gcc
[aarch64]=/usr/bin/aarch64-linux-gnu-gcc
[armv7l]=/usr/bin/arm-linux-gnueabi-gcc )
HAILORT_ROOT=/home/nadave/SDK/platform-sw/hailort
HAILORT_ROOT=/home/nadave/Platform/2.6.0/platform/hailort
HAILORT_ROOT=/home/nadave/SDK/3.6.0/platform/hailort
for ARCH in x86_64 aarch64
do
echo "-I- Building ${ARCH}"
mkdir -p build/${ARCH}
HAILORT_VER=2.6.0 HAILORT_ROOT=${HAILORT_ROOT} cmake -H. -Bbuild/${ARCH} -DARCH=${ARCH} -DCMAKE_C_COMPILER=${COMPILER[${ARCH}]}
cmake --build build/${ARCH}
done
if [[ -f "hailort.log" ]]; then
rm hailort.log
fi
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file example.c
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include <net/if.h>
#include <pthread.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <linux/limits.h>
#include <time.h>
#include <hailo/hailort.h>
#include "example_utils.h"
#define NOF_STREAMS (15)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
#define DEFAULT_POWER_MEASUREMENT_DELAY_MS (1100 / 1000.0 * 256 * 2 * 1.2)
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
unsigned int actual_measurments;
void* _send_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
uint32_t input_size = write_args->frame_hw_size;
uint8_t* src_data = (uint8_t*)malloc(input_size);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
struct timespec ts;
float delay = 0.0;
printf("-I- Send Thread stated TX frame size:%d\n", input_size);
if (NULL == src_data) {
printf("-E- Failed to allocate buffers\n");
status = HAILO_OUT_OF_HOST_MEMORY;
goto l_release_buffers;
}
for(size_t i = 0; i < input_size; i++) {
src_data[i] = (uint8_t)(rand() % 256);
}
flag_100 = (uint32_t)write_args->num_images / 10;
if (flag_100==0)
flag_100 = 1;
if (write_args->source_fps > 0) {
delay = 1000000.0 / write_args->source_fps;
printf(CYAN);
printf("-I- Setting the delay to %f usec\n", delay);
printf(RESET);
}
for (uint32_t i = 1; i <= (uint32_t)write_args->num_images; i++) {
if (delay > 0.0)
usleep(delay);
if ((i % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] Send frame [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, i, write_args->num_images, src_data[0], src_data[1], src_data[2], src_data[3]);
sent_clock_t[lat_counter++] = ts;
}
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream, src_data, 0, input_size);
if (status != HAILO_SUCCESS) {
printf("-E- hailo_stream_sync_write_all_raw_buffer failed: %d\n",status);
break;
}
}
l_release_buffers:
FREE(src_data);
write_args->status = status;
return NULL;
}
double get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (double)(ts.tv_nsec / 1000000.0));
return result;
}
void* _recv_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
recv_thread_args_t *recv_args = (recv_thread_args_t *)args;
uint32_t datasize = recv_args->frame_hw_size;
struct timespec ts;
uint8_t *dst_data = (uint8_t*)malloc(datasize);
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
printf("-I- Recv thread %d started, datasize: %d\n", recv_args->tid, datasize);
flag_100 = (uint32_t)recv_args->num_images / 10;
if (flag_100==0)
flag_100 = 1;
actual_measurments = 0;
for (uint32_t j = 1; j <= (uint32_t)recv_args->num_images; j++) {
status = hailo_stream_sync_read_all_raw_buffer(recv_args->output_stream, dst_data, 0, datasize);
REQUIRE_SUCCESS(status, l_exit, "hailo_stream_sync_read_all_raw_buffer failed");
if ((j % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Recv [%3d/%3d] 0x%x%x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, recv_args->tid, j, recv_args->num_images, dst_data[0], dst_data[1], dst_data[2], dst_data[3]);
recv_clock_t[recv_args->tid][lat_counter++] = ts;
actual_measurments++;
}
}
l_exit:
FREE(dst_data);
recv_args->status = status;
return NULL;
}
hailo_status infer(
hailo_input_stream input_stream, hailo_output_stream *output_streams, hailo_stream_info_t *all_strems_info,
int output_stream_cnt, int num_images, int write_log, size_t* host_output_frame_size, size_t host_input_frame_size, int source_fps)
{
hailo_status status = HAILO_SUCCESS;
pthread_t write_thread = 1;
recv_thread_args_t recv_args[NOF_STREAMS-1];
pthread_t recv_threads[NOF_STREAMS-1];
// struct timespec st, et;
// uint8_t* src_data = (uint8_t*)malloc(all_strems_info[0].hw_frame_size);
// uint8_t* dst_data = (uint8_t*)malloc(all_strems_info[1].hw_frame_size);
write_thread_args_t write_args = {
.input_stream = input_stream,
.status = HAILO_UNINITIALIZED,
.output_streams_cnt = output_stream_cnt,
.num_images = num_images,
.host_frame_size = host_input_frame_size,
.frame_hw_size = all_strems_info[0].hw_frame_size,
.source_fps = source_fps
};
for (int ii=0; ii<output_stream_cnt; ii++) {
recv_args[ii].output_stream = output_streams[ii];
recv_args[ii].tid = ii;
recv_args[ii].status = HAILO_UNINITIALIZED;
recv_args[ii].num_images = num_images;
recv_args[ii].write_log = write_log;
recv_args[ii].host_frame_size = host_output_frame_size[ii];
recv_args[ii].frame_hw_size = all_strems_info[ii+1].hw_frame_size;
(void) pthread_create(&recv_threads[ii], NULL, _recv_thread, &recv_args[ii]);
};
(void) pthread_create(&write_thread, NULL, _send_thread, &write_args);
pthread_join(write_thread, NULL);
if (HAILO_SUCCESS != write_args.status) {
printf("-E- write_thread failed\n");
status = HAILO_INTERNAL_FAILURE;
}
for (int ii=0; ii<output_stream_cnt; ii++) {
pthread_join(recv_threads[ii], NULL);
printf("-I- Closing Recv thread #%d: %d\n", recv_args[ii].tid, recv_args[ii].status);
if (HAILO_SUCCESS != recv_args[ii].status) {
printf("-E- Recv thread %d failed\n", recv_args[ii].tid);
status = HAILO_INTERNAL_FAILURE;
}
}
// for (uint32_t i = 1; i <= (uint32_t)num_images; i++) {
// clock_gettime(CLOCK_REALTIME, &st);
// status = hailo_stream_sync_write_all_raw_buffer(input_stream, src_data, 0, all_strems_info[0].hw_frame_size);
// status = hailo_stream_sync_read_all_raw_buffer(output_streams[0], dst_data, 0, all_strems_info[1].hw_frame_size);
// clock_gettime(CLOCK_REALTIME, &et);
// printf("-I- [%f ms] Infer [%3d/%3d]\n", get_time_from_ts(et)-get_time_from_ts(st), i, num_images);
// }
// FREE(src_data);
// FREE(dst_data);
return status;
}
void print_net_banner(hailo_input_stream_params_by_name_t* inputs, hailo_output_stream_params_by_name_t* outputs, size_t in_cnt, size_t out_cnt)
{
printf(MAGENTA);
printf("-I-----------------------------------------------------------\n");
printf("-I- Dir Name Transform Type Flags Order\n");
printf("-I-----------------------------------------------------------\n");
for (int i=0; i<in_cnt; i++) {
printf("-I- IN: %-20.20s: %-9.9s %-7.7s %-5.5s %-4.4s\n",
inputs[i].name,
get_transform_string(inputs[i].params.pcie_params.base_params.transform_mode),
get_type_string(inputs[i].params.pcie_params.base_params.user_buffer_format.type),
get_flags_string(inputs[i].params.pcie_params.base_params.user_buffer_format.flags),
get_order_string(inputs[i].params.pcie_params.base_params.user_buffer_format.order));
}
printf("-I-----------------------------------------------------------\n");
for (int i=0; i<out_cnt; i++) {
printf("-I- OUT:%-20.20s: %-9.9s %-7.7s %-5.5s %-4.4s\n",
outputs[i].name,
get_transform_string(outputs[i].params.pcie_params.base_params.transform_mode),
get_type_string(outputs[i].params.pcie_params.base_params.user_buffer_format.type),
get_flags_string(outputs[i].params.pcie_params.base_params.user_buffer_format.flags),
get_order_string(outputs[i].params.pcie_params.base_params.user_buffer_format.order));
}
printf("-I-----------------------------------------------------------\n");
printf(RESET);
}
double calc_latency(int count, double precentile, int write_log) {
double cur_rcv;
double cur_snd;
double latencies[actual_measurments];
for (int j=0; j<actual_measurments; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
latencies[j] = (cur_rcv - cur_snd);
}
if ((precentile<0) || (precentile>1)) {
precentile = 0.5;
}
if (write_log>0) {
FILE *fp = fopen("latency_redouts.txt", "w");
for (int ii=0; ii<actual_measurments; ii++) {
fprintf(fp, "%f\n",latencies[ii]);
}
fclose(fp);
}
return latencies[(int)(precentile * actual_measurments)];
}
void print_inference_stats(struct timespec start_time, struct timespec end_time, hailo_stream_info_t *all_stream_infos, int output_stream_cnt,
int num_images, uint32_t latency_readout, int write_log, hailo_latency_measurement_result_t driver_lat)
{
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
uint32_t send_frame_size = all_stream_infos[0].hw_frame_size;
uint32_t recv_frame_size = 0;
printf(BOLDGREEN);
printf("-I-----------------------------------------------\n");
printf("-I- Total time: %4.2lf sec\n", infer_time_secs);
printf("-I- Average FPS: %4.2lf\n", num_images / infer_time_secs);
printf("-I- 95p Latency: %3.2lf ms\n", calc_latency(output_stream_cnt, 0.95, write_log));
printf("-I- Driver Latency: %3.2lf ms\n", driver_lat.avg_hw_latency_ms);
// if (num_images==1)
// printf("-I- Average Latency: %3.2lf ms\n", calc_latency(output_stream_cnt));
printf("-I- Send data rate: %-4.2lf Mbit/s\n",
(double)(num_images) * send_frame_size * mbit_per_byte / infer_time_secs);
for (int i=1; i<=output_stream_cnt; i++) {
recv_frame_size = all_stream_infos[i].hw_frame_size;
printf("-I- Recv[%d] data rate: %-4.2lf Mbit/s\n", i,
(double)(num_images) * recv_frame_size * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
void set_default_eth_output_stream_params(hailo_eth_output_stream_params_t* stream) {
stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
stream->device_port = 0;
stream->host_address.sin_family = AF_INET;
stream->host_address.sin_port = 0;
stream->host_address.sin_addr.s_addr = INADDR_ANY;
stream->base_params.buffers_threshold = 1;
// stream->is_sync_enabled = true;
memset(&stream->host_address.sin_zero, 0, sizeof(stream->host_address.sin_zero));
}
void set_default_pcie_output_stream_params(hailo_pcie_output_stream_params_t* stream) {
stream->base_params.transform_mode = HAILO_STREAM_TRANSFORM_COPY;
stream->base_params.user_buffer_format.order = HAILO_FORMAT_ORDER_NHWC;
stream->base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
stream->base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_UINT8;
}
hailo_status create_and_load_hef(hailo_device device, hailo_hef *hef, char* hef_file, hailo_network_group *network_group)
{
hailo_status status = HAILO_SUCCESS;
size_t number_of_network_groups = 1;
status = hailo_create_hef_file(hef, hef_file);
REQUIRE_SUCCESS(status, l_exit, "Failed to create hef file");
printf(MAGENTA);
printf("-I- Loading HEF file from %s\n", hef_file);
printf(RESET);
status = hailo_configure_device_from_hef(device, *hef, network_group, &number_of_network_groups);
REQUIRE_SUCCESS(status, l_exit, "Failed to configure device from hef");
if (number_of_network_groups > 1) {
status = HAILO_UNINITIALIZED;
printf("-E- Got network_group=%ld", number_of_network_groups);
REQUIRE_SUCCESS(status, l_exit, "Failed to extract network group, larger than 1");
}
l_exit:
return status;
}
hailo_status activate_network_group(hailo_hef *hef, hailo_stream_info_t *streams_info, hailo_network_group network_group, hailo_activated_network_group *active_net_g, hailo_input_stream_params_by_name_t *input_stream_params, hailo_output_stream_params_by_name_t *output_stream_param, size_t *output_stream_cnt)
{
hailo_status status = HAILO_SUCCESS;
hailo_network_group_params_t network_group_params = {0};//HAILO_NETWORK_GROUP_PARAMS_DEFAULT;
size_t out_param_size = NOF_STREAMS-1;
size_t in_param_size = 1;
size_t number_of_streams;
hailo_stream_transform_mode_t transform_mode = HAILO_STREAM_NO_TRANSFORM;// HAILO_STREAM_NO_TRANSFORM
status = hailo_hef_get_all_stream_infos(hef, NULL, streams_info, sizeof(*streams_info), &number_of_streams);
status = hailo_make_input_stream_params(network_group, transform_mode, true, HAILO_FORMAT_TYPE_UINT8, input_stream_params, &in_param_size);
REQUIRE_SUCCESS(status, l_exit, "Failed to create input_params");
status = hailo_make_output_stream_params(network_group, transform_mode, true, HAILO_FORMAT_TYPE_UINT8, output_stream_param, &out_param_size);
*output_stream_cnt = out_param_size;
REQUIRE_SUCCESS(status, l_exit, "Failed to create output_params");
if (output_stream_param->params.pcie_params.base_params.user_buffer_format.order != HAILO_FORMAT_ORDER_HAILO_NMS)
network_group_params.latency = HAILO_LATENCY_MEASURE;
network_group_params.context_switch_batch_size = 1;
output_stream_param->params.eth_params.base_params.buffers_threshold = 1;
input_stream_params->params.eth_params.base_params.buffers_threshold = 1;
// input_stream_params->params.pcie_params.base_params.user_buffer_format.flags = streams_info[0].format.flags;
// input_stream_params->params.pcie_params.base_params.user_buffer_format.flags |= HAILO_FORMAT_FLAGS_TRANSPOSED;
print_net_banner(input_stream_params, output_stream_param, in_param_size, out_param_size);
status = hailo_activate_network_group(network_group,
&network_group_params,
input_stream_params, // Input params
in_param_size, // number of inputs
output_stream_param, // Output params
out_param_size, // number of ouputs
active_net_g);
REQUIRE_SUCCESS(status, l_exit, "Failed to activate network group");
l_exit:
return status;
}
hailo_status initialize_eth_device(const char *interface_name, hailo_device *device)
{
hailo_status status = HAILO_SUCCESS;
hailo_eth_device_info_t eth_device_info = {0};
size_t number_of_devices = 0;
status = hailo_scan_ethernet_devices(interface_name, &eth_device_info, 1, &number_of_devices, HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for eth_devices");
if (0 == number_of_devices) {
printf("No eth_device found on the given interface\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_ethernet_device(&eth_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_device");
l_exit:
return status;
}
hailo_status initialize_pcie_device(hailo_pcie_device_info_t *pcie_device_info, hailo_device *device)
{
hailo_status status = HAILO_UNINITIALIZED;
size_t number_of_devices = 0;
status = hailo_scan_pcie_devices(pcie_device_info, 2, &number_of_devices);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan for pcie_devices");
if (0 == number_of_devices) {
printf("No pcie_device found\n");
status = HAILO_INTERNAL_FAILURE;
goto l_exit;
}
status = hailo_create_pcie_device(pcie_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create pcie_device");
status = HAILO_SUCCESS;
l_exit:
return status;
}
hailo_status initiazlie_inference(hailo_device *device, hailo_input_stream *input_stream, hailo_stream_info_t *streams_info,
hailo_output_stream *output_streams, size_t *host_input_frame_size, size_t *host_output_frame_size, char* hef_path, size_t* output_stream_cnt,
hailo_activated_network_group *active_net_g, const char *interface)
{
// NADAV: Added two devices to support multiple M.2 connected to the machine
hailo_pcie_device_info_t pcie_device_info[2];
hailo_hef hef = NULL;
hailo_status status = HAILO_SUCCESS;
hailo_network_group network_groups = NULL;
hailo_input_stream_params_by_name_t input_stream_params = {0};
hailo_output_stream_params_by_name_t output_stream_params[NOF_STREAMS];
if (strncmp("pcie", interface, 4) == 0) {
status = initialize_pcie_device(pcie_device_info, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to initialize PCIe device");
} else {
status = initialize_eth_device(interface, device);
REQUIRE_SUCCESS(status, l_exit, "Failed to initialize Eth device");
}
status = create_and_load_hef(*device, &hef, hef_path, &network_groups);
REQUIRE_SUCCESS(status, l_exit, "Failed to create and load HEF");
status = activate_network_group(hef, streams_info, network_groups, active_net_g, &input_stream_params, output_stream_params, output_stream_cnt);
REQUIRE_SUCCESS(status, l_release_hef, "Failed to activate network group and streams");
REQUIRE_SUCCESS(status, l_release_hef, "Failed to create and activate pcie_streams");
status = hailo_get_input_stream_by_name(*active_net_g, streams_info[0].name, input_stream);
REQUIRE_SUCCESS(status, l_release_hef, "Failed getting stream info for input");
*host_input_frame_size = hailo_get_input_stream_frame_size(*input_stream);
for (size_t i = 0; i < *output_stream_cnt; i++) {
status = hailo_get_output_stream_by_name(*active_net_g, streams_info[i+1].name, &output_streams[i]);
REQUIRE_SUCCESS(status, l_release_hef, "Failed getting stream info for output");
host_output_frame_size[i] = hailo_get_output_stream_frame_size(output_streams[i]);
}
l_release_hef:
(void) hailo_release_hef(hef);
// if (status != HAILO_SUCCESS) {
// for (int ii=0;ii<*output_stream_cnt;ii++)
// (void) hailo_release_output_stream(device, output_streams[ii]);
// (void) hailo_release_input_stream(device, input_stream);
// }
l_exit:
return status;
}
int main(int argc, char **argv)
{
hailo_status status = HAILO_SUCCESS;
hailo_device device = NULL;
hailo_input_stream input_stream = NULL;
hailo_output_stream output_streams[NOF_STREAMS];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
size_t host_input_frame_size = 0;
size_t host_output_frame_size[NOF_STREAMS];
struct timespec start_time = {0};
struct timespec end_time = {0};
size_t output_stream_cnt = 0;
char *config = "./JLFs/";
int opt;
char *iface = "pcie";
int num_img = 100;
int write_log = 0;
int source_fps = 0;
// Power Measurement Parameters
hailo_dvm_options_t dvm_option = HAILO_DVM_OPTIONS_OVERCURRENT_PROTECTION;
enum hailo_power_measurement_types_e measurement_type = HAILO_POWER_MEASUREMENT_TYPES__POWER;
int measure_power = 0;
hailo_activated_network_group activated_network_group = NULL;
hailo_latency_measurement_result_t driver_result = {0};
uint32_t latency_readout = 0;
hailo_power_measurement_data_t measurement_data;
while ((opt = getopt(argc, argv, "f:i:c:n:pl")) != -1) {
switch (opt) {
case 'c': config = optarg; break;
case 'i': iface = optarg; break;
case 'n': num_img = atoi(optarg); break;
case 'f': source_fps = atoi(optarg); break;
case 'l': write_log = 1; break;
case 'p': measure_power = 1; break;
case '?': fprintf (stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -c HEF [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -i INTERFACE The Interface, defaults to \'pcie\', can be also an Ethernet port name\n");
fprintf(stderr, " -c HEF FILE The HEF config file \n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -f FPS Emulate the source FPS (defaults to inf.)\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
fprintf(stderr, " -p Enable Power Measurement\n");
exit(EXIT_FAILURE);
}
}
printf(BOLDCYAN);
printf("-I- Running on interface: %s for %d images\n", iface, num_img);
printf(RESET);
status = initiazlie_inference(&device, &input_stream, all_stream_infos, output_streams, &host_input_frame_size,
host_output_frame_size, config, &output_stream_cnt, &activated_network_group, iface);
REQUIRE_SUCCESS(status, l_release_device, "Failed to initialize inference");
if (measure_power==1) {
status = hailo_stop_power_measurement(device);
status = hailo_set_power_measurement(device, 0, dvm_option, measurement_type);
status = hailo_start_power_measurement(device, DEFAULT_POWER_MEASUREMENT_DELAY_MS, HAILO_DEFAULT_INIT_AVERAGING_FACTOR, HAILO_DEFAULT_INIT_SAMPLING_PERIOD_US);
}
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
status = infer(input_stream, output_streams, all_stream_infos, output_stream_cnt, num_img, write_log, host_output_frame_size, host_input_frame_size, source_fps);
REQUIRE_SUCCESS(status, l_release_output_stream, "Inference failure");
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
if (measure_power==1) {
status = hailo_stop_power_measurement(device);
status = hailo_get_power_measurement(device, 0, true, &measurement_data);
printf(BOLDBLUE);
printf("-I-----------------------------------------------\n");
if (measurement_data.total_number_of_samples==0) {
printf("-W- The test was too short to measure power\n");
} else {
printf("-I- Total samples: %d ", measurement_data.total_number_of_samples);
// The ability to measure Power/Current varies with respect to the board that we've using. The below setup
// is good for M.2. We measure the CURRENT, and multiple by 0.8V to get the power.
printf(" [%.3f, %.3f, %.3f] W\n", measurement_data.min_value, measurement_data.average_value, measurement_data.max_value);
printf("-I- Average time per sample (ms): %.3f\n", measurement_data.average_time_value_milliseconds);
}
printf(RESET);
}
// Getting the latency from the driver
status = hailo_get_latency_measurement(activated_network_group, &driver_result);
print_inference_stats(start_time, end_time, all_stream_infos, output_stream_cnt, num_img, latency_readout, write_log, driver_result);
l_release_output_stream:
// for (int i=0;i<output_stream_cnt;i++)
// (void) hailo_release_output_stream(device, output_streams[i]);
// (void) hailo_release_input_stream(device, input_stream);
l_release_device:
// (void) hailo_deactivate_network_group(activated_network_group);
if (device != NULL)
(void) hailo_release_device(device);
printf(MAGENTA);
printf("-I- Finished gracefully\n");
printf(RESET);
return status;
}
#include <hailo/hailort.h>
#define FREE(var) \
do \
{ \
if (NULL != (var)) \
{ \
free(var); \
var = NULL; \
} \
} while (0)
#define REQUIRE_SUCCESS(status, label, msg) \
do \
{ \
if (HAILO_SUCCESS != (status)) \
{ \
printf(BOLDRED); \
printf("-E- %s : (%d)\n",msg, status); \
printf(RESET); \
goto label; \
} \
} while (0)
typedef struct write_thread_args_t
{
hailo_stream_info_t *input_stream_info;
hailo_input_stream input_stream;
hailo_status status;
int output_streams_cnt;
unsigned int num_images;
size_t host_frame_size;
size_t frame_hw_size;
int write_log;
int tid;
int source_fps;
} write_thread_args_t;
typedef struct recv_thread_args_t
{
hailo_stream_info_t *output_stream_info;
hailo_output_stream output_stream;
hailo_status status;
int tid;
unsigned int num_images;
int num_streams;
int write_log;
size_t host_frame_size;
size_t frame_hw_size;
} recv_thread_args_t;
typedef struct video_thread_args_t
{
hailo_stream_info_t *input_stream_info;
const char *video_path;
int num_images;
} video_thread_args_t;
const char* get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
const char *get_transform_string(hailo_stream_transform_mode_t transform)
{
switch(transform) {
case HAILO_STREAM_NO_TRANSFORM: return "NO";
case HAILO_STREAM_TRANSFORM_COPY: return "COPY";
case HAILO_STREAM_TRANSFORM_INPLACE: return "IN_PLACE";
case HAILO_STREAM_MAX_ENUM:
default: return "Wrong";
}
}
const char *get_flags_string(int flags)
{
switch(flags) {
case 0: return "NONE";
case 1: return "QUANT";
case 2: return "TRANS";
case 3: return "QT+TR";
default: return "UNKNOWN";
}
}
const char *get_type_string(int type)
{
switch(type) {
case 0: return "AUTO";
case 1: return "UINT8";
case 2: return "UINT16";
case 3: return "FLOAT32";
default: return "UNKNOWN";
}
}
const char *get_order_string(int order)
{
switch(order) {
case 0: return "NHWC";
case 1: return "NHCW";
case 2: return "FCR";
case 3: return "F8CR";
case 5: return "NC";
case 8: return "NMS";
case 10: return "NCHW";
default: return "UNKNOWN";
}
}
#define RESET "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
\ No newline at end of file
cmake_minimum_required(VERSION 3.0.0)
# CXX=/usr/bin/g++-9
# Setting the ARCH if not provided
if (NOT DEFINED ARCH)
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch_from_cmd)
string(STRIP ${arch_from_cmd} arch_from_cmd)
set(ARCH ${arch_from_cmd})
endif()
# Setting the CMAKE_C_COMPILER if not provided
if (${ARCH} STREQUAL "aarch64")
if (NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER "/usr/bin/aarch64-linux-gnu-gcc")
endif()
else()
if (NOT DEFINED CMAKE_C_COMPILER)
message(STATUS "Setting compiler to g++-9")
set(CMAKE_C_COMPILER "/usr/bin/gcc-9")
set(CMAKE_CXX_COMPILER "/usr/bin/g++-9")
endif()
endif()
message(STATUS "HAILORT_ROOT at: $ENV{HAILORT_ROOT}")
set(HAILORT_LIB $ENV{HAILORT_ROOT}/lib/${ARCH}/libhailort.so.2.2.0)
set(HAILORT_INCLUDE_DIR "$ENV{HAILORT_ROOT}/include")
set(COMPILE_OPTIONS_CPP -Werror -O3 -DNDEBUG -std=c++11)
include_directories(${HAILORT_INCLUDE_DIR} ./)
find_package(Threads)
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
foreach(target runme)
add_executable(${target} stream_and_info.cpp example_device.cpp main.cpp)
target_compile_options(${target} PRIVATE ${COMPILE_OPTIONS_CPP})
target_link_libraries(${target} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${target} ${HAILORT_LIB})
endforeach(target)
1. Dependencies:
1. OpenCV
`sudo apt-get install -y libopencv-dev`
`sudo apt-get install gcc-9`
2. Set HAILORT_ROOT environment variable, e.g.:
export HAILORT_ROOT=~/SDK/3.2.0/platform/hailort
2. First time directory preparation:
`cmake -H. -Bbuild`
3. Consecutive builds:
`cmake --build build`
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <thread>
#include <vector>
#include <fstream>
#include <memory>
#include <example_device.hpp>
#include <example_utils.hpp>
#include <stream_and_info.hpp>
#include <hailo/hailort.h>
using namespace std;
example_device::example_device(std::string& iface, std::string& jlf_path, unsigned int num_imgs, int write_log, int debug) {
cout << BOLDCYAN
<< "-I- Running on interface: " << iface << " " << num_imgs << " images" << endl
<< "-I- Reading JLFs from: " << jlf_path << endl
<< RESET;
example_device::iface = iface;
example_device::jlf_dir = jlf_path;
example_device::debug = debug;
example_device::num_imgs = num_imgs;
example_device::write_log = write_log;
example_device::output_stream_cnt = 0;
example_device::input_stream_cnt = 0;
}
example_device::~example_device() {}
template<class T>
hailo_status example_device::activate_output_stream(hailo_stream_info_t& info) {
hailo_status status = HAILO_SUCCESS;
hailo_eth_output_stream_params_t output_stream_params;
hailo_pcie_output_stream_params_t pcie_output_stream_params;
std::vector<hailo_stream_info_t> mux_stream_info(MAX_OUTPUT_MUX_INFO_CAPACITY);
size_t output_mux_info_size = 0;
hailo_output_stream output_stream;
output_stream_params = HAILO_ETH_OUTPUT_STREAM_PARAMS_DEFAULT;
pcie_output_stream_params = HAILO_PCIE_STREAM_PARAMS_DEFAULT;
if (info.format.order == HAILO_FORMAT_ORDER_NC ||
info.format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
output_stream_params.base_params.user_buffer_format.order = info.format.order;
pcie_output_stream_params.base_params.user_buffer_format.order = info.format.order;
}
if (typeid(T) == typeid(float32_t)) {
output_stream_params.base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_NONE;
output_stream_params.base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_FLOAT32;
pcie_output_stream_params.base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_NONE;
pcie_output_stream_params.base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_FLOAT32;
}
output_streams.resize(++example_device::output_stream_cnt);
if (iface.compare("pcie") == 0) {
status = hailo_create_pcie_output_stream_from_jlf_by_index(device, jlf, info.index, &pcie_output_stream_params, &output_stream);
} else {
status = hailo_create_eth_output_stream_from_jlf_by_index(device, jlf, info.index, &output_stream_params, &output_stream);
}
if (info.is_mux) {
status = hailo_output_stream_get_mux_infos(output_stream, mux_stream_info.data(), MAX_OUTPUT_MUX_INFO_CAPACITY, &output_mux_info_size);
output_streams[output_stream_cnt-1] = std::unique_ptr<OutputStreamMux>(new OutputStreamMux(mux_stream_info, output_mux_info_size, output_stream, info));
} else {
output_streams[output_stream_cnt-1] = std::unique_ptr<OutputStream>(new OutputStream(output_stream, info));
}
if (iface.compare("pcie") == 0) {
output_streams[output_stream_cnt-1]->SetHostFrameSize(info, pcie_output_stream_params.base_params);
} else {
output_streams[output_stream_cnt-1]->SetHostFrameSize(info, output_stream_params.base_params);
}
status = hailo_activate_output_stream(device, output_streams[output_stream_cnt-1]->GetStream());
return status;
}
template<class T>
hailo_status example_device::activate_input_stream(hailo_stream_info_t& info) {
hailo_status status = HAILO_SUCCESS;
hailo_eth_input_stream_params_t input_stream_params = HAILO_ETH_INPUT_STREAM_PARAMS_DEFAULT;
hailo_pcie_input_stream_params_t pcie_input_stream_params = HAILO_PCIE_STREAM_PARAMS_DEFAULT;
hailo_input_stream input_stream;
if (info.format.order == HAILO_FORMAT_ORDER_NC ||
info.format.order == HAILO_FORMAT_ORDER_NHW) {
input_stream_params.base_params.user_buffer_format.order = info.format.order;
}
if (typeid(T) == typeid(float32_t)) {
input_stream_params.base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_NONE;
pcie_input_stream_params.base_params.user_buffer_format.flags = HAILO_FORMAT_FLAGS_NONE;
input_stream_params.base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_FLOAT32;
pcie_input_stream_params.base_params.user_buffer_format.type = HAILO_FORMAT_TYPE_FLOAT32;
}
input_streams.resize(++input_stream_cnt);
if (iface.compare("pcie") == 0) {
status = hailo_create_pcie_input_stream_from_jlf_by_index(device, jlf, info.index, &pcie_input_stream_params, &input_stream);
} else {
status = hailo_create_eth_input_stream_from_jlf_by_index(device, jlf, info.index, &input_stream_params, &input_stream);
}
status = hailo_activate_input_stream(device, input_stream);
input_streams[input_stream_cnt-1].SetStream(input_stream);
input_streams[input_stream_cnt-1].SetStreamInfo(info);
input_streams[input_stream_cnt-1].SetHostFrameSize(info, input_stream_params.base_params);
return status;
}
void example_device::print_net_banner() {
printf(BOLDCYAN);
printf("-I-----------------------------------------------\n");
for (int ii=0; ii<output_stream_cnt+input_stream_cnt; ii++) {
printf("-I- %s[%d]: %s (%d, %d, %d)\n", get_direction_name(all_stream_infos[ii].direction), ii, all_stream_infos[ii].name, all_stream_infos[ii].shape.height, all_stream_infos[ii].shape.width,
all_stream_infos[ii].shape.features);
}
printf("-I-----------------------------------------------\n");
printf(RESET);
}
double example_device::get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (ts.tv_nsec / 1000000));
return result;
}
const char** example_device::get_jlf_files_form_path(const char *dir_name, uint8_t *actual_number_of_jlfs_files) {
static char jlf_files[HAILO_MAX_NUMBER_OF_JLFS][PATH_MAX];
static const char *res_jlf_files[HAILO_MAX_NUMBER_OF_JLFS];
DIR *dir = NULL;
struct dirent *entry = NULL;
uint8_t i = 0;
dir = opendir(dir_name);
if (NULL == dir) {
return NULL;
}
entry = readdir(dir);
while (NULL != entry) {
if (entry->d_name[0] != '.') {
(void)snprintf(jlf_files[i], sizeof(jlf_files[i]), "%s%s", dir_name, entry->d_name);
res_jlf_files[i] = jlf_files[i];
i++;
}
entry = readdir(dir);
}
(void) closedir(dir);
*actual_number_of_jlfs_files = i;
return res_jlf_files;
}
hailo_status example_device::create_eth_device() {
hailo_status status = HAILO_SUCCESS;
size_t number_of_devices = 0;
uint8_t jlf_buffer[48*1024];
uint8_t actual_number_of_jlfs_files = 0;
const char **jlf_files = NULL;
try {
status = hailo_scan_ethernet_devices(iface.c_str(), &device_info, 1, &number_of_devices, HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
if (0 == number_of_devices) {
cout << "-E- No device found on the given interface:" << iface << endl;
status = HAILO_INTERNAL_FAILURE;
}
if (status != HAILO_SUCCESS) return status;
status = hailo_create_ethernet_device(&device_info, &device);
if (status != HAILO_SUCCESS) return status;
jlf_files = get_jlf_files_form_path(jlf_dir.c_str(), &actual_number_of_jlfs_files);
if (NULL == jlf_files) {
cout << "-E- Failed to get jlf files from path:" << jlf_dir << endl;
return HAILO_INTERNAL_FAILURE;
}
jlf = NULL;
status = hailo_create_jlf_files(jlf_files, actual_number_of_jlfs_files, jlf_buffer, sizeof(jlf_buffer), &jlf);
if (status!=HAILO_SUCCESS) return status;
status = hailo_configure_device_from_jlf(device, jlf, jlf_buffer, sizeof(jlf_buffer));
} catch (std::exception const& e) {
std::cout << "-E- create device failed" << e.what() << std::endl;
return HAILO_INTERNAL_FAILURE;
}
return status;
}
hailo_status example_device::create_pcie_device() {
hailo_status status = HAILO_SUCCESS;
size_t number_of_devices = 0;
uint8_t jlf_buffer[48*1024];
uint8_t actual_number_of_jlfs_files = 0;
const char **jlf_files = NULL;
try {
status = hailo_scan_pcie_devices(&pcie_device_info, 1, &number_of_devices);
if (0 == number_of_devices) {
cout << "-E- No device found on the given interface:" << iface << endl;
status = HAILO_INTERNAL_FAILURE;
}
if (status != HAILO_SUCCESS) return status;
status = hailo_create_pcie_device(&pcie_device_info, &device);
if (status != HAILO_SUCCESS) return status;
jlf_files = get_jlf_files_form_path(jlf_dir.c_str(), &actual_number_of_jlfs_files);
if (NULL == jlf_files) {
cout << "-E- Failed to get jlf files from path:" << jlf_dir << endl;
return HAILO_INTERNAL_FAILURE;
}
jlf = NULL;
status = hailo_create_jlf_files(jlf_files, actual_number_of_jlfs_files, jlf_buffer, sizeof(jlf_buffer), &jlf);
if (status!=HAILO_SUCCESS) return status;
status = hailo_configure_device_from_jlf(device, jlf, jlf_buffer, sizeof(jlf_buffer));
} catch (std::exception const& e) {
std::cout << "-E- create device failed" << e.what() << std::endl;
return HAILO_INTERNAL_FAILURE;
}
return status;
}
hailo_status example_device::print_debug_stats() {
uint32_t address;
vector<uint8_t> data(4);
uint32_t size = 4;
hailo_status status = HAILO_SUCCESS;
// rx_jabbers
address = 0x0010918C;
status = hailo_read_memory(device, address, data.data(), size);
cout << CYAN
<< "-I-----------------------------------------------" << endl
<< "-D- RX_JABBERS: 0x" << data.data() << endl;
// fcs_errors
address = 0x00109190;
status = hailo_read_memory(device, address, data.data(), size);
cout << "-D- FCS_ERRORS: 0x" << data.data() << endl
<< "-I-----------------------------------------------" << endl
<< RESET;
return status;
}
const char* example_device::get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
double example_device::calc_latency(int count) {
double result = 0;
double cur_rcv;
double cur_snd;
for (int j=0; j<LATENCY_MEASUREMENTS; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
result += (cur_rcv - cur_snd);
}
return result/LATENCY_MEASUREMENTS;
}
void example_device::print_inference_stats() {
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
uint32_t send_frame_size = 0;
uint32_t recv_frame_size = 0;
for (int inp=0;inp<input_stream_cnt;inp++) {
send_frame_size += input_streams[inp].GetHostFrameSize();
}
cout << BOLDGREEN
<< "-I-----------------------------------------------" << endl
<< "-I- Total time: " << infer_time_secs << endl
<< "-I- Average FPS: " << (num_imgs * input_stream_cnt)/ infer_time_secs << endl
// << "-I- Average Latency: " << calc_latency(output_stream_cnt) << " ms" << endl
<< "-I- Send data rate: " << (double)(num_imgs) * send_frame_size * mbit_per_byte / infer_time_secs << " Mbit/s" << endl;
//for (int i=input_stream_cnt; i<input_stream_cnt+output_stream_cnt; i++) {
for (auto &stream: output_streams) {
recv_frame_size = stream->GetHostFrameSize();
printf("-I- Recv[%d] data rate: %-4.2lf Mbit/s\n", stream->GetStreamInfo().index,
(double)(num_imgs) * recv_frame_size * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
template<class T>
void example_device::_send_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
std::vector<T> src_data;
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
struct timespec ts;
src_data.resize(write_args->input_stream.GetHostFrameSize());
if (src_data.empty()) {
cout << "-E- Failed to allocate buffers" << endl;
status = HAILO_OUT_OF_HOST_MEMORY;
} else {
for(size_t i = 0; i < write_args->input_stream.GetHostFrameSize(); i++) {
src_data[i] = (T)(rand() % 256);
}
flag_100 = (uint32_t)write_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
for (uint32_t i = 1; i <= (uint32_t)write_args->num_images; i++) {
if ((i % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Send frame [%3d/%3d]\n", (long)ts.tv_sec, ts.tv_nsec/1000000, write_args->input_stream_info.index, i, write_args->num_images);
sent_clock_t[lat_counter++] = ts;
}
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream.GetStream(),
src_data.data(),
0,
write_args->input_stream.GetHostFrameSize());
if (status != HAILO_SUCCESS) {
cout << "-E- hailo_stream_sync_write_all_raw_buffer failed" << endl;
break;
}
}
}
write_args->status = status;
}
template<class T>
hailo_status example_device::read_data_from_device(OutputStream* output_stream) {
hailo_status status = HAILO_SUCCESS;
// Must check if this output stream is actually MUXed
if (output_stream->GetIsMux()) {
OutputStreamMux* osm = dynamic_cast<OutputStreamMux*>(output_stream);
std::vector<hailo_stream_raw_buffer_t> demux_raw_buffers;
std::vector<std::vector<T>> host_output_muxed_data(MAX_OUTPUT_MUX_INFO_CAPACITY);
osm->ConfigurDemuxRawBuffers(demux_raw_buffers, host_output_muxed_data);
status = hailo_stream_sync_read_all_mux_raw_buffer(osm->GetStream(), demux_raw_buffers.data(), osm->GetMuxInfoSize());
} else {
std::vector<T> recv_data(output_stream->GetHostFrameSize());
status = hailo_stream_sync_read_all_raw_buffer(output_stream->GetStream(), recv_data.data(), 0, output_stream->GetHostFrameSize());
}
return status;
}
template<class T>
void example_device::_recv_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
recv_thread_args_t *recv_args = (recv_thread_args_t *)args;
struct timespec ts;
ofstream outFile;
//std::vector<T> recv_array;
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
cout << "-I- Recv thread " << recv_args->tid << " started" << endl;
if (recv_args->write_log==1) {
string log_name = "rx_tid_0.log";
outFile = ofstream(log_name);
}
flag_100 = (uint32_t)recv_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
// recv_array.resize(recv_args->output_stream_info->shape_size);
for (uint32_t j = 1; j <= (uint32_t)recv_args->num_images; j++) {
status = read_data_from_device<T>(recv_args->output_stream);
//status = hailo_stream_sync_read_all_raw_buffer(recv_args->output_stream, recv_array.data(), 0, recv_args->output_stream_info->shape_size);
// if (recv_args->write_log==1) {
// for (auto &e : recv_array) outFile << e << " ";
// outFile << endl;
// }
if (status != HAILO_SUCCESS) {
cout << "-E- hailo_stream_sync_read_all_raw_buffer failed" << endl;
break;
}
if ((j % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Recv [%3d/%3d] \n", (long)ts.tv_sec, ts.tv_nsec/1000000, recv_args->tid, j, recv_args->num_images);
recv_clock_t[recv_args->tid][lat_counter++] = ts;
}
}
recv_args->status = status;
}
template<class T>
hailo_status example_device::infer() {
hailo_status status = HAILO_SUCCESS;
std::vector<std::thread> recv_threads;
std::vector<std::thread> write_threads;
std::vector<recv_thread_args_t> recv_args;
std::vector<write_thread_args_t> write_args;
write_threads.resize(input_stream_cnt);
write_args.resize(input_stream_cnt);
for (int s=0;s<input_stream_cnt;s++) {
write_args[s].input_stream_info = all_stream_infos[s];
write_args[s].input_stream = input_streams[s];
write_args[s].status = HAILO_SUCCESS;
write_args[s].output_streams_cnt = output_stream_cnt;
write_args[s].num_images = num_imgs;
write_threads[s] = std::thread(&example_device::_send_thread<T>, this, &write_args[s]);
}
recv_args.resize(output_stream_cnt);
recv_threads.resize(output_stream_cnt);
for (int s=0;s<output_stream_cnt;s++) {
recv_args[s].output_stream_info = &all_stream_infos[s+2];
recv_args[s].output_stream = output_streams[s].get();
recv_args[s].tid = s;
recv_args[s].status = HAILO_SUCCESS;
recv_args[s].num_images = num_imgs;
recv_args[s].write_log = write_log;
recv_threads[s] = std::thread(&example_device::_recv_thread<T>, this, &recv_args[s]);
}
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
for (auto& t: write_threads) t.join();
for (auto& t: recv_threads) t.join();
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
for (auto& a: write_args) {
if (HAILO_SUCCESS != a.status) {
cout << "-E- write_thread failed" << endl;
status = HAILO_INTERNAL_FAILURE;
}
}
return status;
}
template<class T>
hailo_status example_device::setup_device_for_inference() {
hailo_status status = HAILO_SUCCESS;
size_t number_of_streams;
if (iface.compare("pcie") == 0) {
status = create_pcie_device();
} else {
status = create_eth_device();
}
if (status!=HAILO_SUCCESS) return status;
status = hailo_jlf_get_all_stream_infos(example_device::jlf, example_device::all_stream_infos, NOF_STREAMS, &number_of_streams);
if (status != HAILO_SUCCESS) {
cout << "-E- Failed to get all stream info" << endl;
release_jlf();
return status;
}
for (size_t i=0;i<number_of_streams;i++) {
if (example_device::all_stream_infos[i].direction==HAILO_H2D_STREAM) {
activate_input_stream<T>(example_device::all_stream_infos[i]);
} else {
activate_output_stream<T>(example_device::all_stream_infos[i]);
}
}
if (status != HAILO_SUCCESS) {
cout << "-E- Failed to activate streams" << endl;
return status;
}
print_net_banner();
return status;
}
void example_device::release_output_streams() {
for (const auto &s: output_streams) (void) hailo_release_output_stream(device, s->GetStream());
if (example_device::debug==1) {
print_debug_stats();
}
}
void example_device::release_input_stream() {
for (const auto &s: input_streams) (void) hailo_release_input_stream(device, s.GetStream());
}
void example_device::release_jlf() {
(void) hailo_release_jlf(example_device::jlf);
}
void example_device::release_device() {
(void) hailo_release_device(example_device::device);
}
void example_device::run_inference() {
hailo_status status = HAILO_SUCCESS;
status = setup_device_for_inference<float32_t>();
if (status!=HAILO_SUCCESS) {
cout << "-E- Got Status:" << status << endl;
return;
}
status = infer<float32_t>();
example_device::print_inference_stats();
example_device::release_output_streams();
example_device::release_input_stream();
example_device::release_jlf();
example_device::release_device();
}
#ifndef _EXAMPLE_DEVICE_H_
#define _EXAMPLE_DEVICE_H_
#include <time.h>
#include <net/if.h>
#include <vector>
#include <memory>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <dirent.h>
#include <linux/limits.h>
#include <hailo/hailort.h>
#include "stream_and_info.hpp"
#define NOF_STREAMS (6)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
#define MAX_OUTPUT_MUX_INFO_CAPACITY (16)
class example_device
{
private:
hailo_eth_device_info_t device_info;
hailo_pcie_device_info_t pcie_device_info;
hailo_device device;
hailo_jlf jlf;
std::vector<InputStream> input_streams;
//std::vector<hailo_output_stream> output_streams;
std::vector<std::unique_ptr<OutputStream>> output_streams;
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
struct timespec start_time;
struct timespec end_time;
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
std::string iface;
std::string jlf_dir;
unsigned int num_imgs;
int write_log;
int debug;
hailo_status create_pcie_device();
hailo_status create_eth_device();
hailo_status print_debug_stats();
const char** get_jlf_files_form_path(const char *dir_name, uint8_t *actual_number_of_jlfs_files);
const char* get_direction_name(hailo_stream_direction_t dir);
double calc_latency(int count);
template <class T> void _recv_thread(void *args);
template <class T> void _send_thread(void *args);
template <class T> hailo_status read_data_from_device(OutputStream* output_stream);
template <class T> hailo_status infer();
void release_input_stream();
void release_jlf();
void release_device();
double get_time_from_ts(struct timespec ts);
public:
int output_stream_cnt;
int input_stream_cnt;
example_device(std::string& iface, std::string& jlf_path, unsigned int num_imgs, int write_log, int debug);
~example_device();
template <class T> hailo_status activate_output_stream(hailo_stream_info_t& info);
template <class T> hailo_status activate_input_stream(hailo_stream_info_t& info);
void print_net_banner();
void print_inference_stats();
template <class T> hailo_status setup_device_for_inference();
void release_output_streams();
void run_inference();
};
#endif
#include <queue>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/video/video.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <example_source.hpp>
#include <example_utils.h>
using namespace std;
using namespace cv;
example_source::example_source(source_kind_t _source_kind, unsigned _num_of_rand_imgs=0, string _source_path="") {
source_kind = _source_kind;
num_of_rand_imgs = _num_of_rand_imgs;
source_path = _source_path;
cout << BOLDCYAN << "-I-----------------------------------------------" << endl;
cout << "-I- Source: " << source_kind << endl;
if (source_kind != Random) {
cout << "-I- Source: " << source_path << endl;
} else {
cout << "-I- Source: #" << num_of_rand_imgs << " Random images" << endl;
}
cout << "-I-----------------------------------------------" << RESET << endl;
}
void example_source::_frame_lib_thread(void *args)
{
video_thread_args_t *v_args = (video_thread_args_t *)args;
Mat org_frame;
vector<String> file_names;
Mat pp_frame(v_args->input_stream_info->hw_shape.height, v_args->input_stream_info->hw_shape.height, CV_8UC3);
unsigned int idx = 0;
cout << BOLDCYAN << "-I-----------------------------------------------" << endl
<< "-I- [Frames-thread] Output shape (" << v_args->input_stream_info->hw_shape.height << ", " << v_args->input_stream_info->hw_shape.height << ")" << endl
<< "-I-----------------------------------------------" <<
RESET << endl;
cv::glob(v_args->video_path, file_names, false);
for (String file : file_names)
{
org_frame = imread(file);
cout << "-I- [Frames-thread] Getting frame #" << idx++ << ":" << file << endl;
if (org_frame.size() != pp_frame.size())
resize(org_frame, pp_frame, pp_frame.size());
input_image_queue_m.lock();
input_image_queue.push(pp_frame.clone());
input_image_queue_m.unlock();
}
// Mark the final frame
pp_frame.data[0] = 17;
pp_frame.data[1] = 71;
pp_frame.data[2] = 17;
pp_frame.data[3] = 71;
idx++;
input_image_queue_m.lock();
input_image_queue.push(pp_frame);
input_image_queue_m.unlock();
cout << BOLDCYAN << "-I-----------------------------------------------" << endl
<< "-I- [Frames-thread] FINISHED READING DIR - #" << idx << endl
<< "-I-----------------------------------------------"
<< RESET << endl;
}
void example_source::_video_source_thread(void *args)
{
video_thread_args_t *v_args = (video_thread_args_t *)args;
Mat org_frame;
Mat pp_frame(v_args->input_stream_info->hw_shape.height, v_args->input_stream_info->hw_shape.height, CV_8UC3);
unsigned int idx = 0;
VideoCapture cap(v_args->video_path);
if (!cap.isOpened())
{
cout << "-E- Unable to open video stream" << endl;
return;
}
Size shape = Size((int)cap.get(CV_CAP_PROP_FRAME_WIDTH), (int)cap.get(CV_CAP_PROP_FRAME_HEIGHT));
cout << BOLDCYAN << "-I-----------------------------------------------" << endl;
cout << "-I- [Video-thread] Input shape (" << shape.width << ", " << shape.height << ")" << endl;
cout << "-I- [Video-thread] Output shape (" << v_args->input_stream_info->hw_shape.height << ", " << v_args->input_stream_info->hw_shape.height << ")" << endl;
cout << "-I-----------------------------------------------" << RESET << endl;
while (true)
{
if (++idx % 500 == 0)
cout << "-I- [Video-thread] Getting frame: " << idx << endl;
cap >> org_frame;
if (org_frame.empty())
break;
resize(org_frame, pp_frame, pp_frame.size());
input_image_queue_m.lock();
input_image_queue.push(pp_frame.clone());
input_image_queue_m.unlock();
}
// Mark the final frame
pp_frame.data[0] = 17;
pp_frame.data[1] = 71;
pp_frame.data[2] = 17;
pp_frame.data[3] = 71;
idx++;
input_image_queue_m.lock();
input_image_queue.push(pp_frame);
input_image_queue_m.unlock();
cout << BOLDCYAN << "-I-----------------------------------------------" << endl;
cout << "-I- [Video-thread] FINISHED MOVIE STREAM - " << idx << endl;
cout << "-I-----------------------------------------------" << RESET << endl;
cap.release();
}
\ No newline at end of file
#ifndef _EXAMPLE_SOURCE_H_
#define _EXAMPLE_SOURCE_H_
#include <vector>
#include <queue>
#include <mutex>
#include <opencv2/opencv.hpp>
#include <opencv2/video/video.hpp>
#include <opencv2/highgui/highgui.hpp>
class example_source
{
public:
enum source_kind_t { Video, Jpg, Random };
std::queue<cv::Mat> input_image_queue;
example_source(source_kind_t _source_kind, unsigned _num_of_rand_imgs, std::string _source_path);
~example_source();
void _frame_lib_thread(void *args);
void _video_source_thread(void *args);
private:
source_kind_t source_kind;
unsigned num_of_rand_imgs;
std::string source_path;
std::mutex input_image_queue_m;
};
#endif
\ No newline at end of file
#include <hailo/hailort.h>
#include <stream_and_info.hpp>
#define FREE(var) \
do \
{ \
if (NULL != (var)) \
{ \
free(var); \
var = NULL; \
} \
} while (0)
#define REQUIRE_SUCCESS(status, label, msg) \
do \
{ \
if (HAILO_SUCCESS != (status)) \
{ \
printf(BOLDRED); \
printf("-E- %s : (%d)\n",msg, status); \
printf(RESET); \
goto label; \
} \
} while (0)
typedef struct write_thread_args_t
{
hailo_stream_info_t input_stream_info;
InputStream input_stream;
hailo_status status;
int output_streams_cnt;
unsigned int num_images;
} write_thread_args_t;
typedef struct recv_thread_args_t
{
hailo_stream_info_t *output_stream_info;
OutputStream* output_stream;
hailo_status status;
int tid;
unsigned int num_images;
int num_streams;
int write_log;
} recv_thread_args_t;
typedef struct mid_thread_args_t
{
hailo_input_stream input_stream;
hailo_stream_info_t *input_info;
hailo_output_stream output_stream;
hailo_stream_info_t *output_info;
unsigned int num_images;
} mid_thread_args_t;
typedef struct video_thread_args_t
{
hailo_stream_info_t *input_stream_info;
const char *video_path;
int num_images;
} video_thread_args_t;
#define RESET "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
\ No newline at end of file
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file main.cpp
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include "example_device.hpp"
#include <iostream>
#include <thread>
#include <functional>
void thread_wrapper(std::string &iface, std::string &jlf_dir, unsigned int &num_img)
{
example_device dev(iface, jlf_dir, num_img, 0, 0);
dev.run_inference();
}
int main(int argc, char **argv)
{
std::string jlf_dir = "./JLFs";
std::string iface = "pcie";
int opt;
unsigned int num_img = 100;
int debug = 0;
int write_log = 0;
while ((opt = getopt(argc, argv, "i:j:n:dl")) != -1)
{
switch (opt)
{
case 'j':
jlf_dir = optarg;
break;
case 'i':
iface = optarg;
break;
case 'n':
num_img = atoi(optarg);
break;
case 'd':
debug = 1;
break;
case 'l':
write_log = 1;
break;
case '?':
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -j JLF-DIR [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -i INTERFACE The device interface, defaults to \'pcie\', if using Ethernet name the Host port\n");
fprintf(stderr, " -j JLF-DIR The JLFs directory, defaults to \'./JLFs/\'\n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -d Read and print debug registers from FW\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
exit(EXIT_FAILURE);
}
}
try
{
std::cout << "-I- TEST STARTS" << std::endl;
std::thread t0(thread_wrapper, std::ref(iface), std::ref(jlf_dir), std::ref(num_img));
t0.join();
std::cout << "-I- TEST ENDED" << std::endl;
}
catch (const std::exception &e)
{
std::cout << e.what();
}
}
\ No newline at end of file
#include "stream_and_info.hpp"
InputStream::InputStream()
:m_is_mux(false)
{}
InputStream::~InputStream()
{}
hailo_input_stream InputStream::GetStream() const {
return m_input_stream;
}
hailo_stream_info_t InputStream::GetStreamInfo() const {
return m_stream_info;
}
bool InputStream::GetIsMux() const {
return m_is_mux;
}
size_t InputStream::GetHostFrameSize() const {
return m_host_frame_size;
}
void InputStream::SetStream(hailo_input_stream input_stream) {
m_input_stream = input_stream;
}
void InputStream::SetStreamInfo(hailo_stream_info_t stream_info) {
m_stream_info = stream_info;
}
void InputStream::SetIsMux() {
m_is_mux = true;
}
void InputStream::SetHostFrameSize(hailo_stream_info_t info, hailo_stream_params_t params) {
m_host_frame_size = hailo_get_host_frame_size(&info, &params);
}
//////////////////////////////////////////////////////////////////////////////////////
OutputStream::OutputStream()
{}
OutputStream::OutputStream(hailo_output_stream output_stream, hailo_stream_info_t stream_info)
: m_output_stream(output_stream),
m_stream_info(stream_info),
m_is_mux(stream_info.is_mux)
{}
OutputStream::~OutputStream()
{}
OutputStream& OutputStream::operator = (const OutputStream& other) {
if(this != &other) {
m_output_stream = other.m_output_stream;
m_stream_info = other.m_stream_info;
}
return *this;
}
bool OutputStream::GetIsMux() const {
return m_is_mux;
}
hailo_output_stream& OutputStream::GetStream() {
return m_output_stream;
}
hailo_stream_info_t OutputStream::GetStreamInfo() const {
return m_stream_info;
}
size_t OutputStream::GetHostFrameSize() const {
return m_host_frame_size;
}
void OutputStream::SetStream(hailo_output_stream output_stream) {
m_output_stream = output_stream;
}
void OutputStream::SetStreamInfo(hailo_stream_info_t stream_info) {
m_stream_info = stream_info;
m_is_mux = stream_info.is_mux;
}
void OutputStream::SetHostFrameSize(hailo_stream_info_t info, hailo_stream_params_t params) {
m_host_frame_size = hailo_get_host_frame_size(&info, &params);
}
//////////////////////////////////////////////////////////////////////////////////////////
OutputStreamMux::OutputStreamMux()
{}
OutputStreamMux::OutputStreamMux(std::vector<hailo_stream_info_t> mux_stream_info, size_t output_mux_info_size, hailo_output_stream& output_stream, hailo_stream_info_t& stream_info)
: OutputStream(output_stream, stream_info),
m_mux_stream_info(mux_stream_info),
m_output_mux_info_size(output_mux_info_size)
{}
OutputStreamMux::~OutputStreamMux()
{}
OutputStreamMux& OutputStreamMux::operator = (const OutputStreamMux& other) {
if(this != &other) {
m_mux_stream_info = other.m_mux_stream_info;
m_output_mux_info_size = other.m_output_mux_info_size;
m_output_stream = other.m_output_stream;
m_stream_info = other.m_stream_info;
}
return *this;
}
std::vector<hailo_stream_info_t> OutputStreamMux::GetMuxStreamInfo() const {
return m_mux_stream_info;
}
size_t OutputStreamMux::GetMuxInfoSize() const {
return m_output_mux_info_size;
}
void OutputStreamMux::SetMuxStreamInfo(std::vector<hailo_stream_info_t> mux_stream_info) {
m_mux_stream_info = mux_stream_info;
}
void OutputStreamMux::SetMuxInfoSize(size_t mux_info_size) {
m_output_mux_info_size = mux_info_size;
}
void OutputStreamMux::ConfigurDemuxRawBuffers(std::vector<hailo_stream_raw_buffer_t>& demux_raw_buffers, std::vector< std::vector<float32_t> >& host_output_muxed_data) {
hailo_format_t demux_format;
hailo_stream_params_t params;
demux_raw_buffers.resize(m_output_mux_info_size);
demux_format.type = HAILO_FORMAT_TYPE_UINT8;
demux_format.order = HAILO_FORMAT_ORDER_NHWC;
demux_format.flags = HAILO_FORMAT_FLAGS_QUANTIZE;
// if (typeid(T) == typeid(float32_t)) {
demux_format.type = HAILO_FORMAT_TYPE_FLOAT32;
demux_format.flags = HAILO_FORMAT_FLAGS_NONE;
// }
params.user_buffer_format = demux_format;
for(unsigned int i = 0; i < m_output_mux_info_size; ++i) {
size_t host_frame_size = hailo_get_host_frame_size(&m_mux_stream_info[i], &params);
//size_t host_frame_size = m_mux_stream_info[i].shape_size;
host_output_muxed_data[i].resize(host_frame_size);
demux_raw_buffers[i].buffer = host_output_muxed_data[i].data();
demux_raw_buffers[i].offset = 0;
demux_raw_buffers[i].size = host_frame_size;
demux_raw_buffers[i].shape = m_mux_stream_info[i].shape;
demux_raw_buffers[i].format = demux_format;
}
}
#ifndef _STREAM_AND_INFO_H_
#define _STREAM_AND_INFO_H_
#include <vector>
#include <memory>
#include <hailo/hailort.h>
class OutputStream {
public:
OutputStream();
OutputStream(hailo_output_stream output_stream, hailo_stream_info_t stream_info);
virtual ~OutputStream();
OutputStream& operator = (const OutputStream& other);
hailo_output_stream& GetStream();
hailo_stream_info_t GetStreamInfo() const;
size_t GetHostFrameSize() const;
bool GetIsMux() const;
void SetStream(hailo_output_stream output_stream);
void SetStreamInfo(hailo_stream_info_t stream_info);
void SetHostFrameSize(hailo_stream_info_t info, hailo_stream_params_t params);
protected:
hailo_output_stream m_output_stream;
hailo_stream_info_t m_stream_info;
size_t m_host_frame_size;
bool m_is_mux;
};
class OutputStreamMux : public OutputStream {
public:
OutputStreamMux();
OutputStreamMux(std::vector<hailo_stream_info_t> mux_stream_info, size_t output_mux_info_size, hailo_output_stream& output_stream, hailo_stream_info_t& stream_info);
virtual ~OutputStreamMux();
OutputStreamMux& operator = (const OutputStreamMux& other);
std::vector<hailo_stream_info_t> GetMuxStreamInfo() const;
size_t GetMuxInfoSize() const;
void SetMuxStreamInfo(std::vector<hailo_stream_info_t> mux_stream_info);
void SetMuxInfoSize(size_t mux_info_size);
// template<class T>
void ConfigurDemuxRawBuffers(std::vector<hailo_stream_raw_buffer_t>& demux_raw_buffers, std::vector< std::vector<float32_t> >& host_output_muxed_data);
private:
std::vector<hailo_stream_info_t> m_mux_stream_info;
size_t m_output_mux_info_size;
};
class InputStream {
public:
InputStream();
~InputStream();
hailo_input_stream GetStream() const;
hailo_stream_info_t GetStreamInfo() const;
bool GetIsMux() const;
size_t GetHostFrameSize() const;
void SetStream(hailo_input_stream input_stream);
void SetStreamInfo(hailo_stream_info_t stream_info);
void SetIsMux();
void SetHostFrameSize(hailo_stream_info_t info, hailo_stream_params_t params);
private:
hailo_input_stream m_input_stream;
hailo_stream_info_t m_stream_info;
bool m_is_mux;
size_t m_host_frame_size;
};
#endif
\ No newline at end of file
cmake_minimum_required(VERSION 3.1)
project(cpp_agent)
message(STATUS "HAILORT_ROOT: $ENV{HAILORT_ROOT}")
set(HAILORT_ROOT $ENV{HAILORT_ROOT})
set(HAILORT_LIB $ENV{HAILORT_ROOT}/lib/${ARCH}/libhailort.so.$ENV{LIB_VER})
set(HAILORT_INCLUDE_DIR "$ENV{HAILORT_ROOT}/include")
set(COMPILE_OPTIONS_CPP -Werror -g -O0 -std=c++2a)
set(COMPILE_OPTIONS_CPP -Wall -Werror -O3 -DNDEBUG -std=c++2a)
include_directories(${HAILORT_INCLUDE_DIR} ./)
find_package(Threads)
find_package( OpenCV REQUIRED )
foreach(target runme.$ENV{LIB_VER})
add_executable(${target} example_device.cpp main.cpp)
# https://github.com/llohse/libnpy
target_include_directories(${target} PUBLIC /home/nadave/repos/libnpy)
target_compile_options(${target} PRIVATE ${COMPILE_OPTIONS_CPP})
target_link_libraries(${target} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${target} ${HAILORT_LIB})
target_link_libraries(${target} ${OpenCV_LIBS})
endforeach(target)
1. Dependencies:
1. OpenCV
`sudo apt-get install -y libopencv-dev`
`sudo apt-get install gcc-9 g++-9`
2. Install libnpy, if you want debug capability
git clone https://github.com/llohse/libnpy.git
3. Set HAILORT_ROOT environment variable, e.g.:
export HAILORT_ROOT=~/SDK/3.7.0/platform/hailort
2. Build the project
build.sh
3. The binary executable should be found in the ./build directory, e.g.:
./build/x86_64/runme.2.7.0
#!/bin/bash
declare -A COMPILER=( [x86_64]=/usr/bin/gcc
[aarch64]=/usr/bin/aarch64-linux-gnu-gcc
[armv7l]=/usr/bin/arm-linux-gnueabi-gcc )
HAILORT_ROOT=/home/nadave/SDK/platform-sw/hailort
HAILORT_ROOT=/home/nadave/SDK/3.7.0/platform/hailort
for ARCH in x86_64
do
echo "-I- Building ${ARCH}"
mkdir -p build/${ARCH}
export CXX=g++-9
LIB_VER=2.7.0 HAILORT_ROOT=${HAILORT_ROOT} cmake -H. -Bbuild/${ARCH} -DARCH=${ARCH} -DCMAKE_C_COMPILER=${COMPILER[${ARCH}]}
cmake --build build/${ARCH}
done
if [[ -f "hailort.log" ]]; then
rm hailort.log
fi
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <thread>
#include <vector>
#include <regex>
#include <chrono>
#include <future>
#include <fstream>
#include <memory>
#include <example_device.hpp>
#include <example_utils.hpp>
#include <hailo/hailort.h>
#include <yolov5_processing.hpp>
#ifdef DEBUG
#include "npy.hpp"
#endif
using namespace std;
example_device::example_device(std::string& iface, std::string& hef_file, unsigned int num_imgs, unsigned int batch, int write_log, int debug, bool yolo_post, std::string source) {
cout << CYAN
<< "-I- Running on interface: " << iface << " " << num_imgs << " images" << endl
<< RESET;
example_device::yolo_post = yolo_post;
example_device::iface = iface;
example_device::hef_file = hef_file;
example_device::debug = debug;
example_device::num_imgs = num_imgs;
example_device::write_log = write_log;
example_device::output_stream_cnt = NOF_STREAMS;
example_device::input_stream_cnt = 1;
example_device::batch_size = batch;
example_device::source_path = source;
active_net_g = NULL;
if (yolo_post) {
qp_zp_scale = {0};
use_one_rx_thrd = true;
}
}
void example_device::init_qp_zp_struct() {
qp_zp_scale.qp_scale_1 = all_stream_infos[1].quant_info.qp_scale;
qp_zp_scale.qp_scale_2 = all_stream_infos[2].quant_info.qp_scale;
qp_zp_scale.qp_scale_3 = all_stream_infos[3].quant_info.qp_scale;
qp_zp_scale.qp_zp_1 = all_stream_infos[1].quant_info.qp_zp;
qp_zp_scale.qp_zp_2 = all_stream_infos[2].quant_info.qp_zp;
qp_zp_scale.qp_zp_3 = all_stream_infos[3].quant_info.qp_zp;
}
example_device::~example_device() {}
void example_device::print_net_banner() {
printf(GREEN);
printf("-I-----------------------------------------------\n");
for (size_t ii=0; ii<output_stream_cnt+input_stream_cnt; ii++) {
printf("-I- %s[%ld]: %s (%d, %d, %d)\n", get_direction_name(all_stream_infos[ii].direction), ii, all_stream_infos[ii].name, all_stream_infos[ii].shape.height, all_stream_infos[ii].shape.width,
all_stream_infos[ii].shape.features);
}
printf("-I-----------------------------------------------\n");
printf(RESET);
}
double example_device::get_time_from_ts(struct timespec ts) {
double result = (double)(ts.tv_sec * 1000 + (ts.tv_nsec / 1000000));
return result;
}
hailo_status example_device::create_eth_device() {
hailo_status status = HAILO_SUCCESS;
size_t number_of_devices = 0;
try {
status = hailo_scan_ethernet_devices(iface.c_str(), &device_info, 1, &number_of_devices, HAILO_DEFAULT_ETH_SCAN_TIMEOUT_MS);
if (0 == number_of_devices) {
cout << "-E- No device found on the given interface:" << iface << endl;
status = HAILO_INTERNAL_FAILURE;
}
if (status != HAILO_SUCCESS) return status;
status = hailo_create_ethernet_device(&device_info, &device);
if (status != HAILO_SUCCESS) return status;
} catch (std::exception const& e) {
std::cout << "-E- create device failed" << e.what() << std::endl;
return HAILO_INTERNAL_FAILURE;
}
return status;
}
hailo_status example_device::create_pcie_device() {
hailo_status status = HAILO_SUCCESS;
size_t number_of_devices = 0;
try {
status = hailo_scan_pcie_devices(&pcie_device_info, 1, &number_of_devices);
if (0 == number_of_devices) {
cout << "-E- No device found on the given interface:" << iface << endl;
status = HAILO_INTERNAL_FAILURE;
}
if (status != HAILO_SUCCESS) return status;
status = hailo_create_pcie_device(&pcie_device_info, &device);
if (status != HAILO_SUCCESS) return status;
} catch (std::exception const& e) {
std::cout << "-E- create device failed" << e.what() << std::endl;
return HAILO_INTERNAL_FAILURE;
}
return status;
}
hailo_status example_device::print_debug_stats() {
uint32_t address;
std::vector<uint8_t> data(4);
uint32_t size = 4;
hailo_status status = HAILO_SUCCESS;
address = 0x0010918C;// rx_jabbers
status = hailo_read_memory(device, address, data.data(), size);
cout << CYAN
<< "-I-----------------------------------------------" << endl
<< "-D- RX_JABBERS: 0x" << data.data() << endl;
address = 0x00109190;// fcs_errors
status = hailo_read_memory(device, address, data.data(), size);
cout << "-D- FCS_ERRORS: 0x" << data.data() << endl
<< "-I-----------------------------------------------" << endl
<< RESET;
return status;
}
const char* example_device::get_direction_name(hailo_stream_direction_t dir) {
switch (dir) {
case HAILO_H2D_STREAM: return "Input";
case HAILO_D2H_STREAM: return "Output";
case HAILO_STREAM_DIRECTION_MAX_ENUM: return "Wrong";
}
return "Wrong";
}
double example_device::calc_latency(int count) {
double result = 0;
double cur_rcv;
double cur_snd;
for (int j=0; j<LATENCY_MEASUREMENTS; j++) {
cur_snd = get_time_from_ts(sent_clock_t[j]);
cur_rcv = get_time_from_ts(recv_clock_t[0][j]);
for (int ii=1; ii<count; ii++) {
if (get_time_from_ts(recv_clock_t[ii][j]) > cur_rcv) {
cur_rcv = get_time_from_ts(recv_clock_t[ii][j]);
}
}
result += (cur_rcv - cur_snd);
}
return result/LATENCY_MEASUREMENTS;
}
void example_device::print_inference_stats() {
double start_time_secs = (double)start_time.tv_sec + ((double)start_time.tv_nsec / NSEC_IN_SEC);
double end_time_secs = (double)end_time.tv_sec + ((double)end_time.tv_nsec / NSEC_IN_SEC);
double infer_time_secs = end_time_secs - start_time_secs;
static float mbit_per_byte = 8.0f / 1024.0f / 1024.0f;
cout << GREEN
<< "-I-----------------------------------------------" << endl
<< "-I- Total time: " << infer_time_secs << endl
<< "-I- Average FPS: " << (num_imgs * input_stream_cnt)/ infer_time_secs << endl
<< "-I- Send data rate: " << (double)(num_imgs) * host_input_frame_size * mbit_per_byte / infer_time_secs << " Mbit/s" << endl;
for (size_t i=0;i<output_stream_cnt;i++) {
printf("-I- Recv[%ld] data rate: %-4.2lf Mbit/s\n", i,
(double)(num_imgs) * host_output_frame_size[i] * mbit_per_byte / infer_time_secs);
printf("-I-----------------------------------------------\n");
}
printf(RESET);
}
template<class T>
void example_device::_send_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
std::vector<T> src_data;
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
struct timespec ts;
src_data.resize(write_args->host_input_frame_size);
if (src_data.empty()) {
cout << "-E- Failed to allocate buffers" << endl;
status = HAILO_OUT_OF_HOST_MEMORY;
} else {
for(size_t i = 0; i < write_args->host_input_frame_size; i++) {
src_data[i] = (T)(rand() % 256);
}
flag_100 = (uint32_t)write_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
for (uint32_t i = 1; i <= (uint32_t)write_args->num_images; i++) {
if ((i % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Send frame [%3d/%3d]\n", (long)ts.tv_sec, ts.tv_nsec/1000000, write_args->tid, i, write_args->num_images);
sent_clock_t[lat_counter++] = ts;
}
status = hailo_stream_sync_write_all_raw_buffer(write_args->input_stream,
src_data.data(),
0,
write_args->host_input_frame_size);
if (status != HAILO_SUCCESS) {
cout << "-E- hailo_stream_sync_write_all_raw_buffer failed" << endl;
break;
}
}
}
write_args->status = status;
}
template<class T>
void example_device::_recv_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
recv_thread_args_t *recv_args = (recv_thread_args_t *)args;
struct timespec ts;
ofstream outFile;
std::vector<T> recv_array;
unsigned lat_counter = 0;
uint32_t flag_100 = 0;
cout << CYAN << "-I- Recv thread " << recv_args->tid << " started" << RESET << endl;
if (yolo_post)
cout << CYAN << "-I- Recv thread: Doing YOLOv5 post-processing" << RESET << endl;
if (recv_args->write_log==1) {
string log_name = "rx_tid_0.log";
outFile = ofstream(log_name);
}
flag_100 = (uint32_t)recv_args->num_images / 100;
if (flag_100==0)
flag_100 = 1;
recv_array.resize(recv_args->host_output_frame_size);
for (uint32_t j = 1; j <= (uint32_t)recv_args->num_images; j++) {
status = hailo_stream_sync_read_all_raw_buffer(recv_args->output_stream, recv_array.data(), 0, recv_args->host_output_frame_size);
REQUIRE_SUCCESS(status, l_exit, "Failed at hailo_stream_sync_read_all_raw_buffer");
if ((j % flag_100==0) && (lat_counter < LATENCY_MEASUREMENTS)) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] TID:%d Recv [%3d/%3d] \n", (long)ts.tv_sec, ts.tv_nsec/1000000, recv_args->tid, j, recv_args->num_images);
recv_clock_t[recv_args->tid][lat_counter++] = ts;
}
}
l_exit:
recv_args->status = status;
}
void* example_device::_send_from_source_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
write_thread_args_t *write_args = (write_thread_args_t*)args;
// unsigned lat_counter = 0;
struct timespec ts;
cv::Mat curr_img(all_stream_infos->shape.width, all_stream_infos->shape.width, CV_8UC3);
int counter = 0;
vector<uint8_t> array;
array.resize(host_input_frame_size);
while (true) {
if (input_image_queue.empty()) {
cout << "-I- Waiting for the image queue to fill" << endl;
sleep(1);
continue;
}
pthread_mutex_lock(&input_image_queue_m);
curr_img = input_image_queue.front();
input_image_queue.pop();
pthread_mutex_unlock(&input_image_queue_m);
if (counter % 500==0) {
clock_gettime(CLOCK_REALTIME, &ts);
printf("-I- [%10ld.%ld s] Send frame [%3d] 0x%x%x\n", (long)ts.tv_sec, ts.tv_nsec/1000000, counter, curr_img.data[0], curr_img.data[1]);
}
counter++;
if (curr_img.data[0] == 17 && curr_img.data[1] == 71 && curr_img.data[2] == 17 && curr_img.data[3] == 71) {
cout << "-I- [TX-Thread] Received stop pattern - " << counter << endl;
sleep (1);
break;
}
if (curr_img.isContinuous()) {
int totalsz = curr_img.dataend-curr_img.datastart;
array.assign(curr_img.datastart, curr_img.datastart + totalsz);
} else {
int rowsz = CV_ELEM_SIZE(curr_img.type()) * curr_img.cols;
for (int i = 0; i < curr_img.rows; ++i) {
array.insert(array.end(), curr_img.ptr<uint8_t>(i), curr_img.ptr<uint8_t>(i) + rowsz);
}
}
status = hailo_stream_sync_write_all_raw_buffer(input_stream, array.data(), 0, host_input_frame_size);
if (status != HAILO_SUCCESS) {
printf("-E- hailo_stream_sync_write_all_raw_buffer failed");
break;
}
}
write_args->status = status;
write_args->num_images = counter;
return NULL;
}
template<class T>
void example_device::_recv_thread1(std::future<void> &futureObj) {
hailo_status status = HAILO_SUCCESS;
std::vector< std::vector<T> > recv_array;
size_t counter = 0;
if (yolo_post)
cout << CYAN << "-I- Recv thread: Doing YOLOv5 post-processing" << RESET << endl;
recv_array.resize(output_stream_cnt);
for (size_t i=0; i<output_stream_cnt;++i)
recv_array[i].resize(host_output_frame_size[i]);
while (true) {
for (size_t i=0; i<output_stream_cnt;++i) {
status = hailo_stream_sync_read_all_raw_buffer(output_streams[i], recv_array[i].data(), 0, host_output_frame_size[i]);
if (status==HAILO_PCIE_DRIVER_FAIL) goto l_exit;
REQUIRE_SUCCESS(status, l_exit, "Failed at hailo_stream_sync_read_all_raw_buffer");
}
#ifdef DEBUG
size_t shape2 [] = {20, 20, 255};
cout << "-I- Saving logit ouput2 to cpp-output-2.npy" << endl;
npy::SaveArrayAsNumpy("cpp-output-2.npy", false, 3, shape2, recv_array[2]);
size_t shape1 [] = {40, 40, 255};
cout << "-I- Saving logit ouput1 to cpp-output-1.npy" << endl;
npy::SaveArrayAsNumpy("cpp-output-1.npy", false, 3, shape1, recv_array[1]);
size_t shape0 [] = {80, 80, 255};
cout << "-I- Saving logit ouput0 to cpp-output-0.npy" << endl;
npy::SaveArrayAsNumpy("cpp-output-0.npy", false, 3, shape0, recv_array[0]);
#endif
vector<float32_t> detections;
auto num_dets = get_detections(recv_array[0], recv_array[1], recv_array[2], qp_zp_scale, 0.2, detections);
if (num_dets > 0) {
#ifdef DBEUG
cout << "-I- Saving the detections to cpp_detections.npy: " << endl;
size_t shape [] = {4, 1};
npy::SaveArrayAsNumpy("cpp_detections.npy", false, 2, shape, detections);
#endif
cout << "-I- Num detections: " << num_dets << " Classes: [";
for (size_t i = 0; i < num_dets;i++)
cout << get_coco_name_from_int(detections[i*6+4]) << " ";
cout << "]" << endl;
}
counter++;
if (counter%100 == 0)
cout << CYAN << "-I- Received frame #"<< counter << RESET << endl;
}
l_exit:
cout << CYAN << "-I- Exit Recv thread code:"<< status << RESET << endl;
}
bool example_device::source_is_video(string& path) {
const vector<string> suffixs = {"mkv", "avi", "webm", "mp4"};
for (string suffix : suffixs) {
if (regex_search(path, regex(string(suffix) + "$")))
return true;
}
return false;
}
void* example_device::_frame_lib_thread(void *args) {
video_thread_args_t *v_args = (video_thread_args_t*)args;
cv::Mat org_frame;
vector< cv::String > file_names;
cv::Mat pp_frame(v_args->input_stream_info->hw_shape.height, v_args->input_stream_info->hw_shape.height, CV_8UC3);
unsigned int idx=0;
cv::Size input_size;
cout << BOLDCYAN << "-I-----------------------------------------------" << endl
<< "-I- [Frames-thread] Source: " << v_args->video_path << endl
<< "-I- [Frames-thread] Net input shape (" << v_args->input_stream_info->hw_shape.height <<
", " << v_args->input_stream_info->hw_shape.height <<
", " << v_args->input_stream_info->hw_shape.features << ")" << endl
<< "-I-----------------------------------------------"
<< RESET << endl;
cv::glob(v_args->video_path, file_names, false);
input_size.width = v_args->input_stream_info->hw_shape.width;
input_size.height = v_args->input_stream_info->hw_shape.height;
for (std::string file : file_names) {
if (not(file.ends_with(".jpg") || file.ends_with(".png"))) {
continue;
}
org_frame = cv::imread(file);
if (org_frame.channels() == 3) {
cv::cvtColor(org_frame, org_frame, cv::COLOR_BGR2RGB);
}
cout << "-I- [Frames-thread] Getting frame #"<< idx++ << ":" << file << endl;
// size_t shape [] = {640, 640, 3};
pp_frame = yolov5_pre_process(org_frame);
#ifdef DEBUG
cout << "-I- Saving the preprocessed image to cpp-prep-image.npy" << endl;
size_t shape [] = {640, 640, 3};
std::vector<float> image;
int totalsz = pp_frame.dataend-pp_frame.datastart;
image.assign(pp_frame.datastart, pp_frame.datastart + totalsz);
npy::SaveArrayAsNumpy("cpp-prep-image.npy", false, 3, shape, image);
#endif
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame.clone());
pthread_mutex_unlock(&input_image_queue_m);
}
// Mark the final frame
pp_frame.data[0] = 17;
pp_frame.data[1] = 71;
pp_frame.data[2] = 17;
pp_frame.data[3] = 71;
idx++;
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame.clone());
pthread_mutex_unlock(&input_image_queue_m);
cout << BOLDCYAN << "-I-----------------------------------------------" << endl
<< "-I- [Frames-thread] FINISHED READING DIR - #" << idx-1 << endl
<< "-I-----------------------------------------------"
<< RESET << endl;
return NULL;
}
void* example_device::_video_source_thread(void *args) {
hailo_status status = HAILO_SUCCESS;
video_thread_args_t *v_args = (video_thread_args_t*)args;
cv::Mat org_frame;
cv::Mat pp_frame(v_args->input_stream_info->hw_shape.height, v_args->input_stream_info->hw_shape.height, CV_8UC3);
unsigned int idx=0;
cv::VideoCapture cap(v_args->video_path);
if (!cap.isOpened()) {
cout << "-E- Unable to open video stream" << endl;
status = HAILO_INTERNAL_FAILURE;
}
// cv::Size shape = cv::Size((int) cap.get(CV_CAP_PROP_FRAME_WIDTH), (int) cap.get(CV_CAP_PROP_FRAME_HEIGHT));
cout << BOLDCYAN << "-I-----------------------------------------------" << endl;
cout << "-I- [Video-thread] Source: " << v_args->video_path << endl;
cout << "-I- [Frames-thread] Net input shape (" << v_args->input_stream_info->hw_shape.height <<
", " << v_args->input_stream_info->hw_shape.height <<
", " << v_args->input_stream_info->hw_shape.features << ")" << endl;
cout << "-I-----------------------------------------------" << RESET << endl;
while (true && status==HAILO_SUCCESS) {
if (++idx%500==0)
cout << "-I- [Video-thread] Getting frame: "<< idx << endl;
cap >> org_frame;
if (org_frame.empty())
break;
resize(org_frame, pp_frame, pp_frame.size());
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame.clone());
pthread_mutex_unlock(&input_image_queue_m);
}
// Mark the final frame
pp_frame.data[0] = 17;
pp_frame.data[1] = 71;
pp_frame.data[2] = 17;
pp_frame.data[3] = 71;
idx++;
pthread_mutex_lock(&input_image_queue_m);
input_image_queue.push(pp_frame);
pthread_mutex_unlock(&input_image_queue_m);
cout << BOLDCYAN << "-I-----------------------------------------------" << endl;
cout << "-I- [Video-thread] FINISHED MOVIE STREAM - " << idx-1 << endl;
cout << "-I-----------------------------------------------" << RESET << endl;
cap.release();
return (void *)status;
}
template<class T>
hailo_status example_device::infer() {
hailo_status status = HAILO_SUCCESS;
std::vector<std::thread> recv_threads;
std::vector<std::thread> write_threads;
std::thread source_thread;
std::vector<recv_thread_args_t> recv_args;
std::vector<write_thread_args_t> write_args;
video_thread_args_t source_args;
std::promise<void> exitSignal;
std::future<void> futureObj = exitSignal.get_future();
write_threads.resize(input_stream_cnt);
write_args.resize(input_stream_cnt);
source_args.input_stream_info = &all_stream_infos[0];
source_args.video_path = source_path.c_str();
if (yolo_post) {
cout << CYAN << "-I- Creating YOLOv5 threads scheme (1\\1\\1)" << RESET << endl;
if (source_is_video(source_path))
source_thread = std::thread(&example_device::_video_source_thread, this, &source_args);
else
source_thread = std::thread(&example_device::_frame_lib_thread, this, &source_args);
write_threads[0] = std::thread(&example_device::_send_from_source_thread, this, &write_args[0]);
recv_threads.resize(1);
recv_threads[0] = std::thread(&example_device::_recv_thread1<T>, this, std::ref(futureObj));
recv_threads[0].detach();
} else {
for (size_t s=0;s<input_stream_cnt;s++) {
write_args[s].tid = s;
write_args[s].input_stream = input_stream;
write_args[s].status = HAILO_SUCCESS;
write_args[s].output_streams_cnt = output_stream_cnt;
write_args[s].num_images = num_imgs;
write_args[s].stream_info = all_stream_infos[s];
write_args[s].host_input_frame_size = host_input_frame_size;
write_threads[s] = std::thread(&example_device::_send_thread<T>, this, &write_args[s]);
}
recv_args.resize(output_stream_cnt);
recv_threads.resize(output_stream_cnt);
for (size_t s=0;s<output_stream_cnt;s++) {
cout << CYAN << "-I- Creating RECV Thread #" << s << RESET << endl;
recv_args[s].output_stream = output_streams[s];
recv_args[s].tid = s;
recv_args[s].status = HAILO_SUCCESS;
recv_args[s].num_images = num_imgs;
recv_args[s].write_log = write_log;
recv_args[s].stream_info = all_stream_infos[s+1];
recv_args[s].host_output_frame_size = host_output_frame_size[s];
recv_threads[s] = std::thread(&example_device::_recv_thread<T>, this, &recv_args[s]);
}
}
(void) clock_gettime(CLOCK_MONOTONIC, &start_time);
if (yolo_post)
source_thread.join();
for (auto& t: write_threads) t.join();
cout << CYAN << "-I- Finished 2 all threads" << RESET << endl;
if (yolo_post)
exitSignal.set_value();
// else
for (auto& t: recv_threads) if (t.joinable()) t.join();
cout << CYAN << "-I- Finished all threads" << RESET << endl;
(void) clock_gettime(CLOCK_MONOTONIC, &end_time);
for (auto& a: write_args) {
if (HAILO_SUCCESS != a.status) {
cout << "-E- write_thread failed" << endl;
status = HAILO_INTERNAL_FAILURE;
}
}
return status;
}
hailo_status example_device::create_and_load_hef()
{
hailo_status status = HAILO_SUCCESS;
size_t number_of_network_groups = 1;
hailo_configure_params_t configure_params = {0};
status = hailo_create_hef_file(&hef, hef_file.c_str());
REQUIRE_SUCCESS(status, l_exit, "Failed to create hef file");
cout << CYAN << "-I- Loading HEF file from " << hef_file << RESET << endl;
configure_params.network_group_params[0].batch_size = batch_size;
status = hailo_configure_device(device, hef, &configure_params, &network_group, &number_of_network_groups);
REQUIRE_SUCCESS(status, l_exit, "Failed to configure device from hef");
if (number_of_network_groups > 1) {
status = HAILO_UNINITIALIZED;
cout << "-E- Got network_group=" <<number_of_network_groups << endl;
REQUIRE_SUCCESS(status, l_exit, "Failed to extract network group, larger than 1");
}
l_exit:
return status;
}
template<class T>
hailo_status example_device::set_stream_infos(hailo_input_stream_params_by_name_t *input_stream_params, hailo_output_stream_params_by_name_t *output_stream_params)
{
hailo_status status = HAILO_SUCCESS;
size_t number_of_streams = 0;
bool quantized = false;
hailo_stream_transform_mode_t transform = HAILO_STREAM_TRANSFORM_COPY;
hailo_format_type_t format = HAILO_FORMAT_TYPE_UINT8;
if (std::is_same<T, float32_t>::value)
format = HAILO_FORMAT_TYPE_FLOAT32;
status = hailo_hef_get_all_stream_infos(hef, NULL, all_stream_infos, NOF_STREAMS, &number_of_streams);
REQUIRE_SUCCESS(status, l_exit, "Failed to get pcie_stream_infos");
cout << CYAN << "-I- Activating the input streams with transform=" << transform << ", quantized=" << quantized << RESET << endl;
status = hailo_make_input_stream_params(network_group, transform, quantized, format, input_stream_params, &input_stream_cnt);
REQUIRE_SUCCESS(status, l_exit, "Failed to get input stream params");
// Passing here quantized=true, this is unique to YOLOv5, where the post-processing function will take
// care of the scaling of the output, only on the BOXES that are above the IOU threashold.
format = HAILO_FORMAT_TYPE_UINT8;
quantized = true;
cout << CYAN << "-I- Activating the output streams with transform=" << transform << ", quantized=" << quantized << RESET << endl;
status = hailo_make_output_stream_params(network_group, transform, quantized, format, output_stream_params, &output_stream_cnt);
REQUIRE_SUCCESS(status, l_exit, "Failed to get input stream params");
l_exit:
return status;
}
hailo_status example_device::activate_network_group(hailo_input_stream_params_by_name_t *input_stream_params, hailo_output_stream_params_by_name_t *output_stream_params)
{
hailo_status status = HAILO_SUCCESS;
hailo_network_group_params_t network_group_params;
// network_group_params.context_switch_batch_size = 1;
// for (int i = 0; i < output_stream_cnt;++i)
// output_stream_params[i].params.eth_params.base_params.buffers_threshold = 1;
// input_stream_params->params.eth_params.base_params.buffers_threshold = 1;
status = hailo_activate_network_group(network_group,
&network_group_params,
input_stream_params, // Input params
input_stream_cnt, // number of inputs
output_stream_params, // Output params
output_stream_cnt, // number of ouputs
&active_net_g);
REQUIRE_SUCCESS(status, l_exit, "Failed to activate network group");
l_exit:
return status;
}
template<class T>
hailo_status example_device::setup_device_for_inference() {
hailo_status status = HAILO_SUCCESS;
hailo_input_stream_params_by_name_t input_stream_params = {0};
hailo_output_stream_params_by_name_t output_stream_params[NOF_STREAMS];
if (iface.compare("pcie") == 0) {
status = create_pcie_device();
} else {
status = create_eth_device();
}
if (status!=HAILO_SUCCESS) return status;
status = create_and_load_hef();
if (status != HAILO_SUCCESS) {
cout << "-E- Failed to get all stream info" << endl;
release_hef();
return status;
}
status = set_stream_infos<T>(&input_stream_params, output_stream_params);
REQUIRE_SUCCESS(status, l_exit, "Failed get_stream_infos");
status = activate_network_group(&input_stream_params, output_stream_params);
REQUIRE_SUCCESS(status, l_exit, "Failed activate_network_group");
status = hailo_get_input_stream_by_name(active_net_g, all_stream_infos[0].name, &input_stream);
REQUIRE_SUCCESS(status, l_exit, "Failed get_input_stream_by_name");
host_input_frame_size = hailo_get_input_stream_frame_size(input_stream);
for (size_t i = 0; i < output_stream_cnt; ++i) {
status = hailo_get_output_stream_by_name(active_net_g, all_stream_infos[i+1].name, &output_streams[i]);
REQUIRE_SUCCESS(status, l_exit, "Failed get_output_stream_by_name");
host_output_frame_size[i] = hailo_get_output_stream_frame_size(output_streams[i]);
}
print_net_banner();
l_exit:
return status;
}
void example_device::release_output_streams() {
// for (size_t i = 0; i < output_stream_cnt; ++i)
// (void) hailo_release_output_stream(device, output_streams[i]);
if (example_device::debug==1) {
print_debug_stats();
}
}
void example_device::release_input_stream() {
// for (const auto &s: input_streams) (void) hailo_release_input_stream(device, s.GetStream());
//( void) hailo_release_input_stream(device, input_stream);
}
void example_device::release_hef() {
(void) hailo_release_hef(example_device::hef);
}
void example_device::release_device() {
(void) hailo_release_device(example_device::device);
}
void example_device::run_inference() {
hailo_status status = HAILO_SUCCESS;
status = setup_device_for_inference<uint8_t>();
REQUIRE_SUCCESS(status, l_exit, "setup_device_for_inference failed");
if (yolo_post)
init_qp_zp_struct();
status = infer<uint8_t>();
example_device::print_inference_stats();
example_device::release_output_streams();
example_device::release_input_stream();
example_device::release_hef();
example_device::release_device();
l_exit:
cout << GREEN << "-I- Finished Gracefully" << RESET << endl;
}
#ifndef _EXAMPLE_DEVICE_H_
#define _EXAMPLE_DEVICE_H_
#include <time.h>
#include <net/if.h>
#include <vector>
#include <memory>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <dirent.h>
#include <linux/limits.h>
#include <example_utils.hpp>
#include <condition_variable>
#include <queue>
#include <future>
#include <opencv2/opencv.hpp>
#include <opencv2/video/video.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <hailo/hailort.h>
#define NOF_STREAMS (6)
#define NSEC_IN_SEC (1e+9)
#define LATENCY_MEASUREMENTS (100)
#define MAX_OUTPUT_MUX_INFO_CAPACITY (16)
class example_device
{
private:
hailo_eth_device_info_t device_info;
hailo_pcie_device_info_t pcie_device_info;
hailo_device device;
hailo_hef hef;
hailo_network_group network_group;
hailo_activated_network_group active_net_g;
hailo_input_stream input_stream;
hailo_output_stream output_streams[NOF_STREAMS];
hailo_stream_info_t all_stream_infos[NOF_STREAMS];
struct timespec start_time;
struct timespec end_time;
struct timespec sent_clock_t[LATENCY_MEASUREMENTS];
struct timespec recv_clock_t[NOF_STREAMS-1][LATENCY_MEASUREMENTS];
std::string iface;
std::string hef_file;
unsigned int num_imgs;
unsigned int batch_size;
int write_log;
int debug;
bool yolo_post;
qp_zp_scale_t qp_zp_scale;
bool use_one_rx_thrd;
std::queue<cv::Mat> input_image_queue;
pthread_mutex_t input_image_queue_m = PTHREAD_MUTEX_INITIALIZER;
// std::queue< std::vector<uint8_t> > post_infer_queue[NOF_STREAMS-1];
// pthread_mutex_t post_infer_queue_m = PTHREAD_MUTEX_INITIALIZER;
void* _frame_lib_thread(void *args);
void* _video_source_thread(void *args);
void* _send_from_source_thread(void *args);
std::string source_path;
bool source_is_video(std::string& path);
template <class T> void _recv_thread1(std::future<void> &futureObj);
void init_qp_zp_struct();
hailo_status create_pcie_device();
hailo_status create_eth_device();
hailo_status print_debug_stats();
template<class T> hailo_status set_stream_infos(hailo_input_stream_params_by_name_t *input_stream_params, hailo_output_stream_params_by_name_t *output_stream_params);
const char* get_direction_name(hailo_stream_direction_t dir);
double calc_latency(int count);
template <class T> void _recv_thread(void *args);
template <class T> void _send_thread(void *args);
template <class T> hailo_status infer();
void release_input_stream();
void release_hef();
void release_device();
double get_time_from_ts(struct timespec ts);
public:
size_t output_stream_cnt;
size_t input_stream_cnt;
example_device(std::string& iface, std::string& hef_file, unsigned int num_imgs, unsigned int batch, int write_log, int debug, bool yolo_post, std::string source_path);
~example_device();
hailo_status create_and_load_hef();
void print_net_banner();
void print_inference_stats();
template <class T> hailo_status setup_device_for_inference();
void release_output_streams();
void run_inference();
hailo_status activate_network_group(hailo_input_stream_params_by_name_t *input_stream_params, hailo_output_stream_params_by_name_t *output_stream_params);
size_t host_input_frame_size;
size_t host_output_frame_size[NOF_STREAMS];
};
#endif
#ifndef _EXAMPLE_UTILS_H_
#define _EXAMPLE_UTILS_H_
#include <hailo/hailort.h>
#define FREE(var) \
do \
{ \
if (NULL != (var)) \
{ \
free(var); \
var = NULL; \
} \
} while (0)
#define REQUIRE_SUCCESS(status, label, msg) \
do \
{ \
if (HAILO_SUCCESS != (status)) \
{ \
printf(BOLDRED); \
printf("-E- %s : (%d)\n",msg, status); \
printf(RESET); \
goto label; \
} \
} while (0)
typedef struct write_thread_args_t
{
hailo_stream_info_t input_stream_info;
hailo_input_stream input_stream;
hailo_status status;
hailo_stream_info_t stream_info;
int output_streams_cnt;
unsigned int num_images;
size_t host_input_frame_size;
int tid;
} write_thread_args_t;
typedef struct recv_thread_args_t
{
hailo_output_stream output_stream;
hailo_status status;
size_t host_output_frame_size;
hailo_stream_info_t stream_info;
unsigned int num_images;
int num_streams;
int write_log;
int tid;
} recv_thread_args_t;
typedef struct recv_thread1_args_t
{
hailo_output_stream *output_stream;
size_t *host_output_frame_size;
hailo_stream_info_t *stream_info;
unsigned int num_images;
int num_streams;
int write_log;
} recv_thread1_args_t;
typedef struct video_thread_args_t
{
hailo_stream_info_t *input_stream_info;
const char *video_path;
int num_images;
} video_thread_args_t;
typedef struct qp_zp_scale_t {
float32_t qp_zp_1;
float32_t qp_scale_1;
float32_t qp_zp_2;
float32_t qp_scale_2;
float32_t qp_zp_3;
float32_t qp_scale_3;
} qp_zp_scale_t;
#define RESET "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
#endif
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
**/
/**
* @ file main.cpp
* This example demonstrates the basic data-path on HailoRT.
* The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates random dataset,
* and runs it through the device.
**/
#include "example_device.hpp"
#include "example_utils.hpp"
#include <iostream>
#include <thread>
#include <functional>
void thread_wrapper(std::string &iface, std::string &hef_file, unsigned int &batch, unsigned int &num_img, int &write_log, int &debug, bool &yolo_post, std::string &source_input)
{
example_device dev(iface, hef_file, num_img, batch, write_log, debug, yolo_post, source_input);
dev.run_inference();
}
int main(int argc, char **argv)
{
std::string hef = "";
std::string iface = "pcie";
std::string video_path = "";
bool yolo_post = false;
int opt;
unsigned int num_img = 100;
unsigned int batch = 1;
int debug = 0;
int write_log = 0;
while ((opt = getopt(argc, argv, "i:c:n:v:dly")) != -1)
{
switch (opt)
{
case 'c':
hef = optarg;
break;
case 'b':
batch = atoi(optarg);
break;
case 'i':
iface = optarg;
break;
case 'n':
num_img = atoi(optarg);
break;
case 'd':
debug = 1;
break;
case 'l':
write_log = 1;
break;
case 'v':
video_path = optarg;
break;
case 'y':
yolo_post = true;
break;
case '?':
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
default:
fprintf(stderr, "Usage: %s -i INTERFACE -j JLF-DIR [-n NUM-IMAGES]\n\n", argv[0]);
fprintf(stderr, " -c HEF The HEF Configuration file\n");
fprintf(stderr, " -n NUM-IMAGES The number of images to process, defaults to 100\n");
fprintf(stderr, " -v VIDEO FILE Path to an input video file\n");
fprintf(stderr, " -i INTERFACE The device interface, defaults to \'pcie\', if using Ethernet name the Host port\n");
fprintf(stderr, " -b BATCH Batch size, defaults to 1, relevant only to context-switch\n");
fprintf(stderr, " -y Do YOLOv5 post-processing\n");
fprintf(stderr, " -d Read and print debug registers from FW\n");
fprintf(stderr, " -l Each receive thread will write a log file\n");
exit(EXIT_FAILURE);
}
}
try
{
std::cout << CYAN << "-I- TEST STARTS" << RESET << std::endl;
if (yolo_post==true && video_path.empty()) {
std::cout << RED << "-W- Received no input source (Video or images) and YOLOv5, aborting" << RESET << std::endl;
exit(0);
}
std::thread t0(thread_wrapper, std::ref(iface), std::ref(hef), std::ref(num_img), std::ref(batch), std::ref(write_log), std::ref(debug), std::ref(yolo_post), std::ref(video_path));
t0.join();
std::cout << CYAN << "-I- TEST ENDED" << RESET << std::endl;
}
catch (const std::exception &e)
{
std::cout << e.what();
}
}
\ No newline at end of file
#ifndef _YOLOV5_POSTPROCESS_H_
#define _YOLOV5_POSTPROCESS_H_
#include <vector>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <functional>
#include <example_utils.hpp>
#include <hailo/hailort.h>
#ifdef DEBUG
#include "npy.hpp"
#endif
constexpr int FEATURE_MAP_SIZE1 = 20;
constexpr int FEATURE_MAP_SIZE2 = 40;
constexpr int FEATURE_MAP_SIZE3 = 80;
constexpr int FEATURE_MAP_CHANNELS = 85;
constexpr int IMAGE_SIZE = 640;
constexpr int ANCHORS_NUM = 3;
constexpr float32_t IOU_THRESHOLD = 0.45f;
constexpr int MAX_BOXES = 100;
constexpr int CONF_CHANNEL_OFFSET = 4;
constexpr int CLASS_CHANNEL_OFFSET = 5;
struct DetectionObject {
float ymin, xmin, ymax, xmax, confidence;
int class_id;
DetectionObject(float32_t ymin, float32_t xmin, float32_t ymax, float32_t xmax, float32_t confidence, int class_id):
ymin(ymin), xmin(xmin), ymax(ymax), xmax(xmax), confidence(confidence), class_id(class_id)
{}
bool operator<(const DetectionObject &s2) const {
return this->confidence > s2.confidence;
}
};
float32_t fix_scale(float32_t input, float32_t qp_scale, float32_t qp_zp)
{
return (input - qp_zp) * qp_scale;
}
float32_t iou_calc(const DetectionObject &box_1, const DetectionObject &box_2) {
const float32_t width_of_overlap_area = std::min(box_1.xmax, box_2.xmax) - std::max(box_1.xmin, box_2.xmin);
const float32_t height_of_overlap_area = std::min(box_1.ymax, box_2.ymax) - std::max(box_1.ymin, box_2.ymin);
const float32_t positive_width_of_overlap_area = std::max(width_of_overlap_area, 0.0f);
const float32_t positive_height_of_overlap_area = std::max(height_of_overlap_area, 0.0f);
const float32_t area_of_overlap = positive_width_of_overlap_area * positive_height_of_overlap_area;
const float32_t box_1_area = (box_1.ymax - box_1.ymin) * (box_1.xmax - box_1.xmin);
const float32_t box_2_area = (box_2.ymax - box_2.ymin) * (box_2.xmax - box_2.xmin);
return area_of_overlap / (box_1_area + box_2_area - area_of_overlap);
}
void extract_boxes(std::vector<uint8_t> &fm, float32_t qp_zp, float32_t qp_scale, int feature_map_size,
int* anchors, std::vector<DetectionObject>& objects, float32_t& thr) {
float32_t confidence, x, y, h, w, xmin, ymin, xmax, ymax, conf_max = 0.0f;
int add = 0, anchor = 0, chosen_row = 0, chosen_col = 0, chosen_cls = -1;
float32_t cls_prob, prob_max;
// channels 0-3 are box coordinates, channel 4 is the confidence, and channels 5-84 are classes
for (int row = 0; row < feature_map_size; ++row) {
for (int col = 0; col < feature_map_size; ++col) {
prob_max = 0;
for (int a = 0; a < ANCHORS_NUM; ++a) {
add = FEATURE_MAP_CHANNELS * ANCHORS_NUM * feature_map_size * row + FEATURE_MAP_CHANNELS * ANCHORS_NUM * col + FEATURE_MAP_CHANNELS * a + CONF_CHANNEL_OFFSET;
confidence = fix_scale(fm[add], qp_scale, qp_zp);
for (int c = CLASS_CHANNEL_OFFSET; c < FEATURE_MAP_CHANNELS; ++c) {
add = FEATURE_MAP_CHANNELS * ANCHORS_NUM * feature_map_size * row + FEATURE_MAP_CHANNELS * ANCHORS_NUM * col + FEATURE_MAP_CHANNELS * a + c;
// final confidence: box confidence * class probability
cls_prob = fm[add];
if (cls_prob > prob_max) {
conf_max = fix_scale(cls_prob, qp_scale, qp_zp) * confidence;
chosen_cls = c - CLASS_CHANNEL_OFFSET + 1;
prob_max = cls_prob;
anchor = a;
chosen_row = row;
chosen_col = col;
}
}
}
if (conf_max >= thr) {
add = FEATURE_MAP_CHANNELS * ANCHORS_NUM * feature_map_size * chosen_row + FEATURE_MAP_CHANNELS * ANCHORS_NUM * chosen_col + FEATURE_MAP_CHANNELS * anchor;
x = (fix_scale(fm[add], qp_scale, qp_zp) * 2.0f - 0.5f + chosen_col) / feature_map_size;
y = (fix_scale(fm[add + 1], qp_scale, qp_zp) * 2.0f - 0.5f + chosen_row) / feature_map_size;
w = pow(2.0f * (fix_scale(fm[add + 2], qp_scale, qp_zp)), 2.0f) * anchors[anchor * 2] / IMAGE_SIZE;
h = pow(2.0f * (fix_scale(fm[add + 3], qp_scale, qp_zp)), 2.0f) * anchors[anchor * 2 + 1] / IMAGE_SIZE;
xmin = (x - (w / 2.0f)) * IMAGE_SIZE;
ymin = (y - (h / 2.0f)) * IMAGE_SIZE;
xmax = (x + (w / 2.0f)) * IMAGE_SIZE;
ymax = (y + (h / 2.0f)) * IMAGE_SIZE;
objects.push_back(DetectionObject(ymin, xmin, ymax, xmax, conf_max, chosen_cls));
}
}
}
}
size_t _decode(std::vector<uint8_t> &fm1, std::vector<uint8_t> &fm2, std::vector<uint8_t> &fm3, int* anchors1, int* anchors2, int* anchors3,
// xt::xarray<float32_t, xt::layout_type::row_major> _decode(std::vector<uint8_t> &fm1, std::vector<uint8_t> &fm2, std::vector<uint8_t> &fm3, int* anchors1, int* anchors2, int* anchors3,
qp_zp_scale_t qp_zp_scale, float32_t& thr, std::vector<float32_t> &results) {
size_t num_boxes = 0;
std::vector<DetectionObject> objects;
// std::vector<std::vector<float32_t>> results;
objects.reserve(MAX_BOXES);
// feature map1/2/3
extract_boxes(fm1, qp_zp_scale.qp_zp_1, qp_zp_scale.qp_scale_1, FEATURE_MAP_SIZE1, anchors1, objects, thr);
extract_boxes(fm2, qp_zp_scale.qp_zp_2, qp_zp_scale.qp_scale_2, FEATURE_MAP_SIZE2, anchors2, objects, thr);
extract_boxes(fm3, qp_zp_scale.qp_zp_3, qp_zp_scale.qp_scale_3, FEATURE_MAP_SIZE3, anchors3, objects, thr);
num_boxes = objects.size();
// filter by overlapping boxes
if (objects.size() > 0) {
std::sort(objects.begin(), objects.end());
for (unsigned int i = 0; i < objects.size(); ++i) {
if (objects[i].confidence <= thr)
continue;
for (unsigned int j = i + 1; j < objects.size(); ++j) {
if (objects[i].class_id == objects[j].class_id && objects[j].confidence >= thr) {
if (iou_calc(objects[i], objects[j]) >= IOU_THRESHOLD) {
objects[j].confidence = 0;
num_boxes -= 1;
}
}
}
}
}
// copy the results
if (num_boxes > 0) {
int box_ptr = 0;
// xt::xarray<int>::shape_type shape({num_boxes, 6});
// xt::xarray<float32_t, xt::layout_type::row_major> results(shape);
// results = (float32_t *)calloc(num_boxes * 6, sizeof(float32_t));
results.resize(num_boxes * 6);
for (const auto &obj: objects) {
if (obj.confidence >= thr) {
/*
results(box_ptr, 0) = obj.ymin / IMAGE_SIZE;
results(box_ptr, 1) = obj.xmin / IMAGE_SIZE;
results(box_ptr, 2) = obj.ymax / IMAGE_SIZE;
results(box_ptr, 3) = obj.xmax / IMAGE_SIZE;
results(box_ptr, 4) = (float32_t)obj.class_id;
results(box_ptr, 5) = obj.confidence;
*/
results[box_ptr*6 + 0] = obj.ymin / IMAGE_SIZE;
results[box_ptr*6 + 1] = obj.xmin / IMAGE_SIZE;
results[box_ptr*6 + 2] = obj.ymax / IMAGE_SIZE;
results[box_ptr*6 + 3] = obj.xmax / IMAGE_SIZE;
results[box_ptr*6 + 4] = (float32_t)obj.class_id;
results[box_ptr*6 + 5] = obj.confidence;
box_ptr += 1;
}
}
// return results;
return num_boxes;
} else {
// return xt::zeros<float32_t>({6});
results.resize(0);
// float32_t results[6] = {0, 0, 0, 0, 0, 0};
return 0;
}
}
/*
Given all parameters this function returns boxes with class and confidence
Inputs:
feature map1: 20x20x255
feature map2: 40x40x255
feature map3: 80x80x255
Outputs:
final boxes for display (Nx6) - ymin, xmin, ymax, xmax, class, conf
*/
size_t get_detections(std::vector<uint8_t> fm1, std::vector<uint8_t> fm2, std::vector<uint8_t> fm3,
// xt::xarray<float32_t> get_detections(std::vector<uint8_t> fm1, std::vector<uint8_t> fm2, std::vector<uint8_t> fm3,
qp_zp_scale_t qp_zp_scale, float32_t thr, std::vector<float32_t> &results) {
int anchors1[] = {116, 90, 156, 198, 373, 326};
int anchors2[] = {30, 61, 62, 45, 59, 119};
int anchors3[] = {10, 13, 16, 30, 33, 23};
return _decode(std::ref(fm1), std::ref(fm2), std::ref(fm3), anchors1, anchors2, anchors3, qp_zp_scale, thr, results);
}
//https://stackoverflow.com/questions/28562401/resize-an-image-to-a-square-but-keep-aspect-ratio-c-opencv
cv::Mat letterbox( const cv::Mat& img, int target_width = 640, int color = 114 )
{
int width = img.cols,
height = img.rows;
cv::Mat square( target_width, target_width, img.type(), cv::Scalar(color, color, color) );
int max_dim = ( width >= height ) ? width : height;
float32_t scale = ( ( float32_t ) target_width ) / max_dim;
cv::Rect roi;
if (width >= height) {
roi.width = target_width;
roi.x = 0;
roi.height = height * scale;
roi.y = ( target_width - roi.height ) / 2;
} else {
roi.y = 0;
roi.height = target_width;
roi.width = width * scale;
roi.x = ( target_width - roi.width ) / 2;
}
cv::resize( img, square( roi ), roi.size() );
return square;
}
typedef cv::Vec<uchar, 12> Vec12b;
cv::Mat yolov5_input_reshape(cv::Mat &input)
{
cv::Mat output( 320, 320, CV_8UC(12) );
int cols = input.cols;
int rows = input.rows;
for (int i = 0; i < cols; i+=2) {
for (int j = 0; j < rows; j+=2) {
Vec12b &output_pixel = output.at<Vec12b>(i/2, j/2);
for (int inner_i=0; inner_i<2; inner_i++) {
for (int inner_j=0; inner_j<2; inner_j++) {
cv::Vec3b &pixel = input.at<cv::Vec3b>(i+inner_i, j+inner_j);
output_pixel.val[(inner_i*2 + inner_j)* 3 + 0] = pixel.val[0];
output_pixel.val[(inner_i*2 + inner_j)* 3 + 1] = pixel.val[1];
output_pixel.val[(inner_i*2 + inner_j)* 3 + 2] = pixel.val[2];
}
}
}
}
return output;
}
cv::Mat yolov5_pre_process(cv::Mat &org_frame)
{
cv::Mat letter = letterbox(org_frame);
cv::imwrite("letter_boxed.jpg", letter);
// cv::Mat output = yolov5_input_reshape(letter);
// size_t shape [] = {320, 320, 12};
// npy::SaveArrayPointerAsNumpy("cpp-prep.npy", false, 3, shape, letter.data);
// cv::Mat output2 = letter.reshape(12/*Channels*/, 320/*Rows*/);
return letter;
}
std::string get_coco_name_from_int(int cls)
{
std::string result = "N/A";
switch(cls) {
case 0: result = "__background__";break;
case 1: result = "person";break;
case 2: result = "bicycle";break;
case 3: result = "car";break;
case 4: result = "motorcycle";break;
case 5: result = "airplane";break;
case 6: result = "bus";break;
case 7: result = "train";break;
case 8: result = "truck";break;
case 9: result = "boat";break;
case 10: result = "traffic light";break;
case 11: result = "fire hydrant";break;
case 12: result = "stop sign";break;
case 13: result = "parking meter";break;
case 14: result = "bench";break;
case 15: result = "bird";break;
case 16: result = "cat";break;
case 17: result = "dog";break;
case 18: result = "horse";break;
case 19: result = "sheep";break;
case 20: result = "cow";break;
case 21: result = "elephant";break;
case 22: result = "bear";break;
case 23: result = "zebra";break;
case 24: result = "giraffe";break;
case 25: result = "backpack";break;
case 26: result = "umbrella";break;
case 27: result = "handbag";break;
case 28: result = "tie";break;
case 29: result = "suitcase";break;
case 30: result = "frisbee";break;
case 31: result = "skis";break;
case 32: result = "snowboard";break;
case 33: result = "sports ball";break;
case 34: result = "kite";break;
case 35: result = "baseball bat";break;
case 36: result = "baseball glove";break;;
case 37: result = "skateboard";break;
case 38: result = "surfboard";break;
case 39: result = "tennis racket";break;
case 40: result = "bottle";break;
case 41: result = "wine glass";break;
case 42: result = "cup";break;
case 43: result = "fork";break;
case 44: result = "knife";break;
case 45: result = "spoon";break;
case 46: result = "bowl";break;
case 47: result = "banana";break;
case 48: result = "apple";break;
case 49: result = "sandwich";break;
case 50: result = "orange";break;
case 51: result = "broccoli";break;
case 52: result = "carrot";break;
case 53: result = "hot dog";break;
case 54: result = "pizza";break;
case 55: result = "donut";break;
case 56: result = "cake";break;
case 57: result = "chair";break;
case 58: result = "couch";break;
case 59: result = "potted plant";break;
case 60: result = "bed";break;
case 61: result = "dining table";break;
case 62: result = "toilet";break;
case 63: result = "tv";break;
case 64: result = "laptop";break;
case 65: result = "mouse";break;
case 66: result = "remote";break;
case 67: result = "keyboard";break;
case 68: result = "cell phone";break;
case 69: result = "microwave";break;
case 70: result = "oven";break;
case 71: result = "toaster";break;
case 72: result = "sink";break;
case 73: result = "refrigerator";break;
case 74: result = "book";break;
case 75: result = "clock";break;
case 76: result = "vase";break;
case 77: result = "scissors";break;
case 78: result = "teddy bear";break;
case 79: result = "hair drier";break;
case 80: result = "toothbrush";break;
}
return result;
}
#endif
#!/usr/bin/env python3
import os
from glob import glob
import time
from multiprocessing import Process
import numpy as np
import argparse as ap
from hailo_platform import HailoUdpControllerObject, HailoPcieObject
from tqdm import trange
from colorama import Fore
from hailo_platform.drivers.hw_object import InferTypesName
from hailo_platform.drivers.hailo_controller.power_measurement import (DvmTypes, PowerMeasurementTypes,
SamplingPeriod, AveragingFactor)
sent_time = 0
def arg_prep():
parser = ap.ArgumentParser()
parser.add_argument('--ip', help='Set the IP of the Hailo device', type=str, default='10.0.0.100')
parser.add_argument('--jlf-dir', help='Point to the dir that contains 4 JLFs (boot, meta_data, config, params)', default='./JLFs')
parser.add_argument('--mode', help='Choose the communication mode [hw-only|full]', type=str, default='full')
parser.add_argument('--iterations', help='How many repeasts on the picture stream (Default:100)', type=int, default=100)
parser.add_argument('--power', help='Enable Power measurement', default=False, action='store_true')
parser.add_argument('--source', help='Specify image or video source', default=None)
args = parser.parse_args()
return args
def get_jlfs(jlf_dir):
jlfs = list()
patterns = list()
for ext in ('mem', 'jlf'):
pat = os.path.join(jlf_dir, '*.{}'.format(ext))
patterns.extend(glob(pat))
for p in patterns:
with open(p, 'rb') as f:
jlfs.append(f.read())
return jlfs
def _initialize_board(remote_ip, jlf_dir, arch='pcie'):
"""Setup initialization function that loads a model to the device."""
print('Initializing hardware object...')
if arch=='udp':
target = HailoUdpControllerObject(remote_ip)
elif arch=='pcie':
target = HailoPcieObject(arch)
else:
print("Error arch given: {}".format(arch))
print('Loading compiled JLFs to device...')
jlfs = get_jlfs(jlf_dir)
target.load_jlfs(jlfs)
return target
def _recv_proc(target, images_count):
target.setup_recv()
outputs_names = target.sorted_output_layer_names
print('-I- Started Receive for {}'.format(images_count))
for i in trange(images_count, desc='-I- Recv...', position=0, bar_format="{l_bar}%s{bar}%s{r_bar}" % (Fore.GREEN, Fore.RESET)):
for outputs_name in outputs_names:
data = target.recv(outputs_name)
def _power_proc(target, time_to_measure_power):
target.control.set_power_measurement(0, DvmTypes.VDD_CORE, PowerMeasurementTypes.POWER)
delay_milliseconds = 1
target.control.start_power_measurement(delay=delay_milliseconds, averaging_factor=AveragingFactor.AVERAGE_64)
print('-I- Measure power for {:.2f} sec, Power measure delay is {}ms'.format(time_to_measure_power, delay_milliseconds))
if (time_to_measure_power<3):
print('-W- time_to_measure_power was update to 3 from {:.3f} sec, since it\'s unreliable to measure power over short times'.format(time_to_measure_power))
time_to_measure_power=3
time.sleep(time_to_measure_power)
measurements = target.control.get_power_measurement(0, DvmTypes.VDD_CORE, PowerMeasurementTypes.POWER)
target.control.stop_power_measurement()
print('-I- Power Avg/Max is {:.3f}/{:.3f} mW'.format(measurements.average, measurements.max_value))
def _run_full_streaming(target, images_count, power):
print('-I- Running full inference...')
p_recv = Process(target=_recv_proc, args=(target, images_count))
power_proccess_started = False
p_power = None
input_conf, output_conf = target.generate_dataflow_configuration()
for outp in output_conf.values():
outp.should_send_sync = True
for inp in input_conf.values():
inp.should_send_sync = False
with target.use_device(translate_input=True, rescale_outputs=True, python_pipeline=False):
p_recv.start()
target.setup_send()
input_shape = target.get_input_shape()[1:]
print('-I- Loading dataset, each image has a shape of {}'.format(input_shape))
dataset_shape = [1] + input_shape
dataset = np.random.random_integers(2, 20, dataset_shape).astype(np.float32)
start_time = time.time()
try:
for image_id in range(images_count):
target.send(dataset)
# out = target.infer(dataset)
# time measure starts when 10% of images have been sent, and ends when 70% were sent
if power and not power_proccess_started and image_id > images_count*0.1:
time_to_measure_power = (time.time()-start_time)*6
p_power = Process(target=_power_proc, args=(target, time_to_measure_power))
p_power.start()
power_proccess_started = True
end_time = time.time()
finally:
if power and p_power:
p_power.join()
p_recv.join()
image_size = int(input_shape[1]*input_shape[2]*input_shape[0])
print('-I----------------------------')
print('-I- Throughput: {:.3f} MB/sec'.format(images_count*image_size*8/((end_time-start_time)*1024*1024)))
print('-I- FPS: {:.3f}'.format(images_count / (end_time-start_time)))
print('-I----------------------------')
def _send_proc(images_count, input_dataflow, data):
for _ in range(images_count):
input_dataflow.send(data)
def _run_hw_only_streaming(target, images_count):
print('-I- Running hw-only inference')
input_conf, output_conf = target.generate_dataflow_configuration()
for outp in output_conf.values():
outp.should_send_sync = True
for inp in input_conf.values():
inp.should_send_sync = False
with target.use_device(InferTypesName.diy, input_dataflow_configuration=input_conf,
output_dataflow_configuration=output_conf, translate_input=True):
input_shape = target.get_input_shape()
dataset_shape = [1] + input_shape[1:]
print('-I- Loading dataset, each image has a shape of {}'.format(input_shape[1:]))
dataset = np.random.randint(2, 20, dataset_shape).astype(np.float32)
(input_dataflows, output_dataflows) = target.get_streams()
input_dataflow = input_dataflows[next(iter(input_dataflows))]
data = input_dataflow.pre_infer(dataset)
p_send = Process(target=_send_proc, args=(images_count, input_dataflow, data))
start_time = time.time()
p_send.start()
try:
for i in trange(images_count, desc='-I- Recv...', position=0, bar_format="{l_bar}%s{bar}%s{r_bar}" % (Fore.GREEN, Fore.RESET)):
for output_dataflow in output_dataflows.values():
r1, r2 = output_dataflow.recv(1)
end_time = time.time()
image_size = int(input_shape[1]*input_shape[2]*input_shape[3])
print('-I----------------------------')
print('-I- Throughput: {:.3f} MB/sec'.format(images_count*image_size*8/((end_time-start_time)*1024*1024)))
print('-I- FPS: {:.3f}'.format(images_count / (end_time-start_time)))
print('-I----------------------------')
finally:
p_send.join()
def streaming_example(remote_ip, streaming_mode, jlf_dir, iterations, power):
"""Streaming example.
Args:
remote_ip (str): Board IP address.
images_count (str): How many images to run.
streaming_mode (:class:`StreamingModes`): Whether to skip pre-infer and post-infer steps on
host (hw-only) or do them (full).
"""
target = _initialize_board(remote_ip, jlf_dir)
if streaming_mode == 'hw-only':
_run_hw_only_streaming(target, iterations)
if streaming_mode == 'full':
_run_full_streaming(target, iterations, power)
if __name__ == '__main__':
args = arg_prep()
streaming_example(remote_ip=args.ip, streaming_mode=args.mode,
jlf_dir=args.jlf_dir, iterations=args.iterations, power=args.power)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment