Files
2026-07-13 13:17:40 +08:00

77 lines
2.6 KiB
Python

import sys
import threading
import time
import numpy as np
import pytest
import ray
def test_multithreaded_ray_get(ray_start_cluster):
# This test tries to get a large object from the head node to the worker node
# while making many concurrent ray.get requests for a local object in plasma.
# TODO(57923): Make this not rely on timing if possible.
ray_cluster = ray_start_cluster
ray_cluster.add_node(
# This will make the object transfer slower and allow the test to
# interleave Get requests.
_system_config={
"object_manager_max_bytes_in_flight": 1024**2,
}
)
ray.init(address=ray_cluster.address)
ray_cluster.add_node(resources={"worker": 1})
# max_concurrency >= 3 is required: one thread for small gets, one for large gets,
# one for setting the threading.Events.
@ray.remote(resources={"worker": 1}, max_concurrency=3)
class Actor:
def __init__(self):
# ray.put will ensure that the object is in plasma
# even if it's small.
self._local_small_ref = ray.put("1")
# Used to check the thread running the small `ray.gets` has made at least
# one API call successfully.
self._small_gets_started = threading.Event()
# Used to tell the thread running small `ray.gets` to exit.
self._stop_small_gets = threading.Event()
def small_gets_started(self):
self._small_gets_started.wait()
def stop_small_gets(self):
self._stop_small_gets.set()
def do_small_gets(self):
while not self._stop_small_gets.is_set():
ray.get(self._local_small_ref)
time.sleep(0.01)
self._small_gets_started.set()
def do_large_get(self, refs_to_get):
remote_large_ref = refs_to_get[0]
ray.get(remote_large_ref)
actor = Actor.remote()
# Start a task on one thread that will repeatedly call `ray.get` on small
# plasma objects.
small_gets_ref = actor.do_small_gets.remote()
ray.get(actor.small_gets_started.remote())
# Start a second task on another thread that will call `ray.get` on a large object.
# The transfer will be slow due to the system config set above.
large_ref = ray.put(np.ones(1024**3, dtype=np.int8))
ray.get(actor.do_large_get.remote([large_ref]))
# Check that all `ray.get` calls succeeded.
ray.get(actor.stop_small_gets.remote())
ray.get(small_gets_ref)
if __name__ == "__main__":
sys.exit(pytest.main(["-sv", __file__]))