[Hexagon] Add RPC Mechanism for Hexagon#9631
Conversation
5fc7750 to
129d96a
Compare
38c2c50 to
ef7da6e
Compare
2f0bd36 to
6f2eec9
Compare
csullivan
left a comment
There was a problem hiding this comment.
What a wonderful consolidation of effort for bringing all the TVM runtimes to Hexagon. The simplicity of the FastRPC interface and resulting enabled featureset speak for themselves. Truly incredible work @mehrdadh, thank you!
| # copy android_bash template file | ||
| configure_file("${CMAKE_SOURCE_DIR}/src/runtime/hexagon/rpc/android_bash.sh.template" | ||
| ${HEXAGON_RPC_OUTPUT} COPYONLY) | ||
| endif() |
There was a problem hiding this comment.
Clean up artifacts, e.g.
| endif() | |
| set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${HEXAGON_RPC_OUTPUT}") | |
| endif() |
| INSTALL_COMMAND "true" | ||
| ) | ||
| elseif(USE_HEXAGON_DEVICE STREQUAL "${PICK_HW}") | ||
| elseif((USE_HEXAGON_DEVICE STREQUAL "${PICK_HW}") OR (USE_HEXAGON_RPC AND BUILD_FOR_ANDROID)) |
There was a problem hiding this comment.
Can we decouple the (USE_HEXAGON_DEVICE STREQUAL "${PICK_HW}") and (USE_HEXAGON_RPC AND BUILD_FOR_ANDROID) cases into separate conditionals? It's a bit tricky to follow the flow and easy to make an error in the build for one or the other flows unintentionally when grouping them together like this.
| elseif(BUILD_FOR_ANDROID AND HEXAGON_SDK_PATH_DEFINED) | ||
| list(APPEND RUNTIME_HEXAGON_SRCS src/runtime/hexagon/proxy_rpc/device_api.cc) | ||
| else() | ||
| elseif(USE_HEXAGON_RPC) |
There was a problem hiding this comment.
See comment ⬆️ about breaking out not reusing the USE_HEXAGON_DEVICE block. It will also be easier to delete the USE_HEXAGON_DEVICE flow down the line if they are decoupled.
| read_buffer_size_bytes_); | ||
|
|
||
| uint32_t bytes_to_read = 0; | ||
| if ((read_buffer_size_bytes_ - read_len_bytes) < 0) { |
There was a problem hiding this comment.
read_buffer_size_bytes_ can be uninitialized if SetReadBuffer is not called.
There was a problem hiding this comment.
I initialized it at the constructor as you suggested in previous comment.
| static tvm::runtime::hexagon::HexagonRPCServer* g_hexagon_rpc_server = nullptr; | ||
|
|
||
| static AEEResult hexagon_rpc_server_init() { | ||
| uint8_t* receive_buffer = new uint8_t[TVM_HEXAGON_RPC_BUFF_SIZE_BYTES]; |
There was a problem hiding this comment.
Nothing as far as I can tell is protecting against overflowing the receive_buffer TVM_HEXAGON_RPC_BUFF_SIZE_BYTES, we don't bass the receive_buffer_size to the iohandler (via the server).
There was a problem hiding this comment.
I added check for buffer size and passed the size to IOHandler:
31fda2b
| } // namespace runtime | ||
| } // namespace tvm | ||
|
|
||
| static tvm::runtime::hexagon::HexagonRPCServer* g_hexagon_rpc_server = nullptr; |
There was a problem hiding this comment.
Use an anonymous function to return the static global and init on first use
| @tvm.testing.fixture | ||
| def tvm_tracker_host(): | ||
| return os.environ["TVM_TRACKER_HOST"] | ||
|
|
||
|
|
||
| @tvm.testing.fixture | ||
| def tvm_tracker_port(): | ||
| return int(os.environ["TVM_TRACKER_PORT"]) | ||
|
|
||
|
|
||
| def _compose(args, decs): | ||
| """Helper to apply multiple markers""" | ||
| if len(args) > 0: | ||
| f = args[0] | ||
| for d in reversed(decs): | ||
| f = d(f) | ||
| return f | ||
| return decs | ||
|
|
||
|
|
||
| def requires_rpc_tracker(*args): | ||
| """Mark a test as requiring an RPC tracker to exist in | ||
| the host environment to run.""" | ||
| _requires_rpc_tracker = [ | ||
| *tvm.testing.requires_rpc(), | ||
| pytest.mark.skipif( | ||
| os.environ.get("TVM_TRACKER_HOST") == None, | ||
| reason="Missing environment variable, TVM_TRACKER_HOST", | ||
| ), | ||
| pytest.mark.skipif( | ||
| os.environ.get("TVM_TRACKER_PORT") == None, | ||
| reason="Missing environment variable, TVM_TRACKER_PORT", | ||
| ), | ||
| ] | ||
|
|
||
| return _compose(args, _requires_rpc_tracker) | ||
|
|
||
|
|
||
| def requires_hexagon_toolchain(*args): | ||
| _requires_hexagon_toolchain = [ | ||
| pytest.mark.skipif( | ||
| os.environ.get("HEXAGON_TOOLCHAIN") == None, | ||
| reason="HEXAGON_TOOLCHAIN environment variable is required to run this test.", | ||
| ), | ||
| ] |
There was a problem hiding this comment.
These are defined also in test_hexagon/proxy_rpc/ for the sake of common code can you put these in test_hexagon/conftest.py?
adstraw
left a comment
There was a problem hiding this comment.
This is a partial review to note that I tested out this PR using the README and was able to get it running. LGTM from a usability / documentation point of view.
d4feb90 to
8216120
Compare
8216120 to
a7ee1a9
Compare
csullivan
left a comment
There was a problem hiding this comment.
Looks great to me! Only (non-blocking) nitpicks/TODOs
269b2a8 to
532bf1b
Compare
* Add Hexagon RPC * removed android remote and updated Readme * Add check for workspace size * Make libtvm_runtime consistent for Android * Remove root access * Fix some docstrings * Make stack remote size as parameter * add documentation * Refactor test conftest * clang format * Decoupled USE_HEXAGON_RPC * fix creation of test base directory on android * Address global variable * Fix format and Cleanup cmake * Fix build for other targets
| COMMAND ${QAIC_EXE} ${QAIC_FLAGS} "${HEXAGON_RPC_DIR}/${RPC_IDL}" -o ${HEXAGON_RPC_DIR} | ||
| MAIN_DEPENDENCY "${HEXAGON_RPC_DIR}/${RPC_IDL}" | ||
| ) | ||
| file(GLOB HEXAGON_RPC_CPP "${HEXAGON_RPC_DIR}/android/*.cc") |
There was a problem hiding this comment.
This will unconditionally add all files from that directory to the runtime target. If USE_HEXAGON_RPC is not set, it will cause link errors.
There was a problem hiding this comment.
@kparzysz-quic thanks for pointing out. This could break if USE_HEXAGON_SDK and BUILD_FOR_ANDROID are enabled and USE_HEXAGON_RPC not enabled. So we should fix this. I suggest that we fix this with a cleanup of Hexagon.cmake once we agreed on using hexagon RPC and decided to deprecate hexagon proxy rpc and apps/hexagon_launcher.
There was a problem hiding this comment.
@kparzysz-quic happy to hear your suggestion on this. thanks!
* Add Hexagon RPC * removed android remote and updated Readme * Add check for workspace size * Make libtvm_runtime consistent for Android * Remove root access * Fix some docstrings * Make stack remote size as parameter * add documentation * Refactor test conftest * clang format * Decoupled USE_HEXAGON_RPC * fix creation of test base directory on android * Address global variable * Fix format and Cleanup cmake * Fix build for other targets
* Add Hexagon RPC * removed android remote and updated Readme * Add check for workspace size * Make libtvm_runtime consistent for Android * Remove root access * Fix some docstrings * Make stack remote size as parameter * add documentation * Refactor test conftest * clang format * Decoupled USE_HEXAGON_RPC * fix creation of test base directory on android * Address global variable * Fix format and Cleanup cmake * Fix build for other targets
* Add Hexagon RPC * removed android remote and updated Readme * Add check for workspace size * Make libtvm_runtime consistent for Android * Remove root access * Fix some docstrings * Make stack remote size as parameter * add documentation * Refactor test conftest * clang format * Decoupled USE_HEXAGON_RPC * fix creation of test base directory on android * Address global variable * Fix format and Cleanup cmake * Fix build for other targets
* Add Hexagon RPC * removed android remote and updated Readme * Add check for workspace size * Make libtvm_runtime consistent for Android * Remove root access * Fix some docstrings * Make stack remote size as parameter * add documentation * Refactor test conftest * clang format * Decoupled USE_HEXAGON_RPC * fix creation of test base directory on android * Address global variable * Fix format and Cleanup cmake * Fix build for other targets
| } | ||
|
|
||
| /*! | ||
| * \brief Get pointer to the buffer that a packet has been written to. |
There was a problem hiding this comment.
This function doesn't "get any pointers", it copies (part of) the write buffer to the specified address.
| read_buffer_index_); | ||
|
|
||
| uint32_t bytes_to_read = 0; | ||
| if ((read_buffer_index_ - read_len_bytes) < 0) { |
There was a problem hiding this comment.
This shouldn't be subtracting unsigned numbers, just comparing them.
| read_buffer_index_ -= bytes_to_read; | ||
| if (bytes_to_read != read_len_bytes) { | ||
| HEXAGON_PRINT(ERROR, "Error bytes_to_read (%d) < read_len_bytes (%d).", bytes_to_read, | ||
| read_len_bytes); |
There was a problem hiding this comment.
If it's an error to read less than read_len_bytes, then why is the code above trying to handle this?
| if (data_size_bytes > read_buffer_size_bytes_) { | ||
| return AEE_EFAILED; | ||
| } | ||
| read_buffer_ = data; |
There was a problem hiding this comment.
This loses the initial read buffer, which is never deallocated.
| */ | ||
| class HexagonIOHandler { | ||
| public: | ||
| explicit HexagonIOHandler(uint8_t* read_buffer, size_t read_buffer_size_bytes) |
There was a problem hiding this comment.
The read_buffer is not used for anything.
| explicit HexagonIOHandler(uint8_t* read_buffer, size_t read_buffer_size_bytes) | ||
| : read_buffer_{read_buffer}, | ||
| read_buffer_size_bytes_{read_buffer_size_bytes}, | ||
| read_buffer_index_{0} {} |
There was a problem hiding this comment.
The order here should follow the order of declarations below.
| namespace { | ||
| tvm::runtime::hexagon::HexagonRPCServer* get_hexagon_rpc_server() { | ||
| static tvm::runtime::hexagon::HexagonRPCServer g_hexagon_rpc_server( | ||
| new uint8_t[TVM_HEXAGON_RPC_BUFF_SIZE_BYTES], TVM_HEXAGON_RPC_BUFF_SIZE_BYTES); |
There was a problem hiding this comment.
This allocation is lost the first time the server tries to read something (see SetReadBuffer).
|
@kparzysz-quic thanks for pointing out these issues. I will address these in the next PR for AOT executor. |
* Add Hexagon RPC * removed android remote and updated Readme * Add check for workspace size * Make libtvm_runtime consistent for Android * Remove root access * Fix some docstrings * Make stack remote size as parameter * add documentation * Refactor test conftest * clang format * Decoupled USE_HEXAGON_RPC * fix creation of test base directory on android * Address global variable * Fix format and Cleanup cmake * Fix build for other targets
This PR:
To use this feature you need to build TVM using these configs:
This will build:
libtvmandlibtvm_runtimeusing hexagon LLVM andtvm_rcpfor host.libtvm_runtime_android.soandtvm_rpc_androidfor Android underbuild/hexagon_rpclibhexagon_rpc_skel.solibrary which include RPC server for Hexagon underbuild/hexagon_rpccc @areusch @csullivan @adstraw