Hello all,
Background Info
I am trying to do the following:
- Use TVM to generate the AST of a certain tensor function (which one it is makes no difference, but as an example it is a copy operation)
- Replace part of the generated AST nodes with calls to function which I have defined externally in Python (using the
@tvm.register_func
decorator) - Run the module, which should trigger the execution of the functions in 2.
Use TVM to generate the AST of a certain tensor function
Assume I have some tvm.compute(...)
which gives the following (printed) AST
for (h.outer, 0, 160) {
for (i1, 0, 6) {
for (i2, 0, 642) {
for (i3, 0, 64) {
//the line below should be replaced
dest_array[some_pointer_arith] = src_array[some_poiner_arith]
}
}
}
}
This is the kind of AST which would be generated for a copy operation of a tensor which is is split only in the H dimension in 160 tiles.
Replace part of the generated AST nodes with calls to function which I have defined in Python
Following the Tutorial:External Tensor Functions, I also have some Python file with
@tvm.register_func("tvm.my_function")
def my_function(iteration_number):
print(iteration_number)
So in this case, lets say I just want to print all the iteration indexes for all lines. There is no specific reason I want to do this (i.e. print). But I want to be able to define external functions which use internal iteration variables as arguments.
So I use the tvm.ir_pass.IRTransform(stmt, None, _replace_stmt,["Store"])
to find the place in the AST which I want to replace doing the following
def _replace_stmt(stmt):
irb = tvm.ir_builder.create()
_func_call_node = tvm.make.Evaluate(tvm.call_packed("tvm.my_function",tvm.expr.Var('h.outer','int')))
#NOTE1: I also tried tvm.make.Evaluate(tvm.call_packed("tvm.my_function")), but this cant work since this would theoretically be a function without parameters
irb.emit(_func_call_node)
return irb.get()
Which should produce the following (printed) AST (it actually does if simple_mode=True
)
for (h.outer, 0, 160) {
for (i1, 0, 6) {
for (i2, 0, 642) {
for (i3, 0, 64) {
tvm_call_packed("tvm.my_function", h.outer)
}
}
}
}
Run the module
So at some point in my code, I have:
f = tvm.lower(some_schedule, some_place_holders, name="some_name")
m = tvm.build(f, target="llvm")
#some lines to fill the place_holders with values
m(some_tvm_nd_arrays)
While executing m(some_tvm_nd_arrays)
I expect the module execution to jump into tvm.my_function(...)
.
Questions
- There are a couple of “external functions” in TVM. When should we use which and am I using the right kind?
Example: the first time I tried something similar to what I described before, I actually didnt pass arguments and usedtvm.call_extern(...)
instead oftvm.call_packed(...)
inreplace_stmt()
and it didn’t work, but the VTA examples usetvm.call_extern()
, but they have a .so which I dont.
If I dont pass arguments and usetvm.call_packed(...)
(i.e._func_call_node = tvm.make.Evaluate(tvm.call_packed("tvm.my_function"))
everything works (even running the module)
As described in the problem statement, the f=tvm.lower(...)
line actually fails because
File "~/tvm/src/pass/make_api.cc", line 188
TVMError: Not all Vars are passed in api_args: 'h.outer' does not appeared in api_args
- How do I pass variables which are present in the AST representation to external functions?
I mean those which are not really tensor of thetvm.compute(...)
, but for example part of the iteration variables (and more specifically those after all loop splits and fusions)
What if my_function()
is actually a class method:
class MyClass():
@tvm.register_func("tvm.my_function")
def my_function(self,iteration_number):
print(iteration_numer)
-
How to call it?
Example: Note here that theself
parameter is part of the argument list but it is not visible from the module’s perspective, which actually leads to some compiling error because the argument list doesnt match -
Am I overcomplicating myself?
Example: should I be using the hybrid script? if so how?
Thanks for the help
Small Update #1
I tried (not at the same time):
some_place_holders.append(tvm.var(name='h.outer', dtype='int32'))
some_place_holders.append(tvm.placeholder((1,), name='h.outer'))
before calling tvm.lower(...)
but this also didnt work
Last EDIT:
I didnt want to explicitly tag anyone, but seeing as the question remains unanswered I will make one last edit with tags.
Those people tagged are the Top-5 in the user list for the quarter 28th of May - 28th of August, in an attempt to tag people who have been most active recently.
I apologize in advance:
@vinx13 @tqchen @thierry @yzhliu @FrozenGene