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

Supporting client-side gRPC cancellation #393

Merged
merged 7 commits into from
Sep 19, 2023

Conversation

tanmayv25
Copy link
Contributor

@tanmayv25 tanmayv25 commented Sep 8, 2023

Enhances python client API to issue gRPC cancellation.

C++ client side grpc cancellation will be added at a later point.

Tests are added here: triton-inference-server/server#6278

@tanmayv25 tanmayv25 requested a review from rmccorm4 September 13, 2023 00:45
@@ -1502,6 +1522,7 @@ def wrapped_callback(call_future):
if request_id != "":
verbose_message = verbose_message + " '{}'".format(request_id)
print(verbose_message)
return self._call_future
Copy link
Contributor

@rmccorm4 rmccorm4 Sep 13, 2023

Choose a reason for hiding this comment

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

I think @nnshah1 had some concerns about returning this grpc future directly, not wanting users to call future.result() on it, possibly conflicting with our own callback that blocks on the result. If we want to return a cancel-only future, we can wrap it and hide the underlying future/.result() method.

However, I think it's fine to return it directly and document they shouldn't call .result() on it for now.

I'll let Neelay comment on this.

Copy link
Contributor

@nnshah1 nnshah1 Sep 13, 2023

Choose a reason for hiding this comment

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

I would like us to define a "WrappedFuture" class, where we override the result() method to return an InferResult() (similar in that sense to the wrapped_callback). Or hide the result as @rmccorm4 mentioned.

I think returning a future but having the result() be different than with the callback will be non-intuitive. - also don't like the idea of documenting 'not to use result()' or 'result()' is different that InferResult() - all seem more confusing than to wrap it.

Let me know if it's feasible.

Copy link
Contributor Author

@tanmayv25 tanmayv25 Sep 13, 2023

Choose a reason for hiding this comment

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

Updated here: cdf8aea

self._active = True
self._response_iterator = None

def __del__(self):
self.close()
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd advocate for del to be non blocking and use self.close(cancel_requests=True) - unless I'm missing something / good reason to keep it blocking.

src/python/library/tritonclient/grpc/_client.py Outdated Show resolved Hide resolved
@@ -1451,6 +1452,23 @@ def async_infer(
Optional custom parameters to be included in the inference
request.

Returns
Copy link
Member

Choose a reason for hiding this comment

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

I think returning a future should replace the callback method. AFAIK, futures (or async/await) were added to replace the need for callbacks and we need to support one of them.

We could perhaps add another argument to async_infer named return_future with the default value of False. If it is set to True, this method would return a future and would never call the callback.

Copy link
Contributor Author

@tanmayv25 tanmayv25 Sep 13, 2023

Choose a reason for hiding this comment

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

This makes sense. IMO we should also support cancelling request for callback based cancellation policy.
However, that is not possible without sending back the future. Maybe we can enforce that for accessing request cancellation feature, the user can not use callback based mode.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe we can enforce that for accessing request cancellation feature, the user can not use callback based mode.

Exactly, that's what I was thinking.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like the idea of returning Future with an additional method for retrieving the message. But I think it goes beyond the scope and can be addressed separately.
Additionally, we should be thinking of moving to aio clients at some point. Maintaining two library version is becoming heavy.

Comment on lines 597 to 608
get_call_obj : bool
If set True, then this function will yield
grpc.aio.call object first bfore the
InferResult.
This object can be used to issue request
cancellation if required. This can be attained
by following:
-------
generator = client.infer(..., get_call_obj=True)
grpc_call = await anext(generator)
grpc_call.cancel()
-------
Copy link
Member

Choose a reason for hiding this comment

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

Would it be possible to wrap the call object in another class (perhaps Request) that once awaited would provide and has a cancel method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are some new primitives that got added for async_generators in python 3.10. I am not very familiar with these right out of bat first trial was not successful.
Reverting cancellation support in asyncio for now. Will be addressing the issue later.

@tanmayv25 tanmayv25 merged commit a147986 into request-cancellation Sep 19, 2023
@tanmayv25 tanmayv25 deleted the tanmayv-grpc-client branch September 19, 2023 01:23
tanmayv25 added a commit that referenced this pull request Oct 4, 2023
* Supporting client-side gRPC cancellation (#393)

* Supporting client-side gRPC cancellation

* Address review comments

* Wrap future to expose only cancel

* Update src/python/library/tritonclient/grpc/_client.py

Co-authored-by: Iman Tabrizian <iman.tabrizian@gmail.com>

* Reverting changes in asyncio library

* Format

* Make class variable real private

---------

Co-authored-by: Iman Tabrizian <iman.tabrizian@gmail.com>

* Fix L0_grpc (#400)

* Improve the check

---------

Co-authored-by: Iman Tabrizian <iman.tabrizian@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

5 participants