diff --git a/README.md b/README.md index 05bbb84..e9e64a1 100644 --- a/README.md +++ b/README.md @@ -74,4 +74,4 @@ PYTHON_VACCEL_PLUGIN=./libs/vaccelrt/build/plugins/noop/libvaccel-noop.so LD_LIB # Test coverage PYTHON_VACCEL_PLUGIN=./libs/vaccelrt/build/plugins/noop/libvaccel-noop.so LD_LIBRARY_PATH=./libs/install/lib PYTHONPATH=$PYTHONPATH:. pytest --cov=vaccel tests/ -``` \ No newline at end of file +``` diff --git a/builder.py b/builder.py index 0834885..31aa449 100644 --- a/builder.py +++ b/builder.py @@ -1,21 +1,21 @@ from cffi import FFI -import pathlib -import os + ffibuilder = FFI() ffibuilder.set_source( - "vaccel._vaccel", - r""" + "vaccel._vaccel", + r""" #include #include #include #include #include #include + #include #include """, - libraries=['vaccel-python', 'dl'], + libraries=['vaccel-python', 'dl'], ) # Session API @@ -40,7 +40,7 @@ struct vaccel_resource *resource ); """ -) + ) # TensorFlow model @@ -51,13 +51,19 @@ ...; }; + struct vaccel_tf_saved_model { + struct vaccel_resource *resource; + ...; + }; + int vaccel_tf_model_new(struct vaccel_tf_model *model, const char *path); int vaccel_tf_model_new_from_buffer(struct vaccel_tf_model *model, const uint8_t *buff, size_t size); int vaccel_tf_model_destroy(struct vaccel_tf_model *model); + int vaccel_tf_saved_model_destroy(struct vaccel_tf_saved_model *model); vaccel_id_t vaccel_tf_model_get_id(const struct vaccel_tf_model *model); """ -) + ) # TensorFlow inference ffibuilder.cdef(""" @@ -117,6 +123,7 @@ /* Data type */ enum vaccel_tf_data_type data_type; + ...; }; struct vaccel_tf_status { @@ -127,21 +134,29 @@ const char *message; }; + int vaccel_tf_saved_model_set_path( + struct vaccel_tf_saved_model *model, + const char *path + ); + + int vaccel_tf_session_load( struct vaccel_session *session, struct vaccel_tf_saved_model *model, struct vaccel_tf_status *status ); + int vaccel_tf_saved_model_register(struct vaccel_tf_saved_model *model); + int vaccel_tf_session_run( struct vaccel_session *session, const struct vaccel_tf_saved_model *model, const struct vaccel_tf_buffer *run_options, - const struct vaccel_tf_node *in_nodes, struct vaccel_tf_tensor *const *in, int nr_inputs, + const struct vaccel_tf_node *in_nodes, struct vaccel_tf_tensor *const*in, int nr_inputs, const struct vaccel_tf_node *out_nodes, struct vaccel_tf_tensor **out, int nr_outputs, struct vaccel_tf_status *status ); """ -) + ) # Plugin system ffibuilder.cdef(""" @@ -153,13 +168,13 @@ int register_plugin_function(struct vaccel_op *plugin_op); int register_plugin_functions(struct vaccel_op *plugin_ops, size_t nr_ops); """ -) + ) # Noop API ffibuilder.cdef(""" int vaccel_noop(struct vaccel_session *sess); """ -) + ) # Genop API ffibuilder.cdef(""" @@ -167,48 +182,48 @@ uint32_t size; void *buf; };""" -) + ) ffibuilder.cdef(""" int vaccel_genop(struct vaccel_session *sess, struct vaccel_arg *read, - int nr_read, struct vaccel_arg *write, int nr_write);""" -) + int nr_read, struct vaccel_arg *write, int nr_write);""" + ) # Image API ffibuilder.cdef(""" int vaccel_image_classification(struct vaccel_session *sess, const void *img, - unsigned char *out_text, unsigned char *out_imgname, - size_t len_img, size_t len_out_text, size_t len_out_imgname); + unsigned char *out_text, unsigned char *out_imgname, + size_t len_img, size_t len_out_text, size_t len_out_imgname); """ -) + ) ffibuilder.cdef(""" int vaccel_image_detection(struct vaccel_session *sess, const void *img, - unsigned char *out_imgname, size_t len_img, - size_t len_out_imgname); + unsigned char *out_imgname, size_t len_img, + size_t len_out_imgname); """ -) + ) ffibuilder.cdef(""" int vaccel_image_segmentation(struct vaccel_session *sess, const void *img, - unsigned char *out_imgname, size_t len_img, - size_t len_out_imgname); + unsigned char *out_imgname, size_t len_img, + size_t len_out_imgname); """ -) + ) ffibuilder.cdef(""" int vaccel_image_pose(struct vaccel_session *sess, const void *img, - unsigned char *out_imgname, size_t len_img, - size_t len_out_imgname); + unsigned char *out_imgname, size_t len_img, + size_t len_out_imgname); """ -) + ) ffibuilder.cdef(""" int vaccel_image_depth(struct vaccel_session *sess, const void *img, - unsigned char *out_imgname, size_t len_img, - size_t len_out_imgname); + unsigned char *out_imgname, size_t len_img, + size_t len_out_imgname); """ -) + ) if __name__ == "__main__": ffibuilder.compile(verbose=True) diff --git a/setup.py b/setup.py index f87e250..8ff82b9 100644 --- a/setup.py +++ b/setup.py @@ -1,21 +1,20 @@ from setuptools import setup, find_packages from platform import uname from datestamp import stamp -from cmake_build_extension import BuildExtension, CMakeExtension package = 'vaccel' platform = uname() if platform.system != 'Linux': - _ = f'"(package.title())" only supported to run on Linux' + _ = f'"{package.title()}" only supported to run on Linux' raise RuntimeError(_) -setup(name = 'vaccel', - url = 'https://github.com/nubificus/python-vaccel', - author = 'Nubificus Ltd.', - version = stamp(package), - packages = find_packages(), - description = ('Python bindings with CFFI for libvaccel'), - install_requires = ["cffi>=1.0.0"], - cffi_modules = ["builder.py:ffibuilder"], -) +setup(name='vaccel', + url='https://github.com/nubificus/python-vaccel', + author='Nubificus Ltd.', + version=stamp(package), + packages=find_packages(), + description=('Python bindings with CFFI for libvaccel'), + install_requires=["cffi>=1.0.0"], + cffi_modules=["builder.py:ffibuilder"], + ) diff --git a/tests/test_general.py b/tests/test_general.py index 41daabd..2789867 100644 --- a/tests/test_general.py +++ b/tests/test_general.py @@ -1,25 +1,14 @@ from vaccel.session import Session from vaccel.noop import Noop -from vaccel.genop import Genop, VaccelArg + def test_session(): ses_a = Session(flags=0) ses_b = Session(flags=1) assert ses_a.id() != ses_b.id() + def test_noop(): ses = Session(flags=0) res = Noop.noop(ses) assert res == 0 - -##def test_genop(): -# """ -# should work, but it doesn't because the sanity check on vAccel -# regarding the number of arguments is not correct -# """ -# ses = Session(flags=1) -# arg_read = [] -# arg_read.append(VaccelArg(data=0)) -# arg_write = [] -# res = Genop.genop(ses, arg_read, arg_write) -# assert res == 22 #should this be 22? diff --git a/tests/test_image.py b/tests/test_image.py index c2f2d28..88f6d9e 100644 --- a/tests/test_image.py +++ b/tests/test_image.py @@ -3,30 +3,32 @@ imgsource = "/usr/local/share/images/example.jpg" + def test_image_classify(): - ses = Session(flags=3) - res = ImageClassify.classify_from_filename(session=ses, source=imgsource) - assert res == "This is a dummy classification tag!" + ses = Session(flags=3) + res = ImageClassify.classify_from_filename(session=ses, source=imgsource) + assert res == "This is a dummy classification tag!" def test_image_detect(): - ses = Session(flags=3) - res = ImageDetect.detect_from_filename(session=ses, source=imgsource) - assert res == 0 + ses = Session(flags=3) + res = ImageDetect.detect_from_filename(session=ses, source=imgsource) + assert res == 0 def test_image_segment(): - ses = Session(flags=3) - res = ImageSegment.segment_from_filename(session=ses, source=imgsource) - assert res == 0 + ses = Session(flags=3) + res = ImageSegment.segment_from_filename(session=ses, source=imgsource) + assert res == 0 def test_image_pose(): - ses = Session(flags=3) - res = ImagePose.pose_from_filename(session=ses, source=imgsource) - assert res == 0 # is this supposed to be 95? + ses = Session(flags=3) + res = ImagePose.pose_from_filename(session=ses, source=imgsource) + assert res == 0 + def test_image_depth(): - ses = Session(flags=3) - res = ImageDepth.depth_from_filename(session=ses, source=imgsource) - assert res == 0 # is this supposed to be 95? + ses = Session(flags=3) + res = ImageDepth.depth_from_filename(session=ses, source=imgsource) + assert res == 0 diff --git a/tests/test_image_genop.py b/tests/test_image_genop.py index e182555..3f7a08f 100644 --- a/tests/test_image_genop.py +++ b/tests/test_image_genop.py @@ -2,24 +2,28 @@ imgsource = "/usr/local/share/images/example.jpg" + def test_image_class_genop(): res = genimg.ImageClassify.classify(image=imgsource) assert res == ("This is a dummy classification tag!") + def test_image_detect_genop(): res = genimg.ImageDetect.detect(image=imgsource) assert res == ("") + def test_image_segme_genop(): res = genimg.ImageSegment.segment(image=imgsource) assert res == ("") + def test_image_pose_genop(): res = genimg.ImagePose.pose(image=imgsource) print(res) assert res == ("") + def test_image_depth_genop(): res = genimg.ImageDepth.depth(image=imgsource) assert res == ("") - diff --git a/tests/test_tf.py b/tests/test_tf.py new file mode 100644 index 0000000..ae0dc25 --- /dev/null +++ b/tests/test_tf.py @@ -0,0 +1,37 @@ +from vaccel.session import Session +from vaccel.tensorflow import Tensor, TensorType, Node, TensorFlowModel + + +def test_tf(): + session = Session(flags=0) + a = TensorFlowModel() + + a.model_set_path("/usr/local/share/models/tf/lstm2") + a.model_register() + session.register_resource(a) + a.from_session(session, "/usr/local/share/models/tf/lstm2") + + nname = "serving_default_input_1" + nid = 0 + n1 = Node(nname, nid) + in_nodes = [n1] + + nname = "StatefulPartitionedCall" + nid = 0 + n2 = Node(nname, nid) + out_nodes = [n2] + + t = Tensor([1, 30], TensorType.FLOAT) + t.data = [1.0] * 30 + t.dims = [1, 30] + + in_tensors = [t] # int64_t dims[] = {1, 30}; + + out = a.run(session, in_nodes, in_tensors, out_nodes) + for t in out: + print(t.__str__()) + + offset = t.data + print(offset) + + session.unregister_resource(a) diff --git a/vaccel/__init__.py b/vaccel/__init__.py index 576da5f..99f6a86 100644 --- a/vaccel/__init__.py +++ b/vaccel/__init__.py @@ -1,7 +1,9 @@ __version__ = '2022.11.2' __vaccel__ = '0.1.0' -import os, sys, ctypes +import os +import sys +import ctypes flags = sys.getdlopenflags() diff --git a/vaccel/_vaccel.c b/vaccel/_vaccel.c index 8077bce..bfac9b1 100644 --- a/vaccel/_vaccel.c +++ b/vaccel/_vaccel.c @@ -573,6 +573,7 @@ static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); #include #include #include + #include #include @@ -580,43 +581,43 @@ static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); static void *_cffi_types[] = { /* 0 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_op *) -/* 1 */ _CFFI_OP(_CFFI_OP_POINTER, 82), // struct vaccel_op * +/* 1 */ _CFFI_OP(_CFFI_OP_POINTER, 89), // struct vaccel_op * /* 2 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), /* 3 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_op *, size_t) /* 4 */ _CFFI_OP(_CFFI_OP_NOOP, 1), /* 5 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 28), // size_t /* 6 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), /* 7 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_plugin *) -/* 8 */ _CFFI_OP(_CFFI_OP_POINTER, 83), // struct vaccel_plugin * +/* 8 */ _CFFI_OP(_CFFI_OP_POINTER, 90), // struct vaccel_plugin * /* 9 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), /* 10 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_session *) -/* 11 */ _CFFI_OP(_CFFI_OP_POINTER, 85), // struct vaccel_session * +/* 11 */ _CFFI_OP(_CFFI_OP_POINTER, 92), // struct vaccel_session * /* 12 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), /* 13 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_session *, struct vaccel_arg *, int, struct vaccel_arg *, int) /* 14 */ _CFFI_OP(_CFFI_OP_NOOP, 11), -/* 15 */ _CFFI_OP(_CFFI_OP_POINTER, 81), // struct vaccel_arg * +/* 15 */ _CFFI_OP(_CFFI_OP_POINTER, 88), // struct vaccel_arg * /* 16 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), // int /* 17 */ _CFFI_OP(_CFFI_OP_NOOP, 15), /* 18 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), /* 19 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), /* 20 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_session *, struct vaccel_resource *) /* 21 */ _CFFI_OP(_CFFI_OP_NOOP, 11), -/* 22 */ _CFFI_OP(_CFFI_OP_POINTER, 84), // struct vaccel_resource * +/* 22 */ _CFFI_OP(_CFFI_OP_POINTER, 91), // struct vaccel_resource * /* 23 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), /* 24 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_session *, struct vaccel_tf_saved_model *, struct vaccel_tf_status *) /* 25 */ _CFFI_OP(_CFFI_OP_NOOP, 11), -/* 26 */ _CFFI_OP(_CFFI_OP_POINTER, 89), // struct vaccel_tf_saved_model * -/* 27 */ _CFFI_OP(_CFFI_OP_POINTER, 90), // struct vaccel_tf_status * +/* 26 */ _CFFI_OP(_CFFI_OP_POINTER, 96), // struct vaccel_tf_saved_model * +/* 27 */ _CFFI_OP(_CFFI_OP_POINTER, 97), // struct vaccel_tf_status * /* 28 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), /* 29 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_session *, struct vaccel_tf_saved_model const *, struct vaccel_tf_buffer const *, struct vaccel_tf_node const *, struct vaccel_tf_tensor * const *, int, struct vaccel_tf_node const *, struct vaccel_tf_tensor * *, int, struct vaccel_tf_status *) /* 30 */ _CFFI_OP(_CFFI_OP_NOOP, 11), -/* 31 */ _CFFI_OP(_CFFI_OP_POINTER, 89), // struct vaccel_tf_saved_model const * -/* 32 */ _CFFI_OP(_CFFI_OP_POINTER, 86), // struct vaccel_tf_buffer const * -/* 33 */ _CFFI_OP(_CFFI_OP_POINTER, 88), // struct vaccel_tf_node const * -/* 34 */ _CFFI_OP(_CFFI_OP_POINTER, 91), // struct vaccel_tf_tensor * const * +/* 31 */ _CFFI_OP(_CFFI_OP_POINTER, 96), // struct vaccel_tf_saved_model const * +/* 32 */ _CFFI_OP(_CFFI_OP_POINTER, 93), // struct vaccel_tf_buffer const * +/* 33 */ _CFFI_OP(_CFFI_OP_POINTER, 95), // struct vaccel_tf_node const * +/* 34 */ _CFFI_OP(_CFFI_OP_POINTER, 98), // struct vaccel_tf_tensor * const * /* 35 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), /* 36 */ _CFFI_OP(_CFFI_OP_NOOP, 33), -/* 37 */ _CFFI_OP(_CFFI_OP_POINTER, 91), // struct vaccel_tf_tensor * * +/* 37 */ _CFFI_OP(_CFFI_OP_POINTER, 98), // struct vaccel_tf_tensor * * /* 38 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), /* 39 */ _CFFI_OP(_CFFI_OP_NOOP, 27), /* 40 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), @@ -626,8 +627,8 @@ static void *_cffi_types[] = { /* 44 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), /* 45 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_session *, void const *, unsigned char *, size_t, size_t) /* 46 */ _CFFI_OP(_CFFI_OP_NOOP, 11), -/* 47 */ _CFFI_OP(_CFFI_OP_POINTER, 97), // void const * -/* 48 */ _CFFI_OP(_CFFI_OP_POINTER, 94), // unsigned char * +/* 47 */ _CFFI_OP(_CFFI_OP_POINTER, 104), // void const * +/* 48 */ _CFFI_OP(_CFFI_OP_POINTER, 101), // unsigned char * /* 49 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 28), /* 50 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 28), /* 51 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), @@ -641,44 +642,51 @@ static void *_cffi_types[] = { /* 59 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 28), /* 60 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), /* 61 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_tf_model *) -/* 62 */ _CFFI_OP(_CFFI_OP_POINTER, 87), // struct vaccel_tf_model * +/* 62 */ _CFFI_OP(_CFFI_OP_POINTER, 94), // struct vaccel_tf_model * /* 63 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), /* 64 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_tf_model *, char const *) /* 65 */ _CFFI_OP(_CFFI_OP_NOOP, 62), -/* 66 */ _CFFI_OP(_CFFI_OP_POINTER, 77), // char const * +/* 66 */ _CFFI_OP(_CFFI_OP_POINTER, 84), // char const * /* 67 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), /* 68 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_tf_model *, uint8_t const *, size_t) /* 69 */ _CFFI_OP(_CFFI_OP_NOOP, 62), -/* 70 */ _CFFI_OP(_CFFI_OP_POINTER, 93), // uint8_t const * +/* 70 */ _CFFI_OP(_CFFI_OP_POINTER, 100), // uint8_t const * /* 71 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 28), /* 72 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 73 */ _CFFI_OP(_CFFI_OP_FUNCTION, 95), // vaccel_id_t()(struct vaccel_tf_model const *) -/* 74 */ _CFFI_OP(_CFFI_OP_POINTER, 87), // struct vaccel_tf_model const * +/* 73 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_tf_saved_model *) +/* 74 */ _CFFI_OP(_CFFI_OP_NOOP, 26), /* 75 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 76 */ _CFFI_OP(_CFFI_OP_POINTER, 77), // char * -/* 77 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 2), // char -/* 78 */ _CFFI_OP(_CFFI_OP_ENUM, 0), // enum vaccel_tf_data_type -/* 79 */ _CFFI_OP(_CFFI_OP_POINTER, 80), // int64_t * -/* 80 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 23), // int64_t -/* 81 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 0), // struct vaccel_arg -/* 82 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 1), // struct vaccel_op -/* 83 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 2), // struct vaccel_plugin -/* 84 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 3), // struct vaccel_resource -/* 85 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 4), // struct vaccel_session -/* 86 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 5), // struct vaccel_tf_buffer -/* 87 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 6), // struct vaccel_tf_model -/* 88 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 7), // struct vaccel_tf_node -/* 89 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 8), // struct vaccel_tf_saved_model -/* 90 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 9), // struct vaccel_tf_status -/* 91 */ _CFFI_OP(_CFFI_OP_POINTER, 92), // struct vaccel_tf_tensor * -/* 92 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 10), // struct vaccel_tf_tensor -/* 93 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 18), // uint8_t -/* 94 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 4), // unsigned char -/* 95 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, _cffi_prim_int(sizeof(vaccel_id_t), ( +/* 76 */ _CFFI_OP(_CFFI_OP_FUNCTION, 16), // int()(struct vaccel_tf_saved_model *, char const *) +/* 77 */ _CFFI_OP(_CFFI_OP_NOOP, 26), +/* 78 */ _CFFI_OP(_CFFI_OP_NOOP, 66), +/* 79 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 80 */ _CFFI_OP(_CFFI_OP_FUNCTION, 102), // vaccel_id_t()(struct vaccel_tf_model const *) +/* 81 */ _CFFI_OP(_CFFI_OP_POINTER, 94), // struct vaccel_tf_model const * +/* 82 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 83 */ _CFFI_OP(_CFFI_OP_POINTER, 84), // char * +/* 84 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 2), // char +/* 85 */ _CFFI_OP(_CFFI_OP_ENUM, 0), // enum vaccel_tf_data_type +/* 86 */ _CFFI_OP(_CFFI_OP_POINTER, 87), // int64_t * +/* 87 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 23), // int64_t +/* 88 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 0), // struct vaccel_arg +/* 89 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 1), // struct vaccel_op +/* 90 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 2), // struct vaccel_plugin +/* 91 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 3), // struct vaccel_resource +/* 92 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 4), // struct vaccel_session +/* 93 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 5), // struct vaccel_tf_buffer +/* 94 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 6), // struct vaccel_tf_model +/* 95 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 7), // struct vaccel_tf_node +/* 96 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 8), // struct vaccel_tf_saved_model +/* 97 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 9), // struct vaccel_tf_status +/* 98 */ _CFFI_OP(_CFFI_OP_POINTER, 99), // struct vaccel_tf_tensor * +/* 99 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 10), // struct vaccel_tf_tensor +/* 100 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 18), // uint8_t +/* 101 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 4), // unsigned char +/* 102 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, _cffi_prim_int(sizeof(vaccel_id_t), ( ((vaccel_id_t)-1) | 0 /* check that vaccel_id_t is an integer type */ ) <= 0)), // vaccel_id_t -/* 96 */ _CFFI_OP(_CFFI_OP_POINTER, 97), // void * -/* 97 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 0), // void +/* 103 */ _CFFI_OP(_CFFI_OP_POINTER, 104), // void * +/* 104 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 0), // void }; static int _cffi_const_VACCEL_TF_FLOAT(unsigned long long *o) @@ -1820,10 +1828,10 @@ _cffi_f_vaccel_tf_model_get_id(PyObject *self, PyObject *arg0) PyObject *pyresult; datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(74), arg0, (char **)&x0); + _cffi_type(81), arg0, (char **)&x0); if (datasize != 0) { x0 = ((size_t)datasize) <= 640 ? (struct vaccel_tf_model const *)alloca((size_t)datasize) : NULL; - if (_cffi_convert_array_argument(_cffi_type(74), arg0, (char **)&x0, + if (_cffi_convert_array_argument(_cffi_type(81), arg0, (char **)&x0, datasize, &large_args_free) < 0) return NULL; } @@ -1955,6 +1963,135 @@ _cffi_f_vaccel_tf_model_new_from_buffer(PyObject *self, PyObject *args) # define _cffi_f_vaccel_tf_model_new_from_buffer _cffi_d_vaccel_tf_model_new_from_buffer #endif +static int _cffi_d_vaccel_tf_saved_model_destroy(struct vaccel_tf_saved_model * x0) +{ + return vaccel_tf_saved_model_destroy(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_vaccel_tf_saved_model_destroy(PyObject *self, PyObject *arg0) +{ + struct vaccel_tf_saved_model * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(26), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (struct vaccel_tf_saved_model *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(26), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = vaccel_tf_saved_model_destroy(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_vaccel_tf_saved_model_destroy _cffi_d_vaccel_tf_saved_model_destroy +#endif + +static int _cffi_d_vaccel_tf_saved_model_register(struct vaccel_tf_saved_model * x0) +{ + return vaccel_tf_saved_model_register(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_vaccel_tf_saved_model_register(PyObject *self, PyObject *arg0) +{ + struct vaccel_tf_saved_model * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(26), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (struct vaccel_tf_saved_model *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(26), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = vaccel_tf_saved_model_register(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_vaccel_tf_saved_model_register _cffi_d_vaccel_tf_saved_model_register +#endif + +static int _cffi_d_vaccel_tf_saved_model_set_path(struct vaccel_tf_saved_model * x0, char const * x1) +{ + return vaccel_tf_saved_model_set_path(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_vaccel_tf_saved_model_set_path(PyObject *self, PyObject *args) +{ + struct vaccel_tf_saved_model * x0; + char const * x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "vaccel_tf_saved_model_set_path", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(26), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (struct vaccel_tf_saved_model *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(26), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(66), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (char const *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(66), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = vaccel_tf_saved_model_set_path(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_vaccel_tf_saved_model_set_path _cffi_d_vaccel_tf_saved_model_set_path +#endif + static int _cffi_d_vaccel_tf_session_load(struct vaccel_session * x0, struct vaccel_tf_saved_model * x1, struct vaccel_tf_status * x2) { return vaccel_tf_session_load(x0, x1, x2); @@ -2214,6 +2351,15 @@ static void _cffi_checkfld_struct_vaccel_tf_node(struct vaccel_tf_node *p) } struct _cffi_align_struct_vaccel_tf_node { char x; struct vaccel_tf_node y; }; +_CFFI_UNUSED_FN +static void _cffi_checkfld_struct_vaccel_tf_saved_model(struct vaccel_tf_saved_model *p) +{ + /* only to generate compile-time warnings or errors */ + (void)p; + { struct vaccel_resource * *tmp = &p->resource; (void)tmp; } +} +struct _cffi_align_struct_vaccel_tf_saved_model { char x; struct vaccel_tf_saved_model y; }; + _CFFI_UNUSED_FN static void _cffi_checkfld_struct_vaccel_tf_status(struct vaccel_tf_status *p) { @@ -2279,9 +2425,12 @@ static const struct _cffi_global_s _cffi_globals[] = { { "vaccel_sess_register", (void *)_cffi_f_vaccel_sess_register, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 20), (void *)_cffi_d_vaccel_sess_register }, { "vaccel_sess_unregister", (void *)_cffi_f_vaccel_sess_unregister, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 20), (void *)_cffi_d_vaccel_sess_unregister }, { "vaccel_tf_model_destroy", (void *)_cffi_f_vaccel_tf_model_destroy, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 61), (void *)_cffi_d_vaccel_tf_model_destroy }, - { "vaccel_tf_model_get_id", (void *)_cffi_f_vaccel_tf_model_get_id, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 73), (void *)_cffi_d_vaccel_tf_model_get_id }, + { "vaccel_tf_model_get_id", (void *)_cffi_f_vaccel_tf_model_get_id, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 80), (void *)_cffi_d_vaccel_tf_model_get_id }, { "vaccel_tf_model_new", (void *)_cffi_f_vaccel_tf_model_new, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 64), (void *)_cffi_d_vaccel_tf_model_new }, { "vaccel_tf_model_new_from_buffer", (void *)_cffi_f_vaccel_tf_model_new_from_buffer, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 68), (void *)_cffi_d_vaccel_tf_model_new_from_buffer }, + { "vaccel_tf_saved_model_destroy", (void *)_cffi_f_vaccel_tf_saved_model_destroy, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 73), (void *)_cffi_d_vaccel_tf_saved_model_destroy }, + { "vaccel_tf_saved_model_register", (void *)_cffi_f_vaccel_tf_saved_model_register, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 73), (void *)_cffi_d_vaccel_tf_saved_model_register }, + { "vaccel_tf_saved_model_set_path", (void *)_cffi_f_vaccel_tf_saved_model_set_path, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 76), (void *)_cffi_d_vaccel_tf_saved_model_set_path }, { "vaccel_tf_session_load", (void *)_cffi_f_vaccel_tf_session_load, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 24), (void *)_cffi_d_vaccel_tf_session_load }, { "vaccel_tf_session_run", (void *)_cffi_f_vaccel_tf_session_run, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 29), (void *)_cffi_d_vaccel_tf_session_run }, }; @@ -2292,13 +2441,13 @@ static const struct _cffi_field_s _cffi_fields[] = { _CFFI_OP(_CFFI_OP_NOOP, 43) }, { "buf", offsetof(struct vaccel_arg, buf), sizeof(((struct vaccel_arg *)0)->buf), - _CFFI_OP(_CFFI_OP_NOOP, 96) }, + _CFFI_OP(_CFFI_OP_NOOP, 103) }, { "session_id", offsetof(struct vaccel_session, session_id), sizeof(((struct vaccel_session *)0)->session_id), _CFFI_OP(_CFFI_OP_NOOP, 43) }, { "data", offsetof(struct vaccel_tf_buffer, data), sizeof(((struct vaccel_tf_buffer *)0)->data), - _CFFI_OP(_CFFI_OP_NOOP, 96) }, + _CFFI_OP(_CFFI_OP_NOOP, 103) }, { "size", offsetof(struct vaccel_tf_buffer, size), sizeof(((struct vaccel_tf_buffer *)0)->size), _CFFI_OP(_CFFI_OP_NOOP, 5) }, @@ -2307,19 +2456,22 @@ static const struct _cffi_field_s _cffi_fields[] = { _CFFI_OP(_CFFI_OP_NOOP, 22) }, { "name", offsetof(struct vaccel_tf_node, name), sizeof(((struct vaccel_tf_node *)0)->name), - _CFFI_OP(_CFFI_OP_NOOP, 76) }, + _CFFI_OP(_CFFI_OP_NOOP, 83) }, { "id", offsetof(struct vaccel_tf_node, id), sizeof(((struct vaccel_tf_node *)0)->id), - _CFFI_OP(_CFFI_OP_NOOP, 80) }, + _CFFI_OP(_CFFI_OP_NOOP, 87) }, + { "resource", offsetof(struct vaccel_tf_saved_model, resource), + sizeof(((struct vaccel_tf_saved_model *)0)->resource), + _CFFI_OP(_CFFI_OP_NOOP, 22) }, { "error_code", offsetof(struct vaccel_tf_status, error_code), sizeof(((struct vaccel_tf_status *)0)->error_code), - _CFFI_OP(_CFFI_OP_NOOP, 93) }, + _CFFI_OP(_CFFI_OP_NOOP, 100) }, { "message", offsetof(struct vaccel_tf_status, message), sizeof(((struct vaccel_tf_status *)0)->message), _CFFI_OP(_CFFI_OP_NOOP, 66) }, { "data", offsetof(struct vaccel_tf_tensor, data), sizeof(((struct vaccel_tf_tensor *)0)->data), - _CFFI_OP(_CFFI_OP_NOOP, 96) }, + _CFFI_OP(_CFFI_OP_NOOP, 103) }, { "size", offsetof(struct vaccel_tf_tensor, size), sizeof(((struct vaccel_tf_tensor *)0)->size), _CFFI_OP(_CFFI_OP_NOOP, 5) }, @@ -2328,44 +2480,44 @@ static const struct _cffi_field_s _cffi_fields[] = { _CFFI_OP(_CFFI_OP_NOOP, 16) }, { "dims", offsetof(struct vaccel_tf_tensor, dims), sizeof(((struct vaccel_tf_tensor *)0)->dims), - _CFFI_OP(_CFFI_OP_NOOP, 79) }, + _CFFI_OP(_CFFI_OP_NOOP, 86) }, { "data_type", offsetof(struct vaccel_tf_tensor, data_type), sizeof(((struct vaccel_tf_tensor *)0)->data_type), - _CFFI_OP(_CFFI_OP_NOOP, 78) }, + _CFFI_OP(_CFFI_OP_NOOP, 85) }, }; static const struct _cffi_struct_union_s _cffi_struct_unions[] = { - { "vaccel_arg", 81, _CFFI_F_CHECK_FIELDS, + { "vaccel_arg", 88, _CFFI_F_CHECK_FIELDS, sizeof(struct vaccel_arg), offsetof(struct _cffi_align_struct_vaccel_arg, y), 0, 2 }, - { "vaccel_op", 82, 0, + { "vaccel_op", 89, 0, sizeof(struct vaccel_op), offsetof(struct _cffi_align_struct_vaccel_op, y), 2, 0 }, - { "vaccel_plugin", 83, 0, + { "vaccel_plugin", 90, 0, sizeof(struct vaccel_plugin), offsetof(struct _cffi_align_struct_vaccel_plugin, y), 2, 0 }, - { "vaccel_resource", 84, _CFFI_F_OPAQUE, + { "vaccel_resource", 91, _CFFI_F_OPAQUE, (size_t)-1, -1, -1, 0 /* opaque */ }, - { "vaccel_session", 85, 0, + { "vaccel_session", 92, 0, sizeof(struct vaccel_session), offsetof(struct _cffi_align_struct_vaccel_session, y), 2, 1 }, - { "vaccel_tf_buffer", 86, _CFFI_F_CHECK_FIELDS, + { "vaccel_tf_buffer", 93, _CFFI_F_CHECK_FIELDS, sizeof(struct vaccel_tf_buffer), offsetof(struct _cffi_align_struct_vaccel_tf_buffer, y), 3, 2 }, - { "vaccel_tf_model", 87, 0, + { "vaccel_tf_model", 94, 0, sizeof(struct vaccel_tf_model), offsetof(struct _cffi_align_struct_vaccel_tf_model, y), 5, 1 }, - { "vaccel_tf_node", 88, _CFFI_F_CHECK_FIELDS, + { "vaccel_tf_node", 95, _CFFI_F_CHECK_FIELDS, sizeof(struct vaccel_tf_node), offsetof(struct _cffi_align_struct_vaccel_tf_node, y), 6, 2 }, - { "vaccel_tf_saved_model", 89, _CFFI_F_OPAQUE, - (size_t)-1, -1, -1, 0 /* opaque */ }, - { "vaccel_tf_status", 90, _CFFI_F_CHECK_FIELDS, - sizeof(struct vaccel_tf_status), offsetof(struct _cffi_align_struct_vaccel_tf_status, y), 8, 2 }, - { "vaccel_tf_tensor", 92, _CFFI_F_CHECK_FIELDS, - sizeof(struct vaccel_tf_tensor), offsetof(struct _cffi_align_struct_vaccel_tf_tensor, y), 10, 5 }, + { "vaccel_tf_saved_model", 96, 0, + sizeof(struct vaccel_tf_saved_model), offsetof(struct _cffi_align_struct_vaccel_tf_saved_model, y), 8, 1 }, + { "vaccel_tf_status", 97, _CFFI_F_CHECK_FIELDS, + sizeof(struct vaccel_tf_status), offsetof(struct _cffi_align_struct_vaccel_tf_status, y), 9, 2 }, + { "vaccel_tf_tensor", 99, 0, + sizeof(struct vaccel_tf_tensor), offsetof(struct _cffi_align_struct_vaccel_tf_tensor, y), 11, 5 }, }; static const struct _cffi_enum_s _cffi_enums[] = { - { "vaccel_tf_data_type", 78, _cffi_prim_int(sizeof(enum vaccel_tf_data_type), ((enum vaccel_tf_data_type)-1) <= 0), + { "vaccel_tf_data_type", 85, _cffi_prim_int(sizeof(enum vaccel_tf_data_type), ((enum vaccel_tf_data_type)-1) <= 0), "VACCEL_TF_FLOAT,VACCEL_TF_DOUBLE,VACCEL_TF_INT32,VACCEL_TF_UINT8,VACCEL_TF_INT16,VACCEL_TF_INT8,VACCEL_TF_STRING,VACCEL_TF_COMPLEX64,VACCEL_TF_COMPLEX,VACCEL_TF_INT64,VACCEL_TF_BOOL,VACCEL_TF_QINT8,VACCEL_TF_QUINT8,VACCEL_TF_QINT32,VACCEL_TF_BFLOAT16,VACCEL_TF_QINT16,VACCEL_TF_QUINT16,VACCEL_TF_UINT16,VACCEL_TF_COMPLEX128,VACCEL_TF_HALF,VACCEL_TF_RESOURCE,VACCEL_TF_VARIANT,VACCEL_TF_UINT32,VACCEL_TF_UINT64" }, }; static const struct _cffi_typename_s _cffi_typenames[] = { - { "vaccel_id_t", 95 }, + { "vaccel_id_t", 102 }, }; static const struct _cffi_type_context_s _cffi_type_context = { @@ -2375,12 +2527,12 @@ static const struct _cffi_type_context_s _cffi_type_context = { _cffi_struct_unions, _cffi_enums, _cffi_typenames, - 46, /* num_globals */ + 49, /* num_globals */ 11, /* num_struct_unions */ 1, /* num_enums */ 1, /* num_typenames */ NULL, /* no includes */ - 98, /* num_types */ + 105, /* num_types */ 0, /* flags */ }; diff --git a/vaccel/error.py b/vaccel/error.py index 92e9ce4..078a591 100644 --- a/vaccel/error.py +++ b/vaccel/error.py @@ -1,5 +1,6 @@ import errno + class VaccelError(RuntimeError): """Exception raised when a vAccel runtime error occurs""" @@ -9,4 +10,3 @@ def __init__(self, err_val, message): def __str__(self): return "[errno {}] {}: {}".format(self.error, errno.errorcode[self.error], self.message) - diff --git a/vaccel/genop.py b/vaccel/genop.py index 9cb7c0c..b5cd781 100644 --- a/vaccel/genop.py +++ b/vaccel/genop.py @@ -1,6 +1,5 @@ from enum import Enum from vaccel._vaccel import lib, ffi -from vaccel.error import VaccelError from vaccel.session import Session from typing import List @@ -72,8 +71,8 @@ def __init__(self, datatype="", datasize="") -> None: self.datatype = datatype self.datasize = datasize - @classmethod - def from_vaccel_arg(cls, arg: VaccelArg): + @staticmethod + def detect_datatype(arg: VaccelArg) -> str: datatype = "void" if isinstance(arg.buf, int): datatype = "int" @@ -85,19 +84,24 @@ def from_vaccel_arg(cls, arg: VaccelArg): datatype = "bytes" if "cdata" in str(arg.buf).lower(): datatype = "cdata" + return datatype + + @classmethod + def from_vaccel_arg(cls, arg: VaccelArg): + datatype = VaccelArgInfo.detect_datatype(arg) if datatype == "int": - temp = ffi.new(f"int *", arg.buf) + temp = ffi.new("int *", arg.buf) if datatype == "char []": - temp = ffi.new(f"char []", bytes(arg.buf, encoding="utf-8")) + temp = ffi.new("char []", bytes(arg.buf, encoding="utf-8")) if datatype == "float": - temp = ffi.new(f"float *", arg.buf) + temp = ffi.new("float *", arg.buf) if datatype == "cdata": temp = arg.buf if datatype == "bytes": temp = ffi.from_buffer(arg.buf) if datatype == "void": - temp1 = ffi.new(f"char []", bytes(arg.buf, encoding="utf-8")) + temp1 = ffi.new("char []", bytes(arg.buf, encoding="utf-8")) temp = ffi.cast(temp1) datasize = ffi.sizeof(temp) return cls(datatype=datatype, datasize=datasize) @@ -141,8 +145,8 @@ def genop(self, session: Session, arg_read: List[VaccelArg], arg_write: List[Vac vaccel_args_write = VaccelArgList(arg_write).to_cffi() ret = lib.vaccel_genop(csession, vaccel_args_read, nr_read, - vaccel_args_write, nr_write) - #if ret != 0: + vaccel_args_write, nr_write) + # if ret != 0: # raise VaccelError(ret, "Could not execute generic operation") return ret diff --git a/vaccel/image.py b/vaccel/image.py index 6429072..08efc66 100644 --- a/vaccel/image.py +++ b/vaccel/image.py @@ -3,9 +3,6 @@ from vaccel.session import Session from typing import List -import cffi -ffi = cffi.FFI() - class ImageClassify: """An ImageClassify model vAccel resource""" @@ -25,7 +22,7 @@ def __classify__(self, session: Session, data: List[int]) -> str: """Execute image classification operation""" csession = session._to_inner() - img = ffi.cast("const void *",data) + img = ffi.cast("const void *", data) out_text = ffi.new(f"unsigned char[{self.out_size}]") @@ -35,9 +32,11 @@ def __classify__(self, session: Session, data: List[int]) -> str: len_out_text = self.out_size len_out_imgname = 0 - ret = lib.vaccel_image_classification(csession, img, out_text, out_imgname, len_img, len_out_text, len_out_imgname) + ret = lib.vaccel_image_classification( + csession, img, out_text, out_imgname, len_img, len_out_text, len_out_imgname) if ret != 0: - raise VaccelError(ret, "Could not execute image classification operation") + raise VaccelError( + ret, "Could not execute image classification operation") out_res = "".join([chr(i) for i in out_text]).rstrip('\x00') @@ -67,25 +66,27 @@ def __del__(self): print("test del") @classmethod - def __detect__(self, session:Session, data: List[int]) -> str : + def __detect__(self, session: Session, data: List[int]) -> str: """Execute image detection operation""" csession = session._to_inner() - img = ffi.cast("const void *",data) + img = ffi.cast("const void *", data) out_imagename = ffi.NULL len_img = len(data) len_out_imagename = 0 - ret = lib.vaccel_image_detection(csession, img, out_imagename, len_img, len_out_imagename) + ret = lib.vaccel_image_detection( + csession, img, out_imagename, len_img, len_out_imagename) if ret != 0: - raise VaccelError(ret, "Could not execute image detection operation") + raise VaccelError( + ret, "Could not execute image detection operation") return ret @classmethod - def detect_from_filename(self, session:Session, source: str) -> str : + def detect_from_filename(self, session: Session, source: str) -> str: """Initialize an ImageDetect model by loading image from filename""" with open(source, "rb") as imgfile: data = imgfile.read() @@ -108,25 +109,27 @@ def __del__(self): print("test del") @classmethod - def __segment__(self, session:Session, data: List[int]) -> str : + def __segment__(self, session: Session, data: List[int]) -> str: """Execute image segmentation operation""" csession = session._to_inner() - img = ffi.cast("const void *",data) + img = ffi.cast("const void *", data) out_imagename = ffi.NULL len_img = len(data) len_out_imagename = 0 - ret = lib.vaccel_image_segmentation(csession, img, out_imagename, len_img, len_out_imagename) + ret = lib.vaccel_image_segmentation( + csession, img, out_imagename, len_img, len_out_imagename) if ret != 0: - raise VaccelError(ret, "Could not execute image segmentation operation") + raise VaccelError( + ret, "Could not execute image segmentation operation") return ret @classmethod - def segment_from_filename(self, session:Session, source: str) -> str : + def segment_from_filename(self, session: Session, source: str) -> str: """Initialize an ImageSegment model by loading image from filename""" with open(source, "rb") as imgfile: data = imgfile.read() @@ -149,25 +152,26 @@ def __del__(self): print("test del") @classmethod - def __pose__(self, session:Session, data: List[int]) -> str : + def __pose__(self, session: Session, data: List[int]) -> str: """Execute image pose operation""" csession = session._to_inner() - img = ffi.cast("const void *",data) + img = ffi.cast("const void *", data) out_imagename = ffi.NULL len_img = len(data) len_out_imagename = 0 - ret = lib.vaccel_image_pose(csession, img, out_imagename, len_img, len_out_imagename) + ret = lib.vaccel_image_pose( + csession, img, out_imagename, len_img, len_out_imagename) if ret != 0: raise VaccelError(ret, "Could not execute image pose operation") return ret @classmethod - def pose_from_filename(self, session:Session, source: str) -> str : + def pose_from_filename(self, session: Session, source: str) -> str: """Initialize an ImagePose model by loading image from filename""" with open(source, "rb") as imgfile: data = imgfile.read() @@ -190,25 +194,26 @@ def __del__(self): print("test del") @classmethod - def __depth__(self, session:Session, data: List[int]) -> str : + def __depth__(self, session: Session, data: List[int]) -> str: """Execute image depth operation""" csession = session._to_inner() - img = ffi.cast("const void *",data) + img = ffi.cast("const void *", data) out_imagename = ffi.NULL len_img = len(data) len_out_imagename = 0 - ret = lib.vaccel_image_depth(csession, img, out_imagename, len_img, len_out_imagename) + ret = lib.vaccel_image_depth( + csession, img, out_imagename, len_img, len_out_imagename) if ret != 0: raise VaccelError(ret, "Could not execute image depth operation") return ret @classmethod - def depth_from_filename(self, session:Session, source: str) -> str : + def depth_from_filename(self, session: Session, source: str) -> str: """Initialize an ImageDepth model by loading image from filename""" with open(source, "rb") as imgfile: data = imgfile.read() diff --git a/vaccel/image_genop.py b/vaccel/image_genop.py index afa8bab..b934e2f 100644 --- a/vaccel/image_genop.py +++ b/vaccel/image_genop.py @@ -1,7 +1,6 @@ from typing import List from vaccel.session import Session from vaccel.genop import Genop, VaccelArg, VaccelOpType -import copy class __ImageOperation__: @@ -31,6 +30,7 @@ def __parse_image__(image: "str | bytes") -> bytes: return image + class ImageClassify(__ImageOperation__): __op__ = VaccelOpType.VACCEL_IMG_CLASS @@ -49,9 +49,11 @@ def classify(self, image: "str | bytes"): image = self.__parse_image__(image=image) arg_read = [VaccelArg(data=int(self.__op__)), VaccelArg(data=image)] - arg_write = [VaccelArg(data=bytes(100 * " ", encoding="utf-8")), VaccelArg(data=bytes(100 * " ", encoding="utf-8"))] + arg_write = [VaccelArg(data=bytes(100 * " ", encoding="utf-8")), + VaccelArg(data=bytes(100 * " ", encoding="utf-8"))] return self.__genop__(arg_read=arg_read, arg_write=arg_write, index=0) + class ImageDetect(__ImageOperation__): __op__ = VaccelOpType.VACCEL_IMG_DETEC @@ -62,7 +64,7 @@ def detect(self, image: "str | bytes"): Perform image detection operation using vAccel over genop Parameters: - image (str | bytes): Filename or bytes object of the image + image (str | bytes): Filename or bytes object of the image Returns: str: Detection result @@ -73,6 +75,7 @@ def detect(self, image: "str | bytes"): arg_write = [VaccelArg(data=bytes(100 * " ", encoding="utf-8"))] return self.__genop__(arg_read=arg_read, arg_write=arg_write, index=0) + class ImageSegment(__ImageOperation__): __op__ = VaccelOpType.VACCEL_IMG_SEGME @@ -83,7 +86,7 @@ def segment(self, image: "str | bytes"): Perform image segmentation operation using vAccel over genop Parameters: - image (str | bytes): Filename or bytes object of the image + image (str | bytes): Filename or bytes object of the image Returns: str: Segmentation result @@ -94,6 +97,7 @@ def segment(self, image: "str | bytes"): arg_write = [VaccelArg(data=bytes(100 * " ", encoding="utf-8"))] return self.__genop__(arg_read=arg_read, arg_write=arg_write, index=0) + class ImagePose(__ImageOperation__): __op__ = VaccelOpType.VACCEL_IMG_POSE @@ -115,6 +119,7 @@ def pose(self, image: "str | bytes"): arg_write = [VaccelArg(data=bytes(100 * " ", encoding="utf-8"))] return self.__genop__(arg_read=arg_read, arg_write=arg_write, index=0) + class ImageDepth(__ImageOperation__): __op__ = VaccelOpType.VACCEL_IMG_DEPTH @@ -125,7 +130,7 @@ def depth(self, image: "str | bytes"): Perform image depth estimation operation using vAccel over genop Parameters: - image (str | bytes): Filename or bytes object of the image + image (str | bytes): Filename or bytes object of the image Returns: str: Depth result diff --git a/vaccel/noop.py b/vaccel/noop.py index 7e5142d..d11f985 100644 --- a/vaccel/noop.py +++ b/vaccel/noop.py @@ -1,7 +1,5 @@ -from vaccel._vaccel import lib, ffi -from vaccel.error import VaccelError +from vaccel._vaccel import lib -from vaccel.session import Session class Noop: def __init__(self): @@ -16,4 +14,3 @@ def noop(self, session): """exec the operation""" csession = session._to_inner() return lib.vaccel_noop(csession) - diff --git a/vaccel/resource.py b/vaccel/resource.py index 0ca63bd..8549588 100644 --- a/vaccel/resource.py +++ b/vaccel/resource.py @@ -1,5 +1,6 @@ from abc import abstractmethod + class Resource: """A vAccel resource diff --git a/vaccel/session.py b/vaccel/session.py index d0bbbc8..2435520 100644 --- a/vaccel/session.py +++ b/vaccel/session.py @@ -1,6 +1,7 @@ from vaccel._vaccel import lib, ffi from vaccel.error import VaccelError + class Session: def __init__(self, flags): """Create a new vAccel session""" @@ -23,16 +24,20 @@ def id(self): def register_resource(self, resource): """Register a vAccel resource with the session""" - ret = lib.vaccel_sess_register(self._inner, resource._get_inner_resource()) + ret = lib.vaccel_sess_register( + self._inner, resource._get_inner_resource()) if ret != 0: - raise VaccelError(ret, "Could not register resource to session".format(self.id())) - + raise VaccelError( + ret, "Could not register resource to session {}".format(self.id())) + def unregister_resource(self, resource): """Unregister a vAccel resource from the session""" - ret = lib.vaccel_sess_unregister(self._inner, resource._get_inner_resource()) + ret = lib.vaccel_sess_unregister( + self._inner, resource._get_inner_resource()) if ret != 0: - raise VaccelError(ret, "Could not unregister resource from session".format(self.id())) + raise VaccelError( + ret, "Could not unregister resource from session {}".format(self.id())) def has_resource(self, resource): """Returns true if the resource is registered with the session""" diff --git a/vaccel/tensorflow.py b/vaccel/tensorflow.py index 97fa80f..ea23ca6 100644 --- a/vaccel/tensorflow.py +++ b/vaccel/tensorflow.py @@ -3,15 +3,16 @@ import functools import operator -import sys from enum import IntEnum + class Node: """A representation of TensorFlow graph input or output node""" def __init__(self, name, node_id): self._name = bytes(name, "ascii") self._id = node_id + self.__hidden__ = list() def __str__(self): return '{}:{}'.format(self._name.decode('ascii'), self._id) @@ -32,20 +33,29 @@ def id(self): def id(self, node_id): self._id = node_id - def _to_ctype(self, ctype=None): - if ctype == None: - ctype = ffi.new("struct vaccel_tf_node *") - ctype.name = ffi.new("char[]", self._name) - ctype.id = self._id - return ctype + def to_cffi(self): + name = ffi.new("char[]", self._name) + nid = self._id - @staticmethod - def _to_carray(nodes): - cnodes = ffi.new("struct vaccel_tf_node[%d]" % len(nodes)) + ctype = ffi.new("struct vaccel_tf_node []", 1) + self.__hidden__.append(ctype) + self.__hidden__.append(name) + ctype[0].name = name + ctype[0].id = nid + + return ctype[0] + + def _to_carray(self, nodes): + temp = [] for i, n in enumerate(nodes): - n._to_ctype(cnodes[i]) + temp.append(n.to_cffi()) + + ctypenew = ffi.new("struct vaccel_tf_node[]", temp) + # hack to keep memory alive + self.__hidden__.append(ctypenew) + + return ctypenew - return cnodes class TensorType(IntEnum): FLOAT = lib.VACCEL_TF_FLOAT @@ -72,21 +82,22 @@ class TensorType(IntEnum): UINT32 = lib.VACCEL_TF_UINT32 UINT64 = lib.VACCEL_TF_UINT64 + class Tensor: """A representation of a Tensor""" _size_dict = dict([ - (TensorType.FLOAT, (ffi.sizeof('float'), 'float')), - (TensorType.DOUBLE, (ffi.sizeof('double'), 'double')), - (TensorType.INT32, (ffi.sizeof('int32_t'), 'int32_t')), - (TensorType.UINT8, (ffi.sizeof('int8_t'), 'int8_t')), - (TensorType.INT16, (ffi.sizeof('int16_t'), 'int16_t')), - (TensorType.INT8, (ffi.sizeof('int8_t'), 'int8_t')), - (TensorType.INT64, (ffi.sizeof('int64_t'), 'int64_t')), - (TensorType.BOOL, (ffi.sizeof('bool'), 'bool')), - (TensorType.UINT16, (ffi.sizeof('uint16_t'), 'uint16_t')), - (TensorType.UINT32, (ffi.sizeof('uint32_t'), 'uint32_t')), - (TensorType.UINT64, (ffi.sizeof('uint64_t'), 'uint64_t')) + (TensorType.FLOAT, (ffi.sizeof('float'), 'float')), + (TensorType.DOUBLE, (ffi.sizeof('double'), 'double')), + (TensorType.INT32, (ffi.sizeof('int32_t'), 'int32_t')), + (TensorType.UINT8, (ffi.sizeof('int8_t'), 'int8_t')), + (TensorType.INT16, (ffi.sizeof('int16_t'), 'int16_t')), + (TensorType.INT8, (ffi.sizeof('int8_t'), 'int8_t')), + (TensorType.INT64, (ffi.sizeof('int64_t'), 'int64_t')), + (TensorType.BOOL, (ffi.sizeof('bool'), 'bool')), + (TensorType.UINT16, (ffi.sizeof('uint16_t'), 'uint16_t')), + (TensorType.UINT32, (ffi.sizeof('uint32_t'), 'uint32_t')), + (TensorType.UINT64, (ffi.sizeof('uint64_t'), 'uint64_t')) ]) class OutOfBoundsTensorIndex(RuntimeError): @@ -105,10 +116,11 @@ def __init__(self, tensor_dims, data_len): def __str__(self): return "Trying to set data with length {} in tensor with dims: {}".format(self._data_len, self._dims) - def __init__(self, dims, dtype:TensorType): + def __init__(self, dims, dtype: TensorType): self._dims = dims self._data = [] self._dtype = dtype + self.__hidden__ = [] def __str__(self): return "Tensor {} of {}".format(self._dims, self._dtype) @@ -158,72 +170,118 @@ def get(self, indices): index = self.get_index(indices) return self.data[index] - def _to_ctype(self, ctype=None): - if ctype == None: - ctype = ffi.new("struct vaccel_tf_tensor *") + def to_cffi(self): + dims = ffi.new("int64_t[%d]" % len(self.dims), self.dims) + # hack to keep memory alive + self.__hidden__.append(dims) - ctype.dims = ffi.new("int64_t[%d]" % len(self.dims), self.dims) - ctype.nr_dims = len(self.dims) - ctype.data = ffi.new("%s[%d]" % (self._ctype(), self._csize() * len(self.data)), self.data) - ctype.size = self._csize() * len(self.data) - ctype.data_type = int(self._dtype) + nr_dims = len(self.dims) - return ctype + data = ffi.new("%s[%d]" % (self._ctype(), len(self.data)), self.data) + # hack to keep memory alive + self.__hidden__.append(data) + + size = self._csize() * len(self.data) + data_type = int(self._dtype) + + ctype = ffi.new("struct vaccel_tf_tensor []", 1) + # hack to keep memory alive + self.__hidden__.append(ctype) + + ctype[0].dims = dims + ctype[0].nr_dims = nr_dims + ctype[0].data = data + ctype[0].size = size + ctype[0].data_type = data_type + + return ctype[0] + + def _to_carray(self, tensors): - @staticmethod - def _to_carray(tensors): ctensors = ffi.new("struct vaccel_tf_tensor[%d]" % len(tensors)) + self.__hidden__.append(ctensors) + + temp = [] for i, t in enumerate(tensors): - t._to_ctype(ctensors[i]) + temp.append(t.to_cffi()) +# __hidden__.append(ctensors[i]) - return ctensors +# ctypenew = ffi.new("struct vaccel_tf_tensor**", ctensors) + ctypenew = ffi.new("struct vaccel_tf_tensor[]", temp) + self.__hidden__.append(ctypenew) + ctypenew = ffi.new("struct vaccel_tf_tensor**", ctypenew) + self.__hidden__.append(ctypenew) +# return ctensors + return ctypenew @staticmethod def _from_ctype(ctensor): dims = ffi.unpack(ctensor.dims, ctensor.nr_dims) +# dims = [ctensor.dims[i] for i in range(ctensor.nr_dims)] dtype = TensorType(ctensor.data_type) tensor = Tensor(dims, dtype) typed_cdata = ffi.cast("%s *" % tensor._ctype(), ctensor.data) - tensor.data = ffi.unpack(typed_cdata, int(ctensor.size / tensor._csize())) + tensor.data = ffi.unpack(typed_cdata, int( + ctensor.size / tensor._csize())) return tensor - + @staticmethod def _from_carray(ctensors, nr_tensors): ctensors = ffi.unpack(ctensors, nr_tensors) return [Tensor._from_ctype(t) for t in ctensors] - + class TensorFlowModel: """A TensorFlow model vAccel resource""" def __init__(self): """Create a TensorFlow model resource""" - self._inner = ffi.new("struct vaccel_tf_model *") + self._inner = ffi.new("struct vaccel_tf_saved_model *") def __del__(self): """Destroy a vAccel TensorFlow model""" - - lib.vaccel_tf_model_destroy(self._inner) + + # lib.vaccel_tf_session_destroy(self._inner) + lib.vaccel_tf_saved_model_destroy(self._inner) def _get_inner_resource(self): return self._inner.resource - def from_model_file(self, model_path:str): + def from_model_file(self, model_path: str): """Initialize a TensorFlow model by loading it from a .pb file""" ret = lib.vaccel_tf_model_new(self._inner, bytes(model_path, 'ascii')) if ret != 0: raise VaccelError(ret, "Could not create model") - def from_data(self, data:bytes): + def from_data(self, data: bytes): """Initialize a TensorFlow model from a byte array""" ret = lib.vaccel_tf_model_new_from_buffer(self._inner, data) if ret != 0: raise VaccelError(ret, "Could not create model") + def model_set_path(self, model_path: str): + ret = lib.vaccel_tf_saved_model_set_path( + self._inner, bytes(model_path, 'ascii')) + if ret != 0: + raise VaccelError(ret, "Could not set path") + + def model_register(self): + ret = lib.vaccel_tf_saved_model_register(self._inner) + if ret != 0: + raise VaccelError(ret, "Could not register model") + + def from_session(self, session, model_path: str): + status = ffi.new("struct vaccel_tf_status *") + + ret = lib.vaccel_tf_session_load( + session._to_inner(), self._inner, status) + if ret != 0: + raise VaccelError(ret, "Could not create model") + def id(self): """Id of the TensorFlow model""" return lib.vaccel_tf_model_get_id(self._inner) @@ -235,27 +293,30 @@ def is_registered(self, session): def load_graph(self, session): status = ffi.new("struct vaccel_tf_status *") ret = lib.vaccel_tf_model_load_graph(session._to_inner(), self._inner, - status) + status) if ret != 0: raise VaccelError(ret, "Could not load TensorFlow graph") def run(self, session, in_nodes, in_tensors, out_nodes): - _run_options = ffi.new("struct vaccel_tf_buffer *"); - _status = ffi.new("struct vaccel_tf_status *"); - _out_tensors = ffi.new("struct vaccel_tf_tensor[%d]" % len(out_nodes)) - - _in_nodes = Node._to_carray(in_nodes) - _in_tensors = Tensor._to_carray(in_tensors) - _out_nodes = Node._to_carray(out_nodes) - - ret = lib.vaccel_tf_model_run(session._to_inner(), self._inner, _run_options, - _in_nodes, _in_tensors, len(in_nodes), - _out_nodes, _out_tensors, len(out_nodes), - _status) + _run_options = ffi.new("struct vaccel_tf_buffer *") + _status = ffi.new("struct vaccel_tf_status *") + _out_tensors_ = ffi.new("struct vaccel_tf_tensor[%d]" % len(out_nodes)) + _out_tensors = ffi.new("struct vaccel_tf_tensor**", _out_tensors_) + +# _in_nodes = Node._to_carray(in_nodes) +# _in_tensors = Tensor._to_carray(in_tensors) +# _out_nodes = Node._to_carray(out_nodes) + _in_nodes = in_nodes[0]._to_carray(in_nodes) + _in_tensors = in_tensors[0]._to_carray(in_tensors) + _out_nodes = out_nodes[0]._to_carray(out_nodes) + + ret = lib.vaccel_tf_session_run(session._to_inner(), self._inner, _run_options, + _in_nodes, _in_tensors, len(in_nodes), + _out_nodes, _out_tensors, len( + out_nodes), + _status) if ret != 0: print(ffi.string(_status.message)) raise VaccelError(ret, "Could not run TensorFlow graph") return Tensor._from_carray(_out_tensors, len(out_nodes)) - - diff --git a/vaccel/test.py b/vaccel/test.py index 1d2c8db..a0bb05f 100644 --- a/vaccel/test.py +++ b/vaccel/test.py @@ -1,9 +1,10 @@ from vaccel.session import Session from vaccel.noop import Noop -from vaccel.genop import Genop, VaccelArg, VaccelOpType +from vaccel.genop import Genop, VaccelArg from vaccel.image import ImageClassify, ImageDetect, ImageSegment, ImagePose, ImageDepth from vaccel import image_genop as genimg + def test_session(): print("Session test") ses_a = Session(flags=0) @@ -11,6 +12,7 @@ def test_session(): print(f'Session A id is {ses_a.id()} and Session B id is {ses_b.id()}') print('') + def test_noop(): print("Noop test") ses = Session(flags=0) @@ -19,8 +21,10 @@ def test_noop(): print(res) print('') + imgsource = "/store/nucs/test.jpg" + def test_genop(): """ should work, but it doesn't because the sanity check on vAccel @@ -36,39 +40,45 @@ def test_genop(): arg_write = [] res = Genop.genop(ses, arg_read, arg_write) - print("RESULT=" ,res) + print("RESULT=", res) print('') + def test_image_class_genop(): print('Image classify over genop test') res = genimg.ImageClassify.classify(image=imgsource) print(res) print('') + def test_image_detect_genop(): print('Image detection over genop test') res = genimg.ImageDetect.detect(image=imgsource) print(res) print('') + def test_image_segme_genop(): print('Image segmentation over genop test') res = genimg.ImageSegment.segment(image=imgsource) print(res) print('') + def test_image_pose_genop(): print('Image pose over genop test') res = genimg.ImagePose.pose(image=imgsource) print(res) print('') + def test_image_depth_genop(): print('Image depth over genop test') res = genimg.ImageDepth.depth(image=imgsource) print(res) print('') + def test_image_classify(): print("Image classify test") ses = Session(flags=3) @@ -77,6 +87,7 @@ def test_image_classify(): print(res) print('') + def test_image_detect(): print("Image detect test") ses = Session(flags=3) @@ -85,6 +96,7 @@ def test_image_detect(): print(res) print('') + def test_image_segment(): print("Image segment test") ses = Session(flags=3) @@ -93,6 +105,7 @@ def test_image_segment(): print(res) print('') + def test_image_pose(): print("Image pose test") ses = Session(flags=3) @@ -101,6 +114,7 @@ def test_image_pose(): print(res) print('') + def test_image_depth(): print("Image depth test") ses = Session(flags=3) @@ -109,16 +123,17 @@ def test_image_depth(): print(res) print('') -if __name__=="__main__": + +if __name__ == "__main__": test_session() test_noop() - #test genop image operations + # test genop image operations test_image_class_genop() test_image_detect_genop() test_image_segme_genop() test_image_pose_genop() test_image_depth_genop() - #test static image operations + # test static image operations test_image_classify() test_image_detect() test_image_segment()