-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
µTVM CRT modifications for on-device RPC server #5921
Conversation
64abc40
to
4d738c5
Compare
@areusch Thanks for your valuable contribution. Since this is a rather big change that might affect many existing users, would you please send an RFC for discussion before taking actions on implementation? |
hi @liangfu, I posted up an RFC about this here: https://discuss.tvm.ai/t/rfc-misra-c-changes-for-rpc-support/7098/2 |
Thanks for quick response and the comprehensive RFC. Let's discuss the the proposed features in the post. |
* Create a make-based build in src/runtime/crt. This is intended to be built in build/standalone_crt (generated by running ninja standalone_crt in build/). Its job is to build CRT without depending on headers not explicitly allowed in CRT. * Create a "public-facing" CRT API targeted to firmware running alongside CRT in include/tvm/runtime/crt. Developers who are integrating the CRT are the target of this API. * Reorganize CRT internally into common/ and graph_runtime/ pieces. Build each pieces as a separate statically-linked library. * Slim down TVMGraphRuntime public-facing API to just the functions that are used externally. * Updates to apps/bundle_deploy to make this work.
* Also add error_codes.h, a file containing error codes returned by CRT.
* NOTE: This changes the default API for functions exposed under the CRT by the TVMFuncCall API. `resource_handle` is now always given as a new 6th parameter. * `resource_handle` is NULL when invoked on a global function and a pointer to the module owning the function otherwise.
bea63f8
to
fa4f0e6
Compare
@@ -0,0 +1,57 @@ | |||
# Licensed to the Apache Software Foundation (ASF) under one |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that we are going to have StandaloneCrt.cmake, can we use CMake to build this instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im not sure how to do this without dragging in extra tvm configuration from e.g. include_directories() calls. The other thing is that the make-based flow is a good example for firmware engineers not used to cmake. What do you think? Cc @tqchen
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will let you guys decide, but it might make sense to show a make flow if it is simple enough, because others can learn from it
static TVMFunctionHandle EncodeFunctionHandle(tvm_module_index_t module_index, | ||
tvm_function_index_t function_index) { | ||
return (TVMFunctionHandle)((uintptr_t)( | ||
((module_index | 0x8000) << (sizeof(tvm_function_index_t) * 8)) | (function_index | 0x8000))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a define (maybe INT16_MSB_MASK
) and use for all occurrences of 0x8000
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, why is the function index ORing a valid bit as well (as opposed to the RFC, where it was just the module index)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left this in so that all valid TVMFunctionHandle are non-zero
* Assumes a constant average function name length. | ||
*/ | ||
static const size_t kTvmAverageFuncEntrySizeBytes = | ||
kTvmAverageFunctionNameSizeBytes + 1 + sizeof(void*); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why the + 1
here? if it's for the null terminator, should that be in the const above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/size/strlen/g to clarify
# specific language governing permissions and limitations | ||
# under the License. | ||
|
||
if(USE_STANDALONE_CRT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we should add this to the cmake config
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
TVMArgs TVMArgs_Create(TVMValue* values, uint32_t* tcodes, uint32_t values_count); | ||
|
||
typedef struct TVMPackedFunc { | ||
char name[200]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe make this smaller and defined in crt_config.h
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar thing--can't touch this in this PR as it's pretty big right now
// operator type in string | ||
char op_type[16]; | ||
// name of the op | ||
char name[120]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
define consts in crt_config.h
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm not going to touch these right now, they're orthogonal to this change. a follow-on PR can look at the graph runtime impl more thoroughly
tests/crt/func_registry_test.cc
Outdated
// overfill `names`. | ||
EXPECT_LT(kTvmAverageFuncEntrySizeBytes, strlen(function_name_chars) + 1); | ||
|
||
for (unsigned int buf_size = 0; buf_size < 10 + 1 + sizeof(void*); buf_size++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should 10 + 1 + sizeof(void*)
be replaced with kTvmAverageFuncEntrySizeBytes
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good call, done.
tests/crt/func_registry_test.cc
Outdated
|
||
for (unsigned int rem = 0; rem < kTvmAverageFuncEntrySizeBytes; rem++) { | ||
// test_function name will be used to test overfilling. | ||
char test_function_name[kTvmAverageFuncNameSizeBytes + 2 + rem]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why + 2
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its testing attempted over-filling, so + 1 for the overfill char and +1 for \0.
@areusch Added some comments. Also curious if there are any special instructions for running the tests. I added
|
* TVM runtime PackedFunc API. | ||
*/ | ||
/* class GraphRuntime : public ModuleNode { */ | ||
typedef struct TVMGraphRuntimeAPI { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to add the "API" suffix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah sorry, previous approach which I now don't use. API should be gone everywhere now
return (TVMModuleHandle)((uintptr_t)(module_index | 0x8000)); | ||
} | ||
|
||
static int _TVMModCreateFromCModule(const TVMModule* mod, TVMModuleHandle* out_handle) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider remove the underscore prefix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
graph, lib, params = relay.build( | ||
func, 'llvm --system-lib', params=params) | ||
func, 'c', params=params) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why should we change this default behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i changed this at first because llvm didn't work on my mac. then, I needed to keep it changed to handle --system-lib for now:
--system-lib is being handled using python/tvm/micro/function_registry.py
. in a follow-on I should be able to fold that in to C++ (I.e. as something like --system-lib --runtime=crt
). is it ok to leave as c for this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest keeping llvm --system-lib
, since we are targeting uTVM, not just mac :-)
Thanks @areusch . I tried to run
In addition, the inference speed slowed down comparing to the Did I make any wrong attempt in running the demo? |
@liangfu thanks for taking a look. I looked more into your error and it looks like I overlooked testing bundle_dynamic most recently. that is fixable, however... I did some more investigation and there are a couple of problems:
in a future PR, I plan to add an additional flag to the target string --runtime=<crt|c++>. this flag would allow us to produce a statically-linked llvm module compatible with the C runtime. would it be okay to do the following til then:
maybe @tqchen has more thoughts here? also, it would be helpful if we could add this app to the CI somehow. any thoughts on that? |
I think it is fine to just build for crt and not targeting c++ for now, as long as it works. The app was removed from the CI due to i386 compact issue of CRT, we can add it back if we confirmed that the issue has been resolved |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update and the detailed explanation. This is a quite significant change. I think we can can have this merged, and expect followup PRs to add the additional argument in targeting llvm with crt/c++ runtime.
* Reorganize CRT into parts, public API, and add standalone build. * Create a make-based build in src/runtime/crt. This is intended to be built in build/standalone_crt (generated by running ninja standalone_crt in build/). Its job is to build CRT without depending on headers not explicitly allowed in CRT. * Create a "public-facing" CRT API targeted to firmware running alongside CRT in include/tvm/runtime/crt. Developers who are integrating the CRT are the target of this API. * Reorganize CRT internally into common/ and graph_runtime/ pieces. Build each pieces as a separate statically-linked library. * Slim down TVMGraphRuntime public-facing API to just the functions that are used externally. * Updates to apps/bundle_deploy to make this work. * Add TVMFuncRegistry, CRT test infrastructure, and tests. * Also add error_codes.h, a file containing error codes returned by CRT. * Add TVMErrorf() * [API_CHANGE] Integrate func registry into CRT. * NOTE: This changes the default API for functions exposed under the CRT by the TVMFuncCall API. `resource_handle` is now always given as a new 6th parameter. * `resource_handle` is NULL when invoked on a global function and a pointer to the module owning the function otherwise. * Generalize arena-based memory manager. * lint * Fix git-clang-format arg parsing * add apache header * add mutable func registry tests * git-clang-format * fix more lint * Move memory_test to crttests. * fix tests * checkpoint * checkpoint * bundle_deploy demo_static works * rm debug printf * git-clang-format * fix lint * add asf header * pylint * update build configs for jenkins * make regression compiler happy * fix build errors in regression GCC * address comments * git-clang-format * fix for 32-bit cpp regression * fix incorrect use of memcpy and tests for 32-bit * clang-format
* Reorganize CRT into parts, public API, and add standalone build. * Create a make-based build in src/runtime/crt. This is intended to be built in build/standalone_crt (generated by running ninja standalone_crt in build/). Its job is to build CRT without depending on headers not explicitly allowed in CRT. * Create a "public-facing" CRT API targeted to firmware running alongside CRT in include/tvm/runtime/crt. Developers who are integrating the CRT are the target of this API. * Reorganize CRT internally into common/ and graph_runtime/ pieces. Build each pieces as a separate statically-linked library. * Slim down TVMGraphRuntime public-facing API to just the functions that are used externally. * Updates to apps/bundle_deploy to make this work. * Add TVMFuncRegistry, CRT test infrastructure, and tests. * Also add error_codes.h, a file containing error codes returned by CRT. * Add TVMErrorf() * [API_CHANGE] Integrate func registry into CRT. * NOTE: This changes the default API for functions exposed under the CRT by the TVMFuncCall API. `resource_handle` is now always given as a new 6th parameter. * `resource_handle` is NULL when invoked on a global function and a pointer to the module owning the function otherwise. * Generalize arena-based memory manager. * lint * Fix git-clang-format arg parsing * add apache header * add mutable func registry tests * git-clang-format * fix more lint * Move memory_test to crttests. * fix tests * checkpoint * checkpoint * bundle_deploy demo_static works * rm debug printf * git-clang-format * fix lint * add asf header * pylint * update build configs for jenkins * make regression compiler happy * fix build errors in regression GCC * address comments * git-clang-format * fix for 32-bit cpp regression * fix incorrect use of memcpy and tests for 32-bit * clang-format
* In apache#5921, resource_handle was added as a parameter to TVMBackendPackedCFunc, which is the typedef for functions called by LibraryModule's function lookup. * It appears TVM_DLL_EXPORT_TYPED_FUNC was overlooked in that PR, although there don't seem to be any runtime affects known so far. However, making this definition proper to avoid any compiler warnings/debug tool problems. * See also https://discuss.tvm.apache.org/t/rfc-misra-c-changes-for-rpc-support/7098/5
* In #5921, resource_handle was added as a parameter to TVMBackendPackedCFunc, which is the typedef for functions called by LibraryModule's function lookup. * It appears TVM_DLL_EXPORT_TYPED_FUNC was overlooked in that PR, although there don't seem to be any runtime affects known so far. However, making this definition proper to avoid any compiler warnings/debug tool problems. * See also https://discuss.tvm.apache.org/t/rfc-misra-c-changes-for-rpc-support/7098/5
* In apache#5921, resource_handle was added as a parameter to TVMBackendPackedCFunc, which is the typedef for functions called by LibraryModule's function lookup. * It appears TVM_DLL_EXPORT_TYPED_FUNC was overlooked in that PR, although there don't seem to be any runtime affects known so far. However, making this definition proper to avoid any compiler warnings/debug tool problems. * See also https://discuss.tvm.apache.org/t/rfc-misra-c-changes-for-rpc-support/7098/5
* In apache#5921, resource_handle was added as a parameter to TVMBackendPackedCFunc, which is the typedef for functions called by LibraryModule's function lookup. * It appears TVM_DLL_EXPORT_TYPED_FUNC was overlooked in that PR, although there don't seem to be any runtime affects known so far. However, making this definition proper to avoid any compiler warnings/debug tool problems. * See also https://discuss.tvm.apache.org/t/rfc-misra-c-changes-for-rpc-support/7098/5
* In apache#5921, resource_handle was added as a parameter to TVMBackendPackedCFunc, which is the typedef for functions called by LibraryModule's function lookup. * It appears TVM_DLL_EXPORT_TYPED_FUNC was overlooked in that PR, although there don't seem to be any runtime affects known so far. However, making this definition proper to avoid any compiler warnings/debug tool problems. * See also https://discuss.tvm.apache.org/t/rfc-misra-c-changes-for-rpc-support/7098/5
* In apache#5921, resource_handle was added as a parameter to TVMBackendPackedCFunc, which is the typedef for functions called by LibraryModule's function lookup. * It appears TVM_DLL_EXPORT_TYPED_FUNC was overlooked in that PR, although there don't seem to be any runtime affects known so far. However, making this definition proper to avoid any compiler warnings/debug tool problems. * See also https://discuss.tvm.apache.org/t/rfc-misra-c-changes-for-rpc-support/7098/5
Sending change to CI; will update with more details when it's ready to review and RFC is posted.