我在动态列表上使用了ParallelFor。我想从循环中收集所有输出,并将它们传递给另一个ContainerOp。
如下所示,由于outputs
列表是静态的,因此显然不起作用。
with dsl.ParallelFor(op1.output) as item:
op2 = dsl.ContainerOp(
name='op2',
...
file_outputs={
'outputs': '/outputs.json',
})
outputs.append(op2.output)
op3 = dsl.ContainerOp(
name='op3',
...
arguments=['--input': outputs] # won't work
)
答案 0 :(得分:1)
不幸的是,方舟坤的解决方案对我不起作用。但是,如果我们提前知道输入数量,则有一种简单的方法可以实现扇入式工作流程。我们可以像这样预先计算管道DAG:
@kfp.components.create_component_from_func
def my_transformer_op(item: str) -> str:
return item + "_NEW"
@kfp.components.create_component_from_func
def my_aggregator_op(items: list) -> str:
return "HELLO"
def pipeline(array_of_arguments):
@dsl.pipeline(PIPELINE_NAME, PIPELINE_DESCRIPTION)
def dynamic_pipeline():
outputs = []
for i in array_of_arguments:
outputs.append(my_transformer_op(str(i)).output)
my_aggregator_op(outputs)
return dynamic_pipeline
...
run_id = client.create_run_from_pipeline_func(
pipeline(data_samples_chunks), {},
run_name=PIPELINE_RUN,
experiment_name=PIPELINE_EXPERIMENT).run_id
答案 1 :(得分:0)
问题是op3
没有正确地引用op2
的输出作为输入参数。试试这个:
op3 = dsl.ContainerOp(
...
arguments=['--input': op2.outputs['outputs']]
)
答案 2 :(得分:0)
我遇到了动态“扇出”问题,然后又出现了Kubeflow管道“扇入”问题。也许有些笨拙,但我使用了固定式PVC宣称来克服这个问题。
Kubeflow允许您使用min
(链接here)动态安装已知的PVC或动态创建新的PVC。此代码段显示了如何使用已知的PVC。
max
确保VolumeOp
在 pvc_name = '<available-pvc-name>'
pvc_volume_name = '<pvc-uuid>' # pass the pvc uuid here
# Op 1 creates a list to iterate over
op_1 = dsl.ContainerOp(
name='echo',
image='library/bash:4.4.23',
command=['sh', '-c'],
arguments=['echo "[1,2,3]"> /tmp/output.txt'],
file_outputs={'output': '/tmp/output.txt'})
# Using withParam here to iterate over the results from op1
# and writing the results of each step to its own PVC
with dsl.ParallelFor(op_1.output) as item:
op_2 = dsl.ContainerOp(
name='iterate',
image='library/bash:4.4.23',
command=['sh', '-c'],
arguments=[f"echo item-{item} > /tmp/output.txt; " # <- write to output
f"mkdir -p /mnt/{{workflow.uid}}; " # <- make a dir under /mnt
f"echo item-{item}\n >> /mnt/{{workflow.uid}}"], # <- append results from each step to the PVC
file_outputs={'output': '/tmp/output.txt'},
# mount the PVC
pvolumes={"/mnt": dsl.PipelineVolume(pvc=pvc_name, name=pvc_volume_name)})
op_3 = dsl.ContainerOp(
name='echo',
image='library/bash:4.4.23',
command=['sh', '-c'],
arguments=[f"echo /mnt/{{workflow.uid}} > /tmp/output.txt"],
# mount the PVC again to use
pvolumes={"/mnt": dsl.PipelineVolume(pvc=pvc_name, name=pvc_volume_name)},
file_outputs={'output': '/tmp/output_2.txt'}).after(op_2)
从op_3
开始的循环之后运行。
注意:这可能是一种繁重的方法,如果KFP允许将其作为KF编译器的一部分,但可能会有更好的解决方案,但我无法使其正常工作。如果在环境中轻松创建PVC,则可能适合您的情况。