Skip to content

[VirtualMachine] fix raw pointer using by VirtualMachine#9980

Merged
tqchen merged 3 commits intoapache:mainfrom
Deelvin:vc/vm-fix
Jan 31, 2022
Merged

[VirtualMachine] fix raw pointer using by VirtualMachine#9980
tqchen merged 3 commits intoapache:mainfrom
Deelvin:vc/vm-fix

Conversation

@vvchernov
Copy link
Contributor

@vvchernov vvchernov commented Jan 19, 2022

The issue was observed during generation of VirtulaMachine Module on python side and using it on c++ one.
Work case: when we work in one python session the lib (exec) object is generated and used for VirtualMachine compilation. Inside VM the raw pointer to the lib (exec) is copied. Due to the lib object is alive along the session the VM object can use the pointer and execute different methods like "set_input", "invoke" and so on.
Unworkable case: if we use python session for generation VM and try to use it on c++ side it does not work. The reason is the lib object died after the session is closed. Thus VM uses the pointer to the spoiled object and it leads to failure.

To fix this problem new field in VM (ObjectPtr) is used instead of Executable* exec_. ObjectPtr object is constructed by GetObjectPtr() and used as before.
There is shorter workaround: use this->IncRef() in executable.cc. But it looks no so good and I followed @tqchen advice

@jwfromm @tmoreau89 please see

ObjectPtr(const ObjectPtr<U>& other) // NOLINT(*)
: ObjectPtr(other.data_) {
static_assert(std::is_base_of<T, U>::value,
"can only assign of child class ObjectPtr to parent");
Copy link
Member

Choose a reason for hiding this comment

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

Likely we want to keep this static assert

Copy link
Member

Choose a reason for hiding this comment

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

Agree with TQ this should not be remove

ObjectRef return_register_;
/*! \brief The executable the VM will operate on. */
Executable* exec_;
ObjectPtr<Executable> exec_;
Copy link
Member

Choose a reason for hiding this comment

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

If you get Executable an ObjectRef wrapper like the rest of the code base you can then use the down casting machinery built on-top of ObjectRef. It might make working with this type easier.

Copy link
Contributor Author

@vvchernov vvchernov Jan 19, 2022

Choose a reason for hiding this comment

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

I have gotten idea, I will try

@vvchernov
Copy link
Contributor Author

Hello @tqchen @jroesch Are there any additional comments, questions?

* \param exec The executable.
*/
virtual void LoadExecutable(Executable* exec);
virtual void LoadExecutable(const ObjectRef& exec);
Copy link
Member

Choose a reason for hiding this comment

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

consider change to ObjectPtr<Executable> which can be constructed via https://github.com/apache/tvm/blob/main/include/tvm/runtime/object.h#L877

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was advice from @jroesch to use ObjectRef. And it seems the simplest way from possible ones. I agree that using of ObjectPtr is preferable but to get it correctly is not so simple task (see below).

return PackedFunc([sptr_to_self, this](TVMArgs args, TVMRetValue* rv) {
auto vm = make_object<VirtualMachine>();
vm->LoadExecutable(this);
vm->LoadExecutable(ObjectRef(sptr_to_self));
Copy link
Member

Choose a reason for hiding this comment

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

GetObjectPtr(this);

Copy link
Contributor Author

@vvchernov vvchernov Jan 24, 2022

Choose a reason for hiding this comment

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

As I know sptr_to_self is already ObjectPtr<Object>, if it is immediatly ObjectPtr<Executable> or can be simply converted to ObjectPtr<Executable> it will be nice, but it is not so. Unfortunately your approach is bad due to GetObjectPtr(...) creates new ObjectPtr<> object which contains copy of raw pointer. There is no any connection between origin and new ObjectPtr. It means that if origin object was released (e.g. when python session where it was generated is closed) we will have pointer to broken object and can not use it. just my PR solves this problem, but your approach does not as I think.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry for the delayed reply. sptr_to_self actually is guanranteed to point to this in this particular case. So actually GetObjectPtr<Executable>(...) should work in this case. This is mainly because ObjectPtr is an intrusive pointer that directly leverages the object data structure.

To confirm, we can add ICHECK(sptr_to_self.get() == this);

@tqchen
Copy link
Member

tqchen commented Jan 22, 2022

cc @YuchenJin @yongwww since this is VM related

@vvchernov
Copy link
Contributor Author

Hello @tqchen @jroesch @yongwww @YuchenJin, any questions? May be we merge this PR?

@tmoreau89 tmoreau89 requested review from jroesch and tqchen January 27, 2022 01:32
@tmoreau89
Copy link
Contributor

@vvchernov there seems to be a CI issue - from the looks of it it might be flaky - can you re-trigger?

@jwfromm
Copy link
Contributor

jwfromm commented Jan 27, 2022

@areusch or @driazati is there a way around the CI error this PR is hitting? Seems like the doc generation is being flaky.

@vvchernov vvchernov changed the title WIP: [VirtualMachine] fix raw pointer using by VirtualMachine [VirtualMachine] fix raw pointer using by VirtualMachine Jan 27, 2022
@driazati
Copy link
Member

Docs were broken for a while earlier, @vvchernov could you rebase (git fetch origin && git rebase origin/main) one more time? The latest commit (fa317ed) should have gotten everything back in working order

@vvchernov
Copy link
Contributor Author

Thanks @driazati ! It works

@tmoreau89
Copy link
Contributor

@driazati does this error seem like a flaky issue to you?

worker 'gw3' crashed while running 'tests/python/contrib/test_ethosu/test_codegen.py::test_mean[ifm_shape8-axis8-False-False-ethos-u55-256]'

@tmoreau89
Copy link
Contributor

At first sight the CI error seems completely unrelated to the PR...

@tqchen
Copy link
Member

tqchen commented Jan 28, 2022

@vvchernov would be great if you can confirm my latest comment, which should be a better fix

Sorry for the delayed reply. sptr_to_self actually is guanranteed to point to this in this particular case. So actually GetObjectPtr<Executable>(...) should work in this case. This is mainly because ObjectPtr is an intrusive pointer that directly leverages the object data structure.

To confirm, we can add ICHECK(sptr_to_self.get() == this);
``

…xecutable object for correct work of VirtualMachine on c++ side
@vvchernov
Copy link
Contributor Author

Thanks @tqchen for your help, I've used your approch with GetObjectPtr. It looks like CI tests should pass soon. May be you recheck my last changes.

@tqchen tqchen merged commit 36b48a5 into apache:main Jan 31, 2022
@tqchen
Copy link
Member

tqchen commented Jan 31, 2022

Thanks @vvchernov !

ylc pushed a commit to ylc/tvm that referenced this pull request Feb 16, 2022
Use ObjectPtr<Executable> instead of Executable* to solid saving of Executable object for correct work of VirtualMachine on c++ side


Co-authored-by: Valery Chernov <valery.chernov@deelvin.com>
@vvchernov vvchernov deleted the vc/vm-fix branch October 4, 2022 07:04
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.

6 participants