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

Add a recursion sample #1016

Merged
merged 37 commits into from
Mar 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d1328bf
add a While in the ops group
gaoning777 Feb 6, 2019
d740b44
deepcopy the while conditions when entering and exiting
gaoning777 Mar 19, 2019
f309d85
add while condition resolution in the compiler
gaoning777 Mar 19, 2019
9afc4bb
define graph component decorator
gaoning777 Mar 20, 2019
c61022f
remove while loop related codes
gaoning777 Mar 20, 2019
054a988
fixes
gaoning777 Mar 20, 2019
0bec6b4
remove while loop related code
gaoning777 Mar 20, 2019
6872014
Merge branch 'master' into full-loops
gaoning777 Mar 20, 2019
56d71da
fix bugs
gaoning777 Mar 20, 2019
5215206
generate a unique ops group name and being able to retrieve by name
gaoning777 Mar 20, 2019
98d6ba6
resolve the opsgroups inputs and dependencies based on the pipelinepa…
gaoning777 Mar 20, 2019
b9bf07a
add a recursive ops_groups
gaoning777 Mar 21, 2019
4107e36
fix bugs of the recursive opsgroup template name
gaoning777 Mar 21, 2019
a4ecc9f
resolve the recursive template name and arguments
gaoning777 Mar 21, 2019
31de0dc
Merge branch 'master' into resolve-io-in-graph-component
gaoning777 Mar 21, 2019
b76c803
add validity checks
gaoning777 Mar 21, 2019
45d7b90
add more comments
gaoning777 Mar 22, 2019
6e94785
add usage comment in graph_component
gaoning777 Mar 22, 2019
7bcf800
add a sample
gaoning777 Mar 22, 2019
8f67da2
add unit test for the graph opsgraph
gaoning777 Mar 22, 2019
d99ddb2
refactor the opsgroup
gaoning777 Mar 22, 2019
d1ce1e2
add unit test for the graph_component decorator
gaoning777 Mar 22, 2019
7e96a30
exposing graph_component decorator
gaoning777 Mar 22, 2019
f840cf5
add recursive compiler unit tests
gaoning777 Mar 22, 2019
a756d4d
Merge branch 'resolve-io-in-graph-component' into add-loop-sample
gaoning777 Mar 22, 2019
bb7e425
add the sample test
gaoning777 Mar 22, 2019
035078e
fix the bug of opsgroup name
gaoning777 Mar 25, 2019
b824b3c
add a todo to combine the graph_component and component decorators
gaoning777 Mar 25, 2019
6f904bc
Merge branch 'master' into resolve-io-in-graph-component
gaoning777 Mar 26, 2019
45d0ef4
Merge branch 'resolve-io-in-graph-component' into add-loop-sample
gaoning777 Mar 26, 2019
81bffc0
Merge branch 'master' into add-loop-sample
gaoning777 Mar 26, 2019
3c3ad4e
Merge branch 'master' into add-loop-sample
gaoning777 Mar 27, 2019
9dd86fa
fix some merging bug
gaoning777 Mar 27, 2019
9169b01
fix typo
gaoning777 Mar 27, 2019
bebbdfd
Merge branch 'master' into add-loop-sample
gaoning777 Mar 27, 2019
bc12f98
add more comments in the sample
gaoning777 Mar 27, 2019
cd77e42
update comments
gaoning777 Mar 27, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions samples/basic/recursion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env python3
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import kfp.dsl as dsl

class FlipCoinOp(dsl.ContainerOp):
"""Flip a coin and output heads or tails randomly."""

def __init__(self):
super(FlipCoinOp, self).__init__(
name='Flip',
image='python:alpine3.6',
command=['sh', '-c'],
arguments=['python -c "import random; result = \'heads\' if random.randint(0,1) == 0 '
'else \'tails\'; print(result)" | tee /tmp/output'],
file_outputs={'output': '/tmp/output'})

class PrintOp(dsl.ContainerOp):
"""Print a message."""

def __init__(self, msg):
super(PrintOp, self).__init__(
name='Print',
image='alpine:3.6',
command=['echo', msg],
)

# Use the dsl.graph_component to decorate functions that are
# recursively called.
@dsl.graph_component
def flip_component(flip_result):
print_flip = PrintOp(flip_result)
flipA = FlipCoinOp().after(print_flip)
with dsl.Condition(flipA.output == 'heads'):
# When the flip_component is called recursively, the flipA.output
# from inside the graph component will be passed to the next flip_component
# as the input whereas the flip_result in the current graph component
# comes from the flipA.output in the flipcoin function.
flip_component(flipA.output)
gaoning777 marked this conversation as resolved.
Show resolved Hide resolved
# Return a dictionary of string to arguments
# such that the downstream components that depend
# on this graph component can access the output.
return {'flip_result': flipA.output}
gaoning777 marked this conversation as resolved.
Show resolved Hide resolved

@dsl.pipeline(
name='pipeline flip coin',
description='shows how to use dsl.Condition.'
)
def flipcoin():
flipA = FlipCoinOp()
flip_loop = flip_component(flipA.output)
# flip_loop is a graph_component with the outputs field
# filled with the returned dictionary.
PrintOp('cool, it is over. %s' % flip_loop.outputs['flip_result'])

if __name__ == '__main__':
import kfp.compiler as compiler
compiler.Compiler().compile(flipcoin, __file__ + '.tar.gz')
12 changes: 12 additions & 0 deletions test/e2e_test_gke_v2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,18 @@ spec:
value: "{{inputs.parameters.namespace}}"
- name: test-name
value: "paralleljoin"
- name: run-recursive-tests
template: run-basic-e2e-tests
arguments:
parameters:
- name: test-results-gcs-dir
value: "{{inputs.parameters.test-results-gcs-dir}}"
- name: sample-tests-image
value: "{{inputs.parameters.target-image-prefix}}{{inputs.parameters.basic-e2e-tests-image-suffix}}"
- name: namespace
value: "{{inputs.parameters.namespace}}"
- name: test-name
value: "recursion"

# Build and push image
- name: build-image
Expand Down
13 changes: 13 additions & 0 deletions test/sample-test/run_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,19 @@ elif [ "$TEST_NAME" == "paralleljoin" ]; then

echo "Copy the test results to GCS ${RESULTS_GCS_DIR}/"
gsutil cp ${SAMPLE_PARALLEL_JOIN_TEST_RESULT} ${RESULTS_GCS_DIR}/${SAMPLE_PARALLEL_JOIN_TEST_RESULT}
elif [ "$TEST_NAME" == "recursion" ]; then
SAMPLE_RECURSION_TEST_RESULT=junit_SampleRecursionOutput.xml
SAMPLE_RECURSION_TEST_OUTPUT=${RESULTS_GCS_DIR}

# Compile samples
cd ${BASE_DIR}/samples/basic
dsl-compile --py recursion.py --output recursion.tar.gz

cd "${TEST_DIR}"
python3 run_basic_test.py --input ${BASE_DIR}/samples/basic/recursion.tar.gz --result $SAMPLE_RECURSION_TEST_RESULT --output $SAMPLE_RECURSION_TEST_OUTPUT --testname recursion --namespace ${NAMESPACE}

echo "Copy the test results to GCS ${RESULTS_GCS_DIR}/"
gsutil cp ${SAMPLE_RECURSION_TEST_RESULT} ${RESULTS_GCS_DIR}/${SAMPLE_RECURSION_TEST_RESULT}
elif [ "$TEST_NAME" == "xgboost" ]; then
SAMPLE_XGBOOST_TEST_RESULT=junit_SampleXGBoostOutput.xml
SAMPLE_XGBOOST_TEST_OUTPUT=${RESULTS_GCS_DIR}
Expand Down