Example #1
0
def test_get_pipeline_input_node():
    # 1) No InputNode found
    ray_dag = combine.bind(1, 2)
    with _DAGNodeNameGenerator() as node_name_generator:
        serve_dag = ray_dag.apply_recursive(
            lambda node: transform_ray_dag_to_serve_dag(node, node_name_generator)
        )
    with pytest.raises(
        AssertionError, match="There should be one and only one InputNode"
    ):
        get_pipeline_input_node(serve_dag)

    # 2) More than one InputNode found
    with InputNode() as dag_input:
        a = combine.bind(dag_input[0], dag_input[1])
    with InputNode() as dag_input_2:
        b = combine.bind(dag_input_2[0], dag_input_2[1])
        ray_dag = combine.bind(a, b)
    with pytest.raises(
        AssertionError, match="Each DAG should only have one unique InputNode"
    ):
        with _DAGNodeNameGenerator() as node_name_generator:
            serve_dag = ray_dag.apply_recursive(
                lambda node: transform_ray_dag_to_serve_dag(node, node_name_generator)
            )
        get_pipeline_input_node(serve_dag)
def test_wide_fanout_deployment_graph(fanout_degree,
                                      init_delay_secs=0,
                                      compute_delay_secs=0):
    """
    Test that focuses on wide fanout of deployment graph
        -> Node_1
        /          \
    INPUT --> Node_2  --> combine -> OUTPUT
        \    ...   /
        -> Node_10

    1) Intermediate blob size can be large / small
    2) Compute time each node can be long / short
    3) Init time can be long / short
    """
    nodes = [
        Node.bind(i, init_delay_secs=init_delay_secs)
        for i in range(0, fanout_degree)
    ]
    outputs = []
    with InputNode() as user_input:
        for i in range(0, fanout_degree):
            outputs.append(nodes[i].compute.bind(
                user_input, compute_delay_secs=compute_delay_secs))

        dag = combine.bind(outputs)

        serve_dag = DAGDriver.bind(dag)

    return serve_dag
Example #3
0
def test_long_chain_deployment_graph(
    chain_length, init_delay_secs=0, compute_delay_secs=0
):
    """
    Test that focuses on long chain of deployment graph
    INPUT -> Node_1 -> Node_2 -> ... -> Node_10 -> OUTPUT
    1) Intermediate blob size can be large / small
    2) Compute time each node can be long / short
    3) Init time can be long / short
    """

    nodes = [Node.bind(i, init_delay_secs=init_delay_secs) for i in range(chain_length)]
    prev_outputs = [None for _ in range(chain_length)]

    with InputNode() as user_input:
        for i in range(chain_length):
            if i == 0:
                prev_outputs[i] = nodes[i].compute.bind(
                    user_input, compute_delay_secs=compute_delay_secs
                )
            else:
                prev_outputs[i] = nodes[i].compute.bind(
                    prev_outputs[i - 1], compute_delay_secs=compute_delay_secs
                )

        serve_dag = DAGDriver.bind(prev_outputs[-1])

    return serve_dag
Example #4
0
def test_dag_to_workflow_execution(workflow_start_regular_shared):
    """This test constructs a DAG with complex dependencies
    and turns it into a workflow."""
    @ray.remote
    def begin(x, pos, a):
        return x * a + pos  # 23.14

    @ray.remote
    def left(x, c, a):
        return f"left({x}, {c}, {a})"

    @ray.remote
    def right(x, b, pos):
        return f"right({x}, {b}, {pos})"

    @ray.remote
    def end(lf, rt, b):
        return f"{lf},{rt};{b}"

    with pytest.raises(TypeError):
        workflow.create(begin.remote(1, 2, 3))

    with InputNode() as dag_input:
        f = begin.bind(2, dag_input[1], a=dag_input.a)
        lf = left.bind(f, "hello", dag_input.a)
        rt = right.bind(f, b=dag_input.b, pos=dag_input[0])
        b = end.bind(lf, rt, b=dag_input.b)

    wf = workflow.create(b, 2, 3.14, a=10, b="ok")
    assert wf.run() == "left(23.14, hello, 10),right(23.14, ok, 2);ok"
Example #5
0
def test_single_class_with_invalid_deployment_options(serve_instance):
    with InputNode() as dag_input:
        model = Model.options(name="my_deployment").bind(2, ratio=0.3)
        ray_dag = model.forward.bind(dag_input)

    with _DAGNodeNameGenerator() as node_name_generator:
        serve_root_dag = ray_dag.apply_recursive(
            lambda node: transform_ray_dag_to_serve_dag(node, node_name_generator)
        )
    deployments = extract_deployments_from_serve_dag(serve_root_dag)
    assert len(deployments) == 1
    with pytest.raises(
        ValueError, match="Specifying 'name' in ray_actor_options is not allowed"
    ):
        deployments[0].deploy()
Example #6
0
def test_same_object_many_dags(workflow_start_regular_shared):
    """Ensure that when we dedupe uploads, we upload the object once per DAG,
    since different DAGs shouldn't look in each others object directories.
    """
    @ray.remote
    def f(a):
        return [a[0]]

    x = {0: ray.put(10)}

    result1 = workflow.create(f.bind(x)).run()
    result2 = workflow.create(f.bind(x)).run()
    with InputNode() as dag_input:
        result3 = workflow.create(f.bind(dag_input.x), x=x).run()

    assert ray.get(*result1) == 10
    assert ray.get(*result2) == 10
    assert ray.get(*result3) == 10
Example #7
0
def test_single_class_with_valid_ray_options(serve_instance):
    with InputNode() as dag_input:
        model = Model.options(num_cpus=1, memory=1000).bind(2, ratio=0.3)
        ray_dag = model.forward.bind(dag_input)

    with _DAGNodeNameGenerator() as node_name_generator:
        serve_root_dag = ray_dag.apply_recursive(
            lambda node: transform_ray_dag_to_serve_dag(node, node_name_generator)
        )
    deployments = extract_deployments_from_serve_dag(serve_root_dag)
    assert len(deployments) == 1
    deployments[0].deploy()
    _validate_consistent_python_output(
        deployments[0], ray_dag, deployments[0].name, input=1, output=0.6
    )

    deployment = serve.get_deployment(deployments[0].name)
    assert deployment.ray_actor_options.get("num_cpus") == 1
    assert deployment.ray_actor_options.get("memory") == 1000
    assert deployment.ray_actor_options.get("runtime_env") == {}
def test_single_class_with_invalid_deployment_options(serve_instance):
    with pytest.raises(TypeError, match="name must be a string"):
        with InputNode() as dag_input:
            model = Model.options(name=123).bind(2, ratio=0.3)
            _ = model.forward.bind(dag_input)