summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: cea3017)
raw | patch | inline | side by side (parent: cea3017)
author | Ajay Jayaraj <ajayj@ti.com> | |
Fri, 21 Sep 2018 15:53:30 +0000 (10:53 -0500) | ||
committer | Ajay Jayaraj <ajayj@ti.com> | |
Wed, 26 Sep 2018 21:37:31 +0000 (16:37 -0500) |
* Using pybind11 v2.2 to add Python 3 bindings to TIDL API classes/methods
https://pybind11.readthedocs.io/en/stable/index.html
https://github.com/pybind/pybind11/tree/v2.2
* Leveraging the Python buffer protocol to expose input/output buffers
from ExecutionObject/ExecutionObjectPipeline to Python application
code. This eliminates copies between the Python application and the TIDL
API library. (see examples/pybind/one_eo_per_frame.py).
* Methods renamed to follow Python style guide (PEP8)
* Bindings split across multiple pybind_* source files to reduce compile
time
* tidl_api/Makefile builds a shared object - tidl.so. Add this so to
PYTHONPATH to make the tidl module available to the Python interpreter.
>>> import tidl
>>> help (tidl)
* See examples/pybind for examples of using the Python bindings
(MCT-1009)
https://pybind11.readthedocs.io/en/stable/index.html
https://github.com/pybind/pybind11/tree/v2.2
* Leveraging the Python buffer protocol to expose input/output buffers
from ExecutionObject/ExecutionObjectPipeline to Python application
code. This eliminates copies between the Python application and the TIDL
API library. (see examples/pybind/one_eo_per_frame.py).
* Methods renamed to follow Python style guide (PEP8)
* Bindings split across multiple pybind_* source files to reduce compile
time
* tidl_api/Makefile builds a shared object - tidl.so. Add this so to
PYTHONPATH to make the tidl module available to the Python interpreter.
>>> import tidl
>>> help (tidl)
* See examples/pybind for examples of using the Python bindings
(MCT-1009)
15 files changed:
examples/pybind/layer_output.py | [new file with mode: 0755] | patch | blob |
examples/pybind/one_eo_per_frame.py | [new file with mode: 0755] | patch | blob |
examples/pybind/tidl_app_utils.py | [new file with mode: 0755] | patch | blob |
examples/pybind/two_eo_per_frame.py | [new file with mode: 0755] | patch | blob |
makefile | patch | blob | history | |
tidl_api/Makefile | patch | blob | history | |
tidl_api/inc/configuration.h | patch | blob | history | |
tidl_api/make.buildid | patch | blob | history | |
tidl_api/make.inc | patch | blob | history | |
tidl_api/src/pybind_common.h | [new file with mode: 0644] | patch | blob |
tidl_api/src/pybind_configuration.cpp | [new file with mode: 0644] | patch | blob |
tidl_api/src/pybind_eo.cpp | [new file with mode: 0644] | patch | blob |
tidl_api/src/pybind_eop.cpp | [new file with mode: 0644] | patch | blob |
tidl_api/src/pybind_executor.cpp | [new file with mode: 0644] | patch | blob |
tidl_api/src/pybind_helpers.cpp | [new file with mode: 0644] | patch | blob |
diff --git a/examples/pybind/layer_output.py b/examples/pybind/layer_output.py
--- /dev/null
@@ -0,0 +1,113 @@
+#!/usr/bin/python3
+
+# Copyright (c) 2018 Texas Instruments Incorporated - http://www.ti.com/
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Texas Instruments Incorporated nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+
+from tidl import DeviceId, DeviceType, Configuration, Executor, TidlError
+from tidl import allocate_memory, free_memory
+
+from tidl_app_utils import read_frame, write_output, report_time
+
+import argparse
+
+def main(config_file, num_frames):
+ c = Configuration()
+ c.read_from_file(config_file)
+ c.enable_layer_dump = True
+ c.num_frames = num_frames
+
+ num_dsp = Executor.get_num_devices(DeviceType.DSP)
+ num_eve = Executor.get_num_devices(DeviceType.EVE)
+
+ if (num_dsp == 0 and num_eve == 0):
+ print('No TIDL API capable devices available')
+ return
+
+ if (num_eve > 0):
+ device_type = DeviceType.EVE
+ else:
+ device_type = DeviceType.DSP
+
+ # Since we are dumping layer outputs, just run on one device
+ run(device_type, 1, c)
+
+ return
+
+def run(device_type, num_devices, c):
+ """ Run the network on a single device and dump output of each layer"""
+
+ print('Running network on {} {}'.format(num_devices, device_type))
+
+ device_ids = set([DeviceId.ID0])
+
+ try:
+ print('TIDL API: performing one time initialization ...')
+
+ executor = Executor(device_type, device_ids, c, 1)
+
+ # Collect all EOs from EVE and DSP executors
+ eos = []
+ for i in range(executor.get_num_execution_objects()):
+ eos.append(executor.at(i))
+
+ allocate_memory(eos)
+
+ # Open input, output files
+ f_in = open(c.in_data, 'rb')
+
+
+ print('TIDL API: processing input frames ...')
+
+ num_eos = len(eos)
+ for frame_index in range(c.num_frames+num_eos):
+ eo = eos [frame_index % num_eos]
+
+ if (eo.process_frame_wait()):
+ eo.write_layer_outputs_to_file()
+
+ if (read_frame(eo, frame_index, c, f_in)):
+ eo.process_frame_start_async()
+
+
+ f_in.close()
+
+ free_memory(eos)
+ except TidlError as err:
+ print (err)
+
+ return
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description=
+ 'Dump output of each network layer to file. ')
+ parser.add_argument('-c', '--config_file',
+ default='../test/testvecs/config/infer/tidl_config_j11_v2.txt',
+ help='Path to TIDL config file')
+ args = parser.parse_args()
+
+ # Run network for 1 frame since we interested in intermediate layer outputs
+ main(args.config_file, 1)
diff --git a/examples/pybind/one_eo_per_frame.py b/examples/pybind/one_eo_per_frame.py
--- /dev/null
@@ -0,0 +1,126 @@
+#!/usr/bin/python3
+
+# Copyright (c) 2018 Texas Instruments Incorporated - http://www.ti.com/
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Texas Instruments Incorporated nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+
+from tidl import DeviceId, DeviceType, Configuration, Executor, TidlError
+from tidl import allocate_memory, free_memory
+
+from tidl_app_utils import read_frame, write_output, report_time
+
+import argparse
+
+def main(config_file, num_frames):
+ c = Configuration()
+ c.read_from_file(config_file)
+ c.enable_api_trace = False
+ c.num_frames = num_frames
+
+ num_dsp = Executor.get_num_devices(DeviceType.DSP)
+ num_eve = Executor.get_num_devices(DeviceType.EVE)
+
+ if (num_dsp == 0 and num_eve == 0):
+ print('No TIDL API capable devices available')
+ return
+
+ run(num_eve, num_dsp, c)
+
+ return
+
+def run(num_eve, num_dsp, c):
+ """ Run the network on the specified device type and number of devices"""
+
+ print('Running network across {} EVEs, {} DSPs'.format(num_eve, num_dsp))
+
+ dsp_device_ids = set([DeviceId.ID0, DeviceId.ID1,
+ DeviceId.ID2, DeviceId.ID3][0:num_dsp])
+ eve_device_ids = set([DeviceId.ID0, DeviceId.ID1,
+ DeviceId.ID2, DeviceId.ID3][0:num_eve])
+
+ # Heap sizes for this network determined using Configuration.showHeapStats
+ c.param_heap_size = (3 << 20)
+ c.network_heap_size = (20 << 20)
+
+
+ try:
+ print('TIDL API: performing one time initialization ...')
+
+ eve = Executor(DeviceType.EVE, eve_device_ids, c, 1)
+ dsp = Executor(DeviceType.DSP, dsp_device_ids, c, 1)
+
+ # Collect all EOs from EVE and DSP executors
+ eos = []
+ for i in range(eve.get_num_execution_objects()):
+ eos.append(eve.at(i))
+
+ for i in range(dsp.get_num_execution_objects()):
+ eos.append(dsp.at(i))
+
+ allocate_memory(eos)
+
+ # Open input, output files
+ f_in = open(c.in_data, 'rb')
+ f_out = open(c.out_data, 'wb')
+
+
+ print('TIDL API: processing input frames ...')
+
+ num_eos = len(eos)
+ for frame_index in range(c.num_frames+num_eos):
+ eo = eos [frame_index % num_eos]
+
+ if (eo.process_frame_wait()):
+ report_time(eo)
+ write_output(eo, f_out)
+
+ if (read_frame(eo, frame_index, c, f_in)):
+ eo.process_frame_start_async()
+
+
+ f_in.close()
+ f_out.close()
+
+ free_memory(eos)
+ except TidlError as err:
+ print (err)
+
+ return
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description=
+ 'Process frames using all available Execution Objects. '
+ 'Each ExecutionObject processes a single frame')
+ parser.add_argument('-n', '--num_frames',
+ type=int,
+ default=1,
+ help='Number of frames to process')
+ args = parser.parse_args()
+
+ # Heaps are sized for the j11_v2 network. Changing the network will
+ # require updating network_heap_size and param_heap_size
+ main('../test/testvecs/config/infer/tidl_config_j11_v2.txt',
+ args.num_frames)
diff --git a/examples/pybind/tidl_app_utils.py b/examples/pybind/tidl_app_utils.py
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/python3
+
+# Copyright (c) 2018 Texas Instruments Incorporated - http://www.ti.com/
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Texas Instruments Incorporated nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+
+from tidl import DeviceId
+from tidl import DeviceType
+from tidl import Configuration
+from tidl import Executor
+from tidl import TidlError
+
+import tidl
+
+def read_frame(eo, frame_index, c, f):
+ """Read a frame into the ExecutionObject input buffer"""
+
+ if (frame_index >= c.num_frames):
+ return False
+
+ # Read into the EO's input buffer
+ arg_info = eo.get_input_buffer()
+ bytes_read = f.readinto(arg_info)
+
+ if (bytes_read != arg_info.size()):
+ print("Expected {} bytes, read {}".format(size, bytes_read))
+ return False
+
+ if (len(f.peek(1)) == 0):
+ f.seek(0)
+
+ eo.set_frame_index(frame_index)
+
+ return True
+
+def write_output(eo, f):
+ """Write the output buffer to file"""
+
+ arg_info = eo.get_output_buffer()
+ f.write(arg_info)
+
+def report_time(eo):
+ """Report execution time on host and device"""
+
+ elapsed_host = eo.get_host_process_time_in_ms()
+ elapsed_device = eo.get_process_time_in_ms()
+ overhead = elapsed_host - elapsed_device
+
+ # https://pyformat.info/
+ print('frame{:3d}: Time on {}: {:4.2f} ms, host: {:4.2f} ms '
+ 'API overhead: {:2.2f} ms'.format(eo.get_frame_index(),
+ eo.get_device_name(),
+ elapsed_device,
+ elapsed_host,
+ overhead))
diff --git a/examples/pybind/two_eo_per_frame.py b/examples/pybind/two_eo_per_frame.py
--- /dev/null
@@ -0,0 +1,134 @@
+#!/usr/bin/python3
+
+# Copyright (c) 2018 Texas Instruments Incorporated - http://www.ti.com/
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Texas Instruments Incorporated nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+
+from tidl import DeviceId, DeviceType, Configuration, TidlError
+from tidl import Executor, ExecutionObjectPipeline
+from tidl import allocate_memory, free_memory
+
+from tidl_app_utils import read_frame, write_output, report_time
+
+import argparse
+
+def main(config_file, num_frames):
+ c = Configuration()
+ c.read_from_file(config_file)
+ c.enable_api_trace = False
+ c.num_frames = num_frames
+
+ num_dsp = Executor.get_num_devices(DeviceType.DSP)
+ num_eve = Executor.get_num_devices(DeviceType.EVE)
+
+ if (num_dsp == 0 or num_eve == 0):
+ print('This example required EVEs and DSPs.')
+ return
+
+ run(num_eve, num_dsp, c)
+
+ return
+
+def run(num_eve, num_dsp, c):
+ """ Run the network on the specified device type and number of devices"""
+
+ print('Running on {} EVEs, {} DSPs'.format(num_eve, num_dsp))
+
+ dsp_device_ids = set([DeviceId.ID0, DeviceId.ID1,
+ DeviceId.ID2, DeviceId.ID3][0:num_dsp])
+ eve_device_ids = set([DeviceId.ID0, DeviceId.ID1,
+ DeviceId.ID2, DeviceId.ID3][0:num_eve])
+
+ EVE_LAYER_GROUP_ID = 1
+ DSP_LAYER_GROUP_ID = 2
+ c.layer_index_to_layer_group_id = {12:DSP_LAYER_GROUP_ID,
+ 13:DSP_LAYER_GROUP_ID,
+ 14:DSP_LAYER_GROUP_ID};
+
+ # Heap sizes for this network determined using Configuration.showHeapStats
+ c.param_heap_size = (3 << 20)
+ c.network_heap_size = (20 << 20)
+
+
+ try:
+ print('TIDL API: performing one time initialization ...')
+
+ eve = Executor(DeviceType.EVE, eve_device_ids, c, EVE_LAYER_GROUP_ID)
+ dsp = Executor(DeviceType.DSP, dsp_device_ids, c, DSP_LAYER_GROUP_ID)
+
+ num_eve_eos = eve.get_num_execution_objects()
+ num_dsp_eos = dsp.get_num_execution_objects()
+
+ eops = []
+ num_pipe = max(num_eve_eos, num_dsp_eos)
+ for i in range(num_pipe):
+ eops.append(ExecutionObjectPipeline( [ eve.at(i % num_eve_eos),
+ dsp.at(i % num_dsp_eos)]))
+
+ allocate_memory(eops)
+
+ # Open input, output files
+ f_in = open(c.in_data, 'rb')
+ f_out = open(c.out_data, 'wb')
+
+
+ print('TIDL API: processing input frames ...')
+
+ num_eops = len(eops)
+ for frame_index in range(c.num_frames+num_eops):
+ eop = eops [frame_index % num_eops]
+
+ if (eop.process_frame_wait()):
+ report_time(eop)
+ write_output(eop, f_out)
+
+ if (read_frame(eop, frame_index, c, f_in)):
+ eop.process_frame_start_async()
+
+
+ f_in.close()
+ f_out.close()
+
+ free_memory(eops)
+ except TidlError as err:
+ print (err)
+
+ return
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description=
+ 'Process frames using ExecutionObjectPipeline. '
+ 'Each ExecutionObjectPipeline processes a single frame')
+ parser.add_argument('-n', '--num_frames',
+ type=int,
+ default=1,
+ help='Number of frames to process')
+ args = parser.parse_args()
+
+ # Heaps are sized for the j11_v2 network. Changing the network will
+ # require updating network_heap_size and param_heap_size
+ main('../test/testvecs/config/infer/tidl_config_j11_v2.txt',
+ args.num_frames)
diff --git a/makefile b/makefile
index e94e5869ce12a1360de5c214039be59570b69ffd..fec1e200d3f7f80198dd062633c7676c84276ef5 100644 (file)
--- a/makefile
+++ b/makefile
build-viewer:
$(MAKE) TARGET=$(VIEWER_TARGET) -C viewer
+build-python-so:
+ $(MAKE) -C tidl_api tidl.so
+
clean:
$(MAKE) -C tidl_api clean
$(MAKE) -C examples clean
diff --git a/tidl_api/Makefile b/tidl_api/Makefile
index 3fc6a2c1922f86dc09aa5e64d83cf7e0c5873f21..77b5a4b7b80e69c34217eb2029133fcc7f5ea035 100644 (file)
--- a/tidl_api/Makefile
+++ b/tidl_api/Makefile
DSP_SRCFILE = dsp/ocl_wrapper.cl
DSP_OUTFILE = dsp/ocl_wrapper.dsp_h
LIB_IMGUTIL_NAME = tidl_imgutil.a
+PY_LIB_NAME = tidl.so
all: $(LIB_NAME) $(LIB_IMGUTIL_NAME)
SRCS = ocl_device.cpp configuration_parser.cpp configuration.cpp\
executor.cpp execution_object.cpp trace.cpp util.cpp \
- execution_object_pipeline.cpp
+ execution_object_pipeline.cpp
SRCS_IMGUTIL = imgutil.cpp
+SRCS_PYBIND = pybind_eo.cpp pybind_eop.cpp pybind_executor.cpp \
+ pybind_configuration.cpp pybind_helpers.cpp
OBJS = $(SRCS:.cpp=.o)
OBJS_IMGUTIL = $(SRCS_IMGUTIL:.cpp=.o)
+OBJS_PYBIND = $(SRCS_PYBIND:.cpp=.o)
-HOST_SRC_FILES = $(addprefix src/,$(SRCS))
-HOST_OBJ_FILES = $(addprefix obj/,$(OBJS))
-HOST_SRC_IMGUTIL_FILES = $(addprefix src/,$(SRCS_IMGUTIL))
+HOST_OBJ_FILES = $(addprefix obj/,$(OBJS))
HOST_OBJ_IMGUTIL_FILES = $(addprefix obj/,$(OBJS_IMGUTIL))
+HOST_OBJ_PYBIND_FILES = $(addprefix obj/,$(OBJS_PYBIND))
HEADERS = src/common_defines.h src/executor_impl.h src/ocl_device.h
HEADERS += src/parameters.h src/tidl_create_params.h src/trace.h src/util.h
endif
CXXFLAGS += -std=c++11 -Wall -Werror -Wno-error=ignored-attributes
+CXXFLAGS += -fPIC
CXXFLAGS += -I$(TI_OCL_INSTALL)/usr/share/ti/opencl
CXXFLAGS += -I$(TARGET_ROOTDIR)/usr/share/ti/opencl
CXXFLAGS += -Isrc -Iinc
CXXFLAGS += $(BUILD_ID)
+PY_INCLUDE = -I$(TARGET_ROOTDIR)/usr/include/python3.5m -I$(PYBIND11_INC_DIR)
$(DSP_OUTFILE): $(DSP_SRCFILE)
$(MAKE) -C dsp
src/ocl_device.cpp: $(DSP_OUTFILE)
touch $@
+$(HOST_OBJ_PYBIND_FILES): obj/%.o: src/%.cpp $(HEADERS) src/pybind_common.h
+ @mkdir -p obj
+ @echo Compiling pybind $< ...
+ $(CXX) -c $(PY_INCLUDE) $(CXXFLAGS) $< -o $@
+
+
obj/%.o: src/%.cpp $(HEADERS)
@mkdir -p obj
@echo Compiling $< ...
$(LIB_NAME): $(HOST_OBJ_FILES)
$(AR) cr $@ $(HOST_OBJ_FILES)
+$(PY_LIB_NAME): $(HOST_OBJ_PYBIND_FILES) $(LIB_NAME)
+ $(CXX) $(CXXFLAGS) -Wl,-Bsymbolic -shared -lOpenCL -locl_util $^ -o $@
$(LIB_IMGUTIL_NAME): $(HOST_OBJ_IMGUTIL_FILES)
$(AR) cr $@ $(HOST_OBJ_IMGUTIL_FILES)
clean::
$(MAKE) -C dsp clean
- $(RM) -f $(LIB_NAME) $(HOST_OBJ_FILES)
+ $(RM) -f $(LIB_NAME) $(PY_LIB_NAME) $(HOST_OBJ_FILES)
$(RM) -f $(LIB_IMGUTIL_NAME) $(HOST_OBJ_IMGUTIL_FILES)
$(RM) -rf obj
index 531bb6dc2bb9798156a4717d7305f338aeb72e68..1fc033ceb32e7faa40d4ea8d5073c3b4b688aed5 100644 (file)
//! Force to run all layers, regardless of layersGroupId partitioning
bool runFullNet;
+ //! Deprecated, do not use.
//! When set, inputs are taken from TIDL internal buffers that contain
//! outputs of previous layersGroupId, instead of from user application
bool enableInternalInput;
diff --git a/tidl_api/make.buildid b/tidl_api/make.buildid
index b114cc299690fd3c87d3ab393dd05ade30668139..474309c010884744426ea74321c1d807fcf83743 100644 (file)
--- a/tidl_api/make.buildid
+++ b/tidl_api/make.buildid
MAJOR_VER=1
MINOR_VER=2
PATCH_VER=0
-BUILD_VER=0
ifeq ($(shell git rev-parse --short HEAD 2>&1 1>/dev/null; echo $$?),0)
BUILD_SHA?=$(shell git rev-parse --short HEAD)
.PHONY: $(BUILD_ID)
BUILD_ID := -D_BUILD_VER=$(shell echo "" | \
- awk '{ printf ("%02d.%02d.%02d.%02d", $(MAJOR_VER), \
- $(MINOR_VER), $(PATCH_VER), $(BUILD_VER)); }') \
+ awk '{ printf ("%02d.%02d.%02d", $(MAJOR_VER), \
+ $(MINOR_VER), $(PATCH_VER)); }') \
-D_BUILD_SHA=$(BUILD_SHA)
diff --git a/tidl_api/make.inc b/tidl_api/make.inc
index aee34fe37be9e891f908385396d97a5a6fb67a92..e1f221fa710ad8b76322584b8e652c07f11060eb 100644 (file)
--- a/tidl_api/make.inc
+++ b/tidl_api/make.inc
# - TI_OCL_CGT_INSTALL : TI C6x CGT installation directory if not system package
#
# ------------------------------------------------------------------------------
+#
+# PYBIND11_INC_DIR : Path to pybind11 include files used to generate Python
+# bindings for TIDL API. E.g. pybind11.git/include
+#
+# ------------------------------------------------------------------------------
+
+PYBIND11_INC_DIR ?= pybind11/include
ifeq ($(MAKECMDGOALS),clean)
# config not required for clean
diff --git a/tidl_api/src/pybind_common.h b/tidl_api/src/pybind_common.h
--- /dev/null
@@ -0,0 +1,52 @@
+/******************************************************************************
+ * Copyright (c) 2018-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#pragma once
+
+#include <vector>
+#include <sstream>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+#include <pybind11/stl_bind.h>
+
+#include "configuration.h"
+#include "executor.h"
+#include "execution_object.h"
+#include "execution_object_pipeline.h"
+
+using EO = tidl::ExecutionObject;
+using EOP = tidl::ExecutionObjectPipeline;
+
+using std::vector;
+
+using namespace tidl;
+using namespace pybind11;
+
+void init_configuration(module &m);
+void init_eo(module &m);
+void init_eop(module &m);
diff --git a/tidl_api/src/pybind_configuration.cpp b/tidl_api/src/pybind_configuration.cpp
--- /dev/null
@@ -0,0 +1,90 @@
+/******************************************************************************
+ * Copyright (c) 2018-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "pybind_common.h"
+
+void init_configuration(module &m)
+{
+ class_<Configuration>(m, "Configuration")
+ .def(init<>())
+ .def_readwrite("num_frames", &Configuration::numFrames,
+ "Number of frames of input data. Can be 0 if data is\n"
+ "not read from file")
+
+ .def_readwrite("height", &Configuration::inHeight)
+
+ .def_readwrite("width", &Configuration::inWidth)
+
+ .def_readwrite("channels", &Configuration::inNumChannels)
+
+ .def_readwrite("pre_proc_type", &Configuration::preProcType,
+ "Pre-processing type applied to the input frame")
+
+ .def_readwrite("run_full_net", &Configuration::runFullNet,
+ "Force to run all layers, regardless of layersGroupId partitioning")
+
+ .def_readwrite("network_binary", &Configuration::netBinFile,
+ "Path to the TIDL network binary file")
+
+ .def_readwrite("parameter_binary", &Configuration::paramsBinFile,
+ "Path to the TIDL parameter binary file")
+
+ .def_readwrite("network_heap_size", &Configuration::NETWORK_HEAP_SIZE,
+ "Size of the device side network heap\n"
+ "This heap is used for allocating memory required to"
+ "run the network on the device. One per ExecutionObject.")
+
+ .def_readwrite("param_heap_size", &Configuration::PARAM_HEAP_SIZE,
+ "Size of the device side heap used for parameter data.\n"
+ "The size depends on the size of the parameter binary file.\n"
+ "There is one parameter heap for each instance of Executor\n")
+
+ .def_readwrite("enable_api_trace", &Configuration::enableApiTrace,
+ "Debug - Set to True to generate a trace of host/device\n"
+ "function calls")
+
+ .def_readwrite("enable_layer_dump", &Configuration::enableOutputTrace,
+ "Debug - Enable dump of output buffers associated with each layer")
+
+ .def_readwrite("show_heap_stats", &Configuration::showHeapStats,
+ "Debug - Shows total size of PARAM and NETWORK heaps. Also \n"
+ "shows bytes free after all allocations. Used to adjust heap sizes")
+
+ .def_readwrite("layer_index_to_layer_group_id",
+ &Configuration::layerIndex2LayerGroupId,
+ "Map of layer index to layer group id. Used to override \n"
+ "layer group assigment for layers. Any layer not specified\n"
+ "in this map will retain its existing mapping")
+
+ .def_readwrite("in_data", &Configuration::inData)
+
+ .def_readwrite("out_data", &Configuration::outData)
+
+ .def("read_from_file", &Configuration::ReadFromFile,
+ "Read a configuration from the specified file");
+}
diff --git a/tidl_api/src/pybind_eo.cpp b/tidl_api/src/pybind_eo.cpp
--- /dev/null
@@ -0,0 +1,90 @@
+/******************************************************************************
+ * Copyright (c) 2018-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "pybind_common.h"
+
+
+PYBIND11_MAKE_OPAQUE(EO);
+
+// Class, method names follow PEP8, Style Guide for Python Code (Reference #3)
+void init_eo(module &m)
+{
+ class_<EO>(m, "ExecutionObject")
+ .def("get_input_buffer",
+ [](const EO &eo)
+ {
+ ArgInfo ai(eo.GetInputBufferPtr(),
+ eo.GetInputBufferSizeInBytes());
+ return ai;
+ },
+ "Exposes the input buffer in the ExecutionObject as\n"
+ "a Python object using the buffer protocol. This object can\n"
+ "be specified as an argument to the readinto method")
+
+ .def("get_output_buffer",
+ [](const EO &eo)
+ {
+ ArgInfo ai(eo.GetOutputBufferPtr(),
+ eo.GetOutputBufferSizeInBytes());
+ return ai;
+ },
+ "Exposes the output buffer in the ExecutionObject as\n"
+ "a Python object using the buffer protocol. This object can\n"
+ "be specified as an argument to the write method")
+
+ .def("set_frame_index", &EO::SetFrameIndex,
+ "Set the frame index of the frame currently processed.\n"
+ "Used for trace/debug messages")
+
+ .def("get_frame_index", &EO::GetFrameIndex)
+
+ .def("process_frame_start_async", &EO::ProcessFrameStartAsync,
+ "Start processing a frame. The call is asynchronous and\n"
+ "returns immediately")
+
+ .def("process_frame_wait", &EO::ProcessFrameWait,
+ "Wait for the executor pipeline to complete processing a frame\n"
+ "returns false if process_frame_wait() was called without a\n"
+ " corresponding call to process_frame_start_async")
+
+ .def("get_device_name", &EO::GetDeviceName)
+
+ .def("get_host_process_time_in_ms",
+ &EO::GetHostProcessTimeInMilliSeconds,
+ "Milliseconds taken on the host to process a frame")
+
+ .def("get_process_time_in_ms",
+ &EO::GetProcessTimeInMilliSeconds,
+ "Milliseconds taken on the device to process a frame")
+
+ .def("write_layer_outputs_to_file",
+ &EO::WriteLayerOutputsToFile,
+ "Write the output buffer for each layer to a file\n"
+ "<filename_prefix>_<ID>_HxW.bin",
+ arg("filename_prefix")="trace_dump_");
+}
diff --git a/tidl_api/src/pybind_eop.cpp b/tidl_api/src/pybind_eop.cpp
--- /dev/null
@@ -0,0 +1,97 @@
+/******************************************************************************
+ * Copyright (c) 2018-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "pybind_common.h"
+
+// Note: Overloaded methods must be disambiguated by casting them to
+// function pointers. See
+// https://pybind11.readthedocs.io/en/stable/classes.html#overloaded-methods
+void init_eop(module &m)
+{
+ class_<EOP>(m, "ExecutionObjectPipeline")
+ .def(init<std::vector<ExecutionObject *>>())
+
+ .def("get_input_buffer",
+ [](const EOP &eo)
+ {
+ ArgInfo ai(eo.GetInputBufferPtr(),
+ eo.GetInputBufferSizeInBytes());
+ return ai;
+ },
+ "Exposes the input buffer in the ExecutionObjectPipeline as\n"
+ "a Python object using the buffer protocol. This object can\n"
+ "be specified as an argument to the readinto method")
+
+ .def("get_output_buffer",
+ [](const EOP &eo)
+ {
+ ArgInfo ai(eo.GetOutputBufferPtr(),
+ eo.GetOutputBufferSizeInBytes());
+ return ai;
+ },
+ "Exposes the output buffer in the ExecutionObjectPipeline as\n"
+ "a Python object using the buffer protocol. This object can\n"
+ "be specified as an argument to the write method")
+
+ .def("set_frame_index", &EOP::SetFrameIndex,
+ "Set the frame index of the frame currently processed.\n"
+ "Used for trace/debug messages")
+
+ .def("get_frame_index", &EOP::GetFrameIndex)
+
+ .def("process_frame_start_async", &EOP::ProcessFrameStartAsync,
+ "Start processing a frame. The call is asynchronous and\n"
+ "returns immediately")
+
+ .def("process_frame_wait", &EOP::ProcessFrameWait,
+ "Wait for the executor pipeline to complete processing a frame\n"
+ "returns false if process_frame_wait() was called without a\n"
+ " corresponding call to process_frame_start_async")
+
+ .def("get_device_name", &EOP::GetDeviceName)
+
+ .def("get_host_process_time_in_ms",
+ (float (EOP::*)() const) &EOP::GetHostProcessTimeInMilliSeconds,
+ "Milliseconds taken on the host to process a frame")
+
+ .def("get_process_time_in_ms",
+ (float (EOP::*)() const) &EOP::GetProcessTimeInMilliSeconds,
+ "Milliseconds taken on the device to process a frame")
+
+ .def("get_host_process_time_in_ms",
+ (float (EOP::*)(uint32_t) const)
+ &EOP::GetHostProcessTimeInMilliSeconds,
+ "Milliseconds taken on the host to process\n"
+ "a frame by the specified EO")
+
+ .def("get_process_time_in_ms",
+ (float (EOP::*)(uint32_t) const)
+ &EOP::GetProcessTimeInMilliSeconds,
+ "Milliseconds taken on the device to process\n"
+ "a frame by the specified EO");
+}
diff --git a/tidl_api/src/pybind_executor.cpp b/tidl_api/src/pybind_executor.cpp
--- /dev/null
@@ -0,0 +1,128 @@
+/******************************************************************************
+ * Copyright (c) 2018-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+/*! \file pybind_executor.cpp */
+
+// Requires https://github.com/pybind/pybind11, branch v2.2
+// References:
+// 1. https://pybind11.readthedocs.io/en/stable/advanced/functions.html#return-value-policies
+// 2. https://pybind11.readthedocs.io/en/stable/advanced/pycpp/numpy.html#buffer-protocol
+// 3. https://www.python.org/dev/peps/pep-0008/
+
+#include "pybind_common.h"
+
+void AllocateMemory(const vector<ExecutionObject *>& eos);
+void AllocateMemory(const vector<ExecutionObjectPipeline *>& eos);
+void FreeMemory(const vector<ExecutionObject *>& eos);
+void FreeMemory(const vector<ExecutionObjectPipeline *>& eos);
+
+#define STRING(S) XSTRING(S)
+#define XSTRING(S) #S
+
+PYBIND11_MAKE_OPAQUE(EO);
+
+// Class, method names follow PEP8, Style Guide for Python Code (Reference #3)
+PYBIND11_MODULE(tidl, m)
+{
+ m.doc() = std::string("TIDL API Python bindings ") + STRING(_BUILD_VER);
+ m.attr("__version__") = STRING(_BUILD_VER);
+
+ register_exception<Exception>(m, "TidlError");
+
+ enum_<DeviceType>(m, "DeviceType")
+ .value("DSP", DeviceType::DSP)
+ .value("EVE", DeviceType::EVE);
+
+ enum_<DeviceId>(m, "DeviceId")
+ .value("ID0", DeviceId::ID0)
+ .value("ID1", DeviceId::ID1)
+ .value("ID2", DeviceId::ID2)
+ .value("ID3", DeviceId::ID3);
+
+ init_configuration(m);
+ init_eo(m);
+ init_eop(m);
+
+ // For an explanation of return_value_policy, see Reference #1
+ class_<Executor>(m, "Executor")
+ .def(init<DeviceType, std::set<DeviceId>, Configuration, int>())
+
+ .def("get_num_execution_objects", &Executor::GetNumExecutionObjects,
+ "Returns number of ExecutionObjects created by this Executor")
+
+ .def_static("get_num_devices", &Executor::GetNumDevices,
+ "Returns number of devices of the specified type\n"
+ "available for TI DL offload")
+
+ .def_static("get_api_version", &Executor::GetAPIVersion)
+
+ .def("at", &Executor::operator[], return_value_policy::reference,
+ "Returns the ExecutionObject at the specified index");
+
+ // Used to expose the EO's internal input and output buffers to the
+ // python application using the Python buffer protocol (Reference #2)
+ class_<ArgInfo>(m, "ArgInfo", buffer_protocol())
+ .def_buffer([](ArgInfo& ai) -> buffer_info
+ {
+ return buffer_info(
+ ai.ptr(),
+ sizeof(char),
+ pybind11::format_descriptor<char>::format(),
+ 1,
+ {ai.size()},
+ {1}
+ );
+ })
+ .def("size", &ArgInfo::size, "Size of the buffer in bytes")
+ .def("__repr__",
+ [](const ArgInfo& ai)
+ {
+ std::stringstream ss;
+ ss << "<ArgInfo: ptr= " << ai.ptr() << " size= " << ai.size()
+ << ">";
+ return ss.str();
+ });
+
+ // Helper functions to allocate memory from Python
+ m.def("allocate_memory",
+ (void (*)(const vector<EO *>&)) &AllocateMemory,
+ "Allocate input and output buffers for all ExecutionObjects");
+
+ m.def("free_memory",
+ (void (*)(const vector<EO *>&)) &FreeMemory,
+ "Free input and output buffers of all ExecutionObjects");
+
+ m.def("allocate_memory",
+ (void (*)(const vector<EOP *>&)) &AllocateMemory,
+ "Allocate input and output buffers for all ExecutionObjectPipelines");
+
+ m.def("free_memory",
+ (void (*)(const vector<EOP *>&)) &FreeMemory,
+ "Free input and output buffers of all ExecutionObjectPipelines");
+}
+
diff --git a/tidl_api/src/pybind_helpers.cpp b/tidl_api/src/pybind_helpers.cpp
--- /dev/null
@@ -0,0 +1,57 @@
+#include "pybind_common.h"
+
+template<typename T>
+void AllocateMemoryT(const vector<T *>& eos)
+{
+ // Allocate input and output buffers for each execution object
+ for (auto eo : eos)
+ {
+ size_t in_size = eo->GetInputBufferSizeInBytes();
+ size_t out_size = eo->GetOutputBufferSizeInBytes();
+ void* in_ptr = malloc(in_size);
+ void* out_ptr = malloc(out_size);
+ assert(in_ptr != nullptr && out_ptr != nullptr);
+
+ ArgInfo in = { ArgInfo(in_ptr, in_size)};
+ ArgInfo out = { ArgInfo(out_ptr, out_size)};
+ eo->SetInputOutputBuffer(in, out);
+ }
+}
+
+// Allocate input and output memory for each EO
+void AllocateMemory(const vector<ExecutionObject *>& eos)
+{
+ AllocateMemoryT<ExecutionObject>(eos);
+}
+
+// Allocate input and output memory for each EO
+void AllocateMemory(const vector<ExecutionObjectPipeline *>& eos)
+{
+ AllocateMemoryT<ExecutionObjectPipeline>(eos);
+}
+
+
+
+// Free the input and output memory associated with each EO
+template<typename T>
+void FreeMemoryT(const vector<T *>& eos)
+{
+ for (auto eo : eos)
+ {
+ free(eo->GetInputBufferPtr());
+ free(eo->GetOutputBufferPtr());
+ }
+}
+
+void FreeMemory(const vector<ExecutionObject *>& eos)
+{
+ FreeMemoryT<ExecutionObject>(eos);
+}
+
+
+// Free the input and output memory associated with each EO
+void FreeMemory(const vector<ExecutionObjectPipeline *>& eos)
+{
+ FreeMemoryT<ExecutionObjectPipeline>(eos);
+}
+