191 lines
5.1 KiB
Python
191 lines
5.1 KiB
Python
import sys
|
|
|
|
import pytest
|
|
|
|
import ray
|
|
from ray._common.test_utils import SignalActor
|
|
from ray.util import as_completed, map_unordered
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def ray_init_4_cpu_shared():
|
|
ray.init(num_cpus=4)
|
|
yield
|
|
ray.shutdown()
|
|
|
|
|
|
@pytest.mark.parametrize("yield_obj_refs", [True, False])
|
|
def test_as_completed_chunk_size_1(ray_init_4_cpu_shared, yield_obj_refs):
|
|
"""Test as_completed with chunk_size=1.
|
|
|
|
Use SignalActor to control task completion order and mimic time.sleep(x) behavior.
|
|
|
|
"""
|
|
inputs = [10, 8, 6, 4, 2]
|
|
|
|
# Create signals for each task
|
|
signals = [SignalActor.remote() for _ in range(len(inputs))]
|
|
|
|
# Create tasks
|
|
@ray.remote
|
|
def f(x, signal):
|
|
ray.get(signal.wait.remote())
|
|
return x
|
|
|
|
# Submit tasks with their corresponding signals in the original order
|
|
refs = [f.remote(x, signal) for x, signal in zip(inputs, signals)]
|
|
|
|
# Use as_completed() lazily
|
|
it = as_completed(refs, chunk_size=1, yield_obj_refs=yield_obj_refs)
|
|
|
|
# Send signal in reverse order to mimic time.sleep(x), i.e.,
|
|
# smallest value releases first. At the same time, collect results
|
|
|
|
results = []
|
|
for signal in reversed(signals):
|
|
ray.get(signal.send.remote())
|
|
results.append(next(it))
|
|
|
|
if yield_obj_refs:
|
|
results = ray.get(results)
|
|
|
|
assert results == [2, 4, 6, 8, 10]
|
|
|
|
|
|
@pytest.mark.parametrize("yield_obj_refs", [True, False])
|
|
def test_as_completed_chunk_size_2(ray_init_4_cpu_shared, yield_obj_refs):
|
|
"""Test as_completed with chunk_size=2.
|
|
|
|
Use SignalActor to control task completion order and mimic time.sleep(x) behavior.
|
|
|
|
"""
|
|
inputs = [10, 8, 6, 4, 2]
|
|
|
|
# Create signals for each task
|
|
signals = [SignalActor.remote() for _ in range(len(inputs))]
|
|
|
|
# Create tasks
|
|
@ray.remote
|
|
def f(x, signal):
|
|
ray.get(signal.wait.remote())
|
|
return x
|
|
|
|
# Submit tasks with their corresponding signals in the original order
|
|
refs = [f.remote(x, signal) for x, signal in zip(inputs, signals)]
|
|
|
|
# Use as_completed() lazily
|
|
it = as_completed(refs, chunk_size=2, yield_obj_refs=yield_obj_refs)
|
|
|
|
# Send signal in reverse order to mimic time.sleep(x), i.e.,
|
|
# smallest value releases first. At the same time, collect results
|
|
|
|
results = []
|
|
|
|
ray.get(signals[4].send.remote())
|
|
ray.get(signals[3].send.remote())
|
|
results.append(next(it))
|
|
results.append(next(it))
|
|
|
|
ray.get(signals[2].send.remote())
|
|
ray.get(signals[1].send.remote())
|
|
results.append(next(it))
|
|
results.append(next(it))
|
|
|
|
ray.get(signals[0].send.remote())
|
|
results.append(next(it))
|
|
|
|
if yield_obj_refs:
|
|
results = ray.get(results)
|
|
|
|
assert results == [4, 2, 8, 6, 10]
|
|
|
|
|
|
@pytest.mark.parametrize("yield_obj_refs", [True, False])
|
|
def test_map_unordered_chunk_size_1(ray_init_4_cpu_shared, yield_obj_refs):
|
|
"""Test map_unordered with chunk_size=1.
|
|
|
|
Use SignalActor to control task completion order and mimic time.sleep(x) behavior.
|
|
|
|
"""
|
|
inputs = [10, 8, 6, 4, 2]
|
|
|
|
# Create signals for each task
|
|
signals = [SignalActor.remote() for _ in range(len(inputs))]
|
|
|
|
# Create tasks
|
|
@ray.remote
|
|
def f(args):
|
|
x, signal = args
|
|
ray.get(signal.wait.remote())
|
|
return x
|
|
|
|
# Submit tasks with their corresponding signals in the original order
|
|
it = map_unordered(
|
|
f, zip(inputs, signals), chunk_size=1, yield_obj_refs=yield_obj_refs
|
|
)
|
|
|
|
# Send signal in reverse order to mimic time.sleep(x), i.e.,
|
|
# smallest value releases first. At the same time, collect results
|
|
|
|
results = []
|
|
for signal in reversed(signals):
|
|
ray.get(signal.send.remote())
|
|
results.append(next(it))
|
|
|
|
if yield_obj_refs:
|
|
results = ray.get(results)
|
|
|
|
assert results == [2, 4, 6, 8, 10]
|
|
|
|
|
|
@pytest.mark.parametrize("yield_obj_refs", [True, False])
|
|
def test_map_unordered_chunk_size_2(ray_init_4_cpu_shared, yield_obj_refs):
|
|
"""Test map_unordered with chunk_size=2.
|
|
|
|
Use SignalActor to control task completion order and mimic time.sleep(x) behavior.
|
|
|
|
"""
|
|
inputs = [10, 8, 6, 4, 2]
|
|
|
|
# Create signals for each task
|
|
signals = [SignalActor.remote() for _ in range(len(inputs))]
|
|
|
|
# Create tasks
|
|
@ray.remote
|
|
def f(args):
|
|
x, signal = args
|
|
ray.get(signal.wait.remote())
|
|
return x
|
|
|
|
# Submit tasks with their corresponding signals in the original order
|
|
it = map_unordered(
|
|
f, zip(inputs, signals), chunk_size=2, yield_obj_refs=yield_obj_refs
|
|
)
|
|
|
|
# Send signal in reverse order to mimic time.sleep(x), i.e.,
|
|
# smallest value releases first. At the same time, collect results
|
|
|
|
results = []
|
|
|
|
ray.get(signals[4].send.remote())
|
|
ray.get(signals[3].send.remote())
|
|
results.append(next(it))
|
|
results.append(next(it))
|
|
|
|
ray.get(signals[2].send.remote())
|
|
ray.get(signals[1].send.remote())
|
|
results.append(next(it))
|
|
results.append(next(it))
|
|
|
|
ray.get(signals[0].send.remote())
|
|
results.append(next(it))
|
|
|
|
if yield_obj_refs:
|
|
results = ray.get(results)
|
|
|
|
assert results == [4, 2, 8, 6, 10]
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(pytest.main(["-sv", __file__]))
|