You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I was playing around in a Jupiter notebook trying to learn ray and come across some strange behaviour regarding threaded vs asyncio concurrency in Actors. Perhaps this behaviour is expected, but I didn't glean that from the docs pages.
The simple actor
@ray.remoteclassMyTestActor:
asyncdefdo_stuff_async(self) ->str: # an async non-blocking function that sleepsawaitasyncio.sleep(1)
return"hello"defdo_stuff_sync(self) ->str: # a synchronous blocking function that sleepssleep(1)
return"hello"actor=MyTestActor.options(max_concurrency=3).remote()
The experiment and results
Running do_stuff_async three times in my notebook takes one second, just as one might expect:
and re-running that notebook cell, then re-running the cell that calls do_stuff_sync, the invocations all completed in one second, meaning they ran concurrently as expected.
Attempted resolutions
I tried:
Using a named concurrency group for both functions rather than the default
Giving the actor two distinct concurrency groups: one for the async method and one for the synchronous one.
In the end, the only way to get the example actor working correctly was to split it into two actors: one with only the async method, and one with only the sync method.
Expected behaviour
As a user of Ray, I would expect that an actor could have both async and non-async functions, and that the concurrency group(s) apply correctly to all of them.
If this is not possible, I would expect a warning or error. If not when deploying the actor without any extra args, then at least when changing the default concurrency params.
Versions / Dependencies
Ray 2.40.0
Python 3.12.3
Reproduction script
importtimeitimportrayfromtimeimportsleepimportasyncio@ray.remoteclassMyTestActor:
asyncdefdo_stuff_async(self) ->str:
awaitasyncio.sleep(1)
return"hello"defdo_stuff_sync(self) ->str:
sleep(1)
return"hello"actor=MyTestActor.options(max_concurrency=3).remote()
# execute and time the async function callasync_futures= [actor.do_stuff_async.remote() for_inrange(3)]
start=timeit.default_timer()
ray.get(async_futures)
end=timeit.default_timer()
async_taken=end-start# execute and time the sync function callsync_futures= [actor.do_stuff_sync.remote() for_inrange(3)]
start=timeit.default_timer()
ray.get(sync_futures)
end=timeit.default_timer()
sync_taken=end-start# print time takenprint(f"async: {async_taken}s")
print(f"sync: {sync_taken}s")
Issue Severity
Medium: It is a significant difficulty but I can work around it.
EDIT:
I guess it is explained in the docs:
Instead, you can use the max_concurrency Actor options without any async methods, allowng you to achieve threaded concurrency (like a thread pool).
Though it could be worded a bit more prominently. Happy to take a stab at a PR for the docs if someone else thinks this is a valid issue with them.
The text was updated successfully, but these errors were encountered:
baughmann
added
bug
Something that is supposed to be working; but isn't
triage
Needs triage (eg: priority, bug/not-bug, and owning component)
labels
Jan 15, 2025
baughmann
changed the title
[<Ray component: Core] Mixing "async" with "blocking" methods in Actor changes threaded concurrency behaviour
[Core] Mixing "async" with "blocking" methods in Actor changes threaded concurrency behaviour
Jan 15, 2025
Hi @baughmann what you said is valid behavior. According to the doc
In async actors, only one task can be running at any point in time (though tasks can be multi-plexed). There will be only one thread in AsyncActor! See [Threaded Actors](https://docs.ray.io/en/latest/ray-core/actors/async_api.html#threaded-actors) if you want a threadpool.
Setting concurrency in Async Actors
You can set the number of “concurrent” task running at once using the max_concurrency flag. By default, 1000 tasks can be running concurrently.
An async actor ONLY has 1 thread and setting max_concurrency=3 won't create 3 threads for you but only allows 3 tasks (coroutines) to run at the same time in 1 thread.
jjyao
added
question
Just a question :)
P1
Issue that should be fixed within a few weeks
and removed
bug
Something that is supposed to be working; but isn't
triage
Needs triage (eg: priority, bug/not-bug, and owning component)
labels
Jan 22, 2025
What happened + What you expected to happen
I was playing around in a Jupiter notebook trying to learn ray and come across some strange behaviour regarding threaded vs asyncio concurrency in Actors. Perhaps this behaviour is expected, but I didn't glean that from the docs pages.
The simple actor
The experiment and results
Running
do_stuff_async
three times in my notebook takes one second, just as one might expect:However--bizarrely--running
do_stuff_sync
three times take three seconds, meaning that it is not running concurrently:Even stranger behaviour upon experimenting
Obviously, the above behaviour is quite strange. What is even stranger, however, is that by simply commenting out the async method:
and re-running that notebook cell, then re-running the cell that calls
do_stuff_sync
, the invocations all completed in one second, meaning they ran concurrently as expected.Attempted resolutions
I tried:
In the end, the only way to get the example actor working correctly was to split it into two actors: one with only the async method, and one with only the sync method.
Expected behaviour
As a user of Ray, I would expect that an actor could have both
async
and non-async
functions, and that the concurrency group(s) apply correctly to all of them.If this is not possible, I would expect a warning or error. If not when deploying the actor without any extra args, then at least when changing the default concurrency params.
Versions / Dependencies
Ray 2.40.0
Python 3.12.3
Reproduction script
Issue Severity
Medium: It is a significant difficulty but I can work around it.
EDIT:
I guess it is explained in the docs:
Though it could be worded a bit more prominently. Happy to take a stab at a PR for the docs if someone else thinks this is a valid issue with them.
The text was updated successfully, but these errors were encountered: