dflow入门1——HelloWorld!

为了梳理学习dflow时遇到的知识点,我决定开这一个系列记录自己的学习过程。当然了,最好是去看官方教程文档

写在前面

dflow是干啥的

是做工作流的,其实就是argo的一个python包装,核心卖点就是可以用argo的UI,同时帮人解决一些工程问题,使代码标准化。

dflow怎么用

所谓工作流就是,预先定好任务执行流程的一整套任务的集合。说人话就是,填空。
使用dflow就是填一个个空。
在python是语境下就是,dflow预先定义好了很多的类,这些类已经可以实现很复杂的,工程向的功能。比如,任务调度、切片、循环、异常处理等等。
我们使用dflow最核心的方式就是调用它的类,增加这些类的科学向的功能。比如分子建模,制作量化软件的输入文件等等,所以学习dflow就是学习调用类的方式。

dflow架构浅析

如果把一整条工作流想象成一座生产标准工业品的工厂,那么step就是一个个顺序拼接起来的生产车间。

车间

每一个生产车间可以完成零部件的加工,在外界看来,step就是一个没有感情的,重复某项工作的一个黑盒。他所需要的只是生产所需的两种元素,一种是message,一种是artifact。前者类似指令,后者类似生产原料。
小结,step的上级是整个工厂(workflow),服从工厂调度,内部黑箱。

工人

那么生产车间内部是什么呢?是一个叫做template的工人。template收到step的原料和指令,开始按照既定的功能开展工作,吭哧吭哧干完后把成果交给step,作为输出。
小结,工人的上级是车间(step),服从车间调度,内部黑箱。

工序

工人干活,比如说,调用gaussian完成一项优化任务。gaussian正版软件要几十万,所以这些东西哪里来?作为一名工人,他需要收集各种工具,处理一些杂事(也就是调取image)。正儿八经要干的活儿,被抽象成了标准的操作手册:OP(operator)。在执行OP的时候,所需的一切条件都已经就位了(container里面环境啥的都配好了)。干完活儿后,把产品交给工人。
小结,工序的上级是工人(template),服从工人安排,内部黑箱。

工作流

我们从头捋一下。
工厂接到了订单,按照指令和原料生产某件产品,并把产品输出。
这是整个工作流的使命,对外黑箱,内部的流程是这样的:
生产流程:
工厂把任务(原料artifact和指令message)分给各个车间(step),车间把任务(原料artifact和指令message)分给工人(template),工人收集工具(image),按照操作手册(OP)生产产品,OP其实也是接收了任务(原料artifact和指令message)。

所以生产的时候,原料artifact和指令message是一直往下传的。

交货流程:
工人完成产品后,该产品对外就是整个车间(step)的output,车间和车间会在工厂的调度下相互耦合,交换产品等。工作流跑完后,工厂可以把最后一个车间的产品交付(download),当然了,也可以交中间车间的产品,这个可以任选,但都是以车间为单位的。

交货的时候,产品(artifact和message)也是一层层向上传的。

案例一:HelloWorld

下面我将从最底层的类开始,逐级向上,并完成helloworld。

制作OP

我们先制作最底层的工序(OP)。
下面是一个OP和他的依赖。

from pathlib import Path
from dflow.python import (OP, OPIO, Artifact, OPIOSign)
from typing import List


class WriteFile(OP):
    def __init__(self):
        pass

    @classmethod
    def get_input_sign(cls):
        return OPIOSign({
            'msg': str,
            'number': int,
        })

    @classmethod
    def get_output_sign(cls):
        return OPIOSign({
            "out_art": Artifact(List[Path])
        })

    @OP.exec_sign_check
    def execute(
            self,
            op_in: OPIO,
    ) -> OPIO:
        f = open("msg.txt","w")
        f.write(op_in["msg"])
        f.close()
        g = open("results.txt","w")
        g.write(str(op_in["number"]))
        g.close()
        
        op_out = OPIO({
            "out_art": [Path("msg.txt"), Path("results.txt")],
        })

        return op_out

我们在制作OP的时候要套用这个模板,他一定要有三个类方法,这些方法的名字不能动。
前两个是定义一下,工序正常运作所需要的原料和指令(get_input_sign),以及正常运作的输出(get_output_sign)

就好比python写一个函数

def aaa(in_msg: str, in_artifact: Artifact):
	op_in = {"in_msg": in_msg, "in_artifact": in_artifact}
	op_out = execute(op_in)
	out_msg, out_artifact = op_out["out_msg"], op_out["out_artifact"]
	return out_msg, out_artifact

我们写OP,其实就是写一个普通的函数,只不过格式上有区别,首先定义输入输出,然后把输入输出打包成dict给op_in,execute使用其中的东西完成业务逻辑,输出op_out,最后的op_out就是整个工序(OP)的输出,也是整个工人(template)。车间(step)的输出,他可以理解为一个字典。
具体的内部细节不用深究,我们只需要学会套用这个模板即可。

制作template

制作template需要考虑选择什么样的工序,以及该工序所需要的工具(image)

from dflow.python import PythonOPTemplate

a_tmp = PythonOPTemplate(WriteFile, image="python:3.8")

制作step

from dflow import Step

step0 = Step(
    name="step0",
    template=a_tmp,
    parameters={"msg": "HelloWorld!", "number": 1},
)

制作step就是把输入准备好即可,内部黑箱,取个名字方便调用。

制作工作流

from dflow import Workflow

wf = Workflow(name="python")
wf.add(step0)

wf.submit()
while wf.query_status() in ["Pending", "Running"]:
    time.sleep(1)
assert (wf.query_status() == "Succeeded")
step = wf.query_step(name="step")[0]
assert (step.phase == "Succeeded")

from dflow import download_artifact
download_artifact(step.outputs.artifacts["out_art"])

工作流就是一个个step组合而成的,我们通过句柄wf来监测任务,是更高级的接口。
任务提交后可以在argo上查看任务状态。

最后放一张PPT,帮助理解:
在这里插入图片描述
此文仅为个人理解,不足之处请指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值