Skip to content
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

[uTVM] Initial BYOC support with c-source module #6950

Merged
merged 1 commit into from
Jan 15, 2021

Conversation

manupak
Copy link
Contributor

@manupak manupak commented Nov 23, 2020

  • Current flow uses saves the module as a c source and compiles it seperately. This blocks multi-module compilation.
  • This patch upgrades it to use export_library which supports external modules.
  • Added BYOC support for uTVM and testing
  • A new member for IRModule to carry external function names as they are required to create the function registry when creating a system-lib.

@manupak
Copy link
Contributor Author

manupak commented Nov 23, 2020

cc: @tqchen @areusch @zhiics @comaniac

@comaniac
Copy link
Contributor

I'm not familiar with uTVM. Out of curiosity, how uTVM uses BYOC codegen C? I ask because BYOC codegen C is just for demonstration purpose so its functionality is not complete.

@manupak
Copy link
Contributor Author

manupak commented Nov 23, 2020

@comaniac , Likewise this is also for demonstration purpose but in the uTVM context. i.e., if we can annotate and offload a set of operations and produce a c-source that can do the required computations and return the DLTensors, this is to show it works in the uTVM context.

Thus, we do not intend to use "ccompiler" as the solution rather to show a external codegen that could create c-source the place of the "ccompiler", the changes done here should enable the compilation of a such a source. Moreover, we do not prefer the metadata packing of Imports (using PackImports* methods) as they will re-create the artifacts in the volatile memory. However, having a c-source gives much better control as to where the artifacts should be placed through a standard linker script.

Copy link
Contributor

@comaniac comaniac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM to the codegen C part.

python/tvm/micro/build.py Outdated Show resolved Hide resolved
include/tvm/ir/module.h Outdated Show resolved Hide resolved
src/relay/backend/contrib/codegen_c/codegen.cc Outdated Show resolved Hide resolved
src/relay/backend/contrib/codegen_c/codegen.cc Outdated Show resolved Hide resolved
include/tvm/ir/module.h Outdated Show resolved Hide resolved
python/tvm/runtime/module.py Outdated Show resolved Hide resolved
python/tvm/micro/build.py Outdated Show resolved Hide resolved
include/tvm/ir/module.h Outdated Show resolved Hide resolved
@manupak manupak force-pushed the utvm_byoc branch 2 times, most recently from 891e53f to 16a51f9 Compare January 12, 2021 18:39
@manupak
Copy link
Contributor Author

manupak commented Jan 13, 2021

Hi @areusch @zhiics ,

Happy new year to you all! .

After CSourceMetadata module, this PR got reduced to introducing a simple test for utvm byoc example and some adjustments to external c-source code generator to make it applicable for uTVM as well. We would like to carry this test to ensure external module compilation works in uTVM.

Please take a look when you have time.

// These are only needed to handle metadata copying
code_stream_ << "#include <tvm/runtime/container.h>\n";
code_stream_ << "#include <tvm/runtime/packed_func.h>\n";
code_stream_ << "#include <dlpack/dlpack.h>\n";
Copy link
Member

@zhiics zhiics Jan 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think packed_func is probably needed to handle packed args. dlpack has to be included if we have DLTensor. The reason it doesn't cause errors is probably because c_runtime_api.h includes it as well or we don't use DLTensor at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, dlpack is in the c_runtime_api.h, thus we can remove it altogether.

Do we need packed_func.h ? -- I would like to avoid if the constants copying process is not required. The obvious usage is from TVM_DLL_EXPORT_TYPED_FUNC macro here which creates C++ code. Hence the gating based on presence of constants.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zhiics to clarify this codegen is just meant to generate C code, correct? we just got away with generating C++ code because export_library always writes .cc files. i also see that the BYOC blogpost has -std=c++14 as a compiler arg, but is that necessary with this simple codegen_c?

it looks like the purpose of TVM_DLL_EXPORT_TYPED_FUNC is to do some limited argument type validation and translate the function call signature from TVMBackendPackedCFunc into a series of primitive pointers. what's confusing is that theoretically we shouldn't need to go through C++ to do this, and you wouldn't expect that to happen since this is called, well, CodegenC.

it seems like the typechecking is actually not buying us much, because it doesn't actually check the element datatype of any DLTensors passed-in. Here, we just static_cast and presume the element datatype matches. if that's true, i'd propose (perhaps not in this PR) that we get rid of the dependency on TVM_DLL_EXPORT_TYPED_FUNC here. I think we should aim to have the same C header dependencies as the c target codegen in src/target/source/codegen_c_host.cc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@areusch Yeah, we used it to generated C++ code before when working on BYOC. But I think you are right, we should just export C code and get rid of the dependency of TVM_DLL_EXPORT_TYPED_FUNC

Copy link
Contributor Author

@manupak manupak Jan 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed dlpack for now and since we need to have Array<NDArray> here, we cant get away not using C++ here. Therefore, I might as well use the macro for convenience here.

However, I made it obvious that this part is not codegen'd/ not visible for a c-compiler.

Copy link
Contributor

@areusch areusch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@manupa-arm happy new year and thanks for continuing to push this forward. this looks pretty good, just a couple small things and some clarifying questions (as I'm not as familiar with codegen_c internals as I should be).

code_stream_ << "#include <tvm/runtime/container.h>\n";
code_stream_ << "#include <tvm/runtime/packed_func.h>\n";
code_stream_ << "#include <dlpack/dlpack.h>\n";
code_stream_ << "using namespace tvm::runtime;\n";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how come we dropped std::malloc yet have a using decl here?

Copy link
Contributor Author

@manupak manupak Jan 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this segment is only to be generated in the presence of constant copying process and makes this source a C++ one. To this end, there is a init function that accepts "Array<NDArray> arr" (See in codegen_c.h) that is in that namespace. I could not think of a way to make it a C source immediately.

Honestly, I was less worried about it as this is an example codegen and in utvm we dont want to be doing constant copying anyway. Therefore this segment will not be codegen'd. I understand its not ideal. However, the purpose of this test was to keep c-source base external codegen support (without constant copying -- which is controlled by constant extraction relay pass) in uTVM

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hrm. should we then add code like:

#ifdef __cplusplus
using std::malloc;
#endif

you're right this is a demo codegen, perhaps we don't need to resolve this. it's just confusing to create c++ code in a codegen named codegen_c.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@areusch So I made it obvious this segment is C++ in the code. See if it works.

tests/micro/qemu/test_zephyr.py Show resolved Hide resolved

def check_result(relay_mod, model, zephyr_board, map_inputs, out_shape, result):
"""Helper function to verify results"""
tol = 1e-5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you make this a module-level all-CAPS constant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

code_stream_ << "#include <tvm/runtime/c_backend_api.h>\n";
code_stream_ << "#include <tvm/runtime/crt/module.h>\n";
if (!variables.empty()) {
// These are only needed to handle metadata copying
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: delete "only" here--that statement is true only at this moment.

Copy link
Contributor Author

@manupak manupak Jan 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done and added a longer description to say why C++ code is generated, at least in this moment.

// These are only needed to handle metadata copying
code_stream_ << "#include <tvm/runtime/container.h>\n";
code_stream_ << "#include <tvm/runtime/packed_func.h>\n";
code_stream_ << "#include <dlpack/dlpack.h>\n";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zhiics to clarify this codegen is just meant to generate C code, correct? we just got away with generating C++ code because export_library always writes .cc files. i also see that the BYOC blogpost has -std=c++14 as a compiler arg, but is that necessary with this simple codegen_c?

it looks like the purpose of TVM_DLL_EXPORT_TYPED_FUNC is to do some limited argument type validation and translate the function call signature from TVMBackendPackedCFunc into a series of primitive pointers. what's confusing is that theoretically we shouldn't need to go through C++ to do this, and you wouldn't expect that to happen since this is called, well, CodegenC.

it seems like the typechecking is actually not buying us much, because it doesn't actually check the element datatype of any DLTensors passed-in. Here, we just static_cast and presume the element datatype matches. if that's true, i'd propose (perhaps not in this PR) that we get rid of the dependency on TVM_DLL_EXPORT_TYPED_FUNC here. I think we should aim to have the same C header dependencies as the c target codegen in src/target/source/codegen_c_host.cc.

tests/micro/qemu/test_zephyr.py Show resolved Hide resolved
This commit mainly introduces a byoc c-source module
example to uTVM. Moreover, it carries certain modifications
to the example codegen_c external module generator code
to generate utvm friendly c-source.

Change-Id: I09f3a42017d518dd5b6c89e3fe0a0332b80088b0
@manupak
Copy link
Contributor Author

manupak commented Jan 15, 2021

Hi @areusch @zhiics ,

I've addressed all the minor comments.

The current limitation of making this generator a pure C code generator is that is carries a Array<NDArray> for constants that will be copied in, if required by the compilation pipeline. I feel changing this is a bigger work and its only there to test the external codegen/runtime pathway (especially the JSONRuntime) handles the constant copying. Therefore, given that we have Array<NDArray>, I might as well use the macro. However, I clearly commented and made it obvious that bit of the code is C++ (using ifdef __cplusplus as @areusch suggested.)

Therefore, in the absense of the constant copying, this will generate a pure C code -- If you see I have removed macro usage for the main compute function (its just the constant copying one uses it).

Let me know your thoughts and what more could be done about it, if any.

Copy link
Contributor

@areusch areusch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, thanks for bearing with me @manupa-arm!

Copy link
Member

@zhiics zhiics left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the effort.

@zhiics zhiics merged commit b52267e into apache:main Jan 15, 2021
@zhiics
Copy link
Member

zhiics commented Jan 15, 2021

Thanks @manupa-arm @areusch

masahi pushed a commit to masahi/tvm that referenced this pull request Jan 18, 2021
This commit mainly introduces a byoc c-source module
example to uTVM. Moreover, it carries certain modifications
to the example codegen_c external module generator code
to generate utvm friendly c-source.

Change-Id: I09f3a42017d518dd5b6c89e3fe0a0332b80088b0
TusharKanekiDey pushed a commit to TusharKanekiDey/tvm that referenced this pull request Jan 20, 2021
This commit mainly introduces a byoc c-source module
example to uTVM. Moreover, it carries certain modifications
to the example codegen_c external module generator code
to generate utvm friendly c-source.

Change-Id: I09f3a42017d518dd5b6c89e3fe0a0332b80088b0
trevor-m pushed a commit to neo-ai/tvm that referenced this pull request Jan 21, 2021
This commit mainly introduces a byoc c-source module
example to uTVM. Moreover, it carries certain modifications
to the example codegen_c external module generator code
to generate utvm friendly c-source.

Change-Id: I09f3a42017d518dd5b6c89e3fe0a0332b80088b0
electriclilies pushed a commit to electriclilies/tvm that referenced this pull request Feb 18, 2021
This commit mainly introduces a byoc c-source module
example to uTVM. Moreover, it carries certain modifications
to the example codegen_c external module generator code
to generate utvm friendly c-source.

Change-Id: I09f3a42017d518dd5b6c89e3fe0a0332b80088b0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants