在本章中,我们将讨论深度学习系统中最后但至关重要的一部分:工作流编排。工作流编排是一种管理、执行和监控工作流自动化的服务。工作流是一个抽象且广泛的概念,它实质上是一系列操作的序列,这些操作是某个更大任务的一部分。如果您可以制定一套任务来完成一项工作,那么这个计划就是一个工作流。例如,我们可以为训练机器学习(ML)模型定义一个顺序工作流。这个工作流可以由以下任务组成:获取原始数据、重建训练数据集、训练模型、评估模型和部署模型。
因为工作流是一个执行计划,它可以手动执行。例如,数据科学家可以手动完成我们刚刚描述的模型训练工作流中的任务。例如,要完成“获取原始数据”任务,数据科学家可以编写网络请求并发送给数据集管理(DM)服务来获取数据集,所有这些都不需要工程师的帮助。
然而,手动执行工作流并不理想。我们希望自动化工作流的执行。当有许多为不同目的开发的工作流时,我们需要一个专门的系统来处理工作流执行的复杂性。我们将这种系统称为工作流编排系统。
工作流编排系统被设计用于管理工作流的生命周期,包括工作流的创建、执行和故障排除。它不仅提供了保持所有计划代码运行的脉搏,还提供了一个控制平面,供数据科学家管理深度学习系统中的所有自动化操作。
在本章中,我们将讨论工作流编排系统的设计以及在深度学习领域中使用最广泛的开源编排系统。通过阅读本章,您不仅将对系统需求和设计选项有扎实的理解,还将了解如何选择最适合您自己情况的合适的开源编排系统。
在我们深入讨论工作流编排系统设计的细节之前,让我们先简要讨论一下工作流编排的基本概念,特别是从深度学习/机器学习的角度看工作流的特殊挑战。
注意,因为在深度学习项目和机器学习项目中使用工作流编排的要求几乎是相同的,所以在本章中,我们将深度学习和机器学习这两个词互换使用。
一般来说,工作流是一个由一系列操作组成的任务。工作流可以被看作是一个有向无环图(DAG),其中每个步骤是最小的可恢复计算单元,描述了一个动作,例如获取数据或触发一个服务。每个步骤要么成功完成,要么完全失败。在本章中,我们将任务(task)和步骤(step)互换使用。
DAG指定了步骤之间的依赖关系和执行顺序。图9.1显示了一个用于训练自然语言处理(NLP)模型的示例工作流。
从图9.1中的示例DAG可以看出,工作流由许多步骤组成。每个步骤依赖于另一个步骤,实线箭头表示步骤之间的依赖关系。这些箭头和步骤形成了一个没有循环的工作流DAG。
工作流在IT行业中被广泛使用。只要您可以将一个过程定义为一系列单个任务/步骤的DAG,这个过程就可以被认为是一个工作流。工作流对于深度学习模型开发至关重要。实际上,在生产环境中,大多数深度学习模型构建活动都以工作流的形式呈现和执行。
注意:工作流不应该有循环。为了确保工作流能够在任何情况下完成,其执行图必须是一个DAG,以防止工作流执行陷入死循环。
一旦我们定义了一个工作流,下一步就是运行工作流。运行工作流意味着根据工作流的DAG中定义的顺序执行工作流步骤。工作流编排是我们用来描述工作流的执行和监控的术语。
工作流编排的目标是自动化执行工作流中定义的任务。在实践中,工作流编排的概念通常扩展到整个工作流管理领域,包括以自动化的方式创建、调度、执行和监控多个工作流。
为什么深度学习系统需要工作流编排?理想情况下,我们应该能够将整个深度学习项目编写为一个整体。这正是我们在项目的原型设计阶段所做的,将所有的代码放在一个Jupyter笔记本中。那么,为什么我们需要将原型设计的代码转换为工作流,并在工作流编排系统中运行呢?答案有两个方面:自动化和工作共享。为了理解这些原因,让我们来看一下图9.2中的三个示例训练工作流。
使用工作流的一个巨大好处是将大块的代码转化为一组可共享和可重用的组件。在图9.2中,我们设想了三名数据科学家分别在三个模型训练项目(A、B和C)上工作。由于每个项目的训练逻辑不同,数据科学家开发了三个不同的工作流程(A、B和C)来自动化他们的模型训练过程。尽管每个工作流程具有不同的DAG,但每个DAG中的步骤高度重叠。总共的六个步骤是可共享和可重用的。例如,auth步骤(步骤1)是所有三个工作流程的第一步。
拥有可重用的步骤可以极大提高数据科学家的生产力。例如,要从DM服务中提取数据(图9.2中的步骤2),数据科学家需要学习DM网络API的工作方式。但是,如果已经有人将DM数据提取方法构建为一个步骤函数,科学家们可以在他们的工作流程中直接重用这个步骤,而无需学习如何与DM服务进行交互。如果每个人都以工作流的形式编写项目,我们将拥有许多可重用的步骤,这将在组织层面上节省大量重复的工作!
工作流之所以适用于深度学习开发的另一个原因是它促进了协作。模型开发需要团队合作;一个专门的团队可能负责数据,而另一个团队负责训练算法。通过在工作流程中定义一个复杂的模型构建过程,我们可以将一个复杂的大型项目分解为不同的部分(或步骤),并将它们分配给不同的团队,同时保持项目有序和组件的正确顺序。工作流DAG清楚地显示了所有项目参与者所见的任务依赖关系。
简而言之,一个好的工作流编排系统鼓励工作共享,促进团队协作,并自动化复杂的开发场景。所有这些优点使得工作流编排成为深度学习项目开发的关键组成部分。
在前面的部分中,我们看到工作流系统如何为深度学习项目开发提供了许多好处。但是有一个注意事项:使用工作流来原型化深度学习算法的想法是繁琐的。
为了了解为什么会繁琐以及为什么会繁琐,让我们看一下深度学习开发过程的图表(图9.3)。这个图表应该为你理解工作流在深度学习环境中带来的挑战奠定基础。
在图9.3中,我们可以看到一个从数据科学家的角度来看的典型深度学习项目开发过程。该过程可以分为两个阶段:本地孵化阶段和生产阶段。
在本地孵化阶段,数据科学家在他们的本地/开发环境中进行数据探索和模型训练的原型制作。当原型制作完成并且项目看起来有希望时,数据科学家开始进行生产部署:将原型代码移植到生产系统中。在生产阶段,数据科学家将原型代码转换为工作流。他们将代码分解为多个步骤,并定义一个工作流DAG,然后将工作流提交给工作流编排系统。之后,编排系统接管并根据其计划运行工作流。
原型制作和生产之间的差距
如果你问一个从事工作流编排系统的工程师对图9.3中的开发过程的看法,答案很可能是:还不错!但在实践中,这个过程对数据科学家来说是有问题的。
从数据科学家的角度来看,一旦算法在本地测试通过,其原型代码应该立即交付到生产环境中。但在图9.3中,我们可以看到原型制作阶段和生产阶段之间并没有平稳的连接。将孵化代码交付到生产环境并不直观;数据科学家必须额外工作来构建一个工作流,在生产环境中运行他们的代码。原型代码与生产工作流之间的差距对开发速度有两个方面的影响:
平滑过渡从原型制作到生产
尽管存在差距,图9.3中的流程是很好的。数据科学家从一个直观的脚本开始进行原型制作,然后继续工作。如果每次迭代后的结果足够有希望,那么“直观的本地脚本”将被转换为工作流,并在生产环境中运行。
在本节中,我们将分三个步骤来设计工作流编排系统。首先,我们将使用一个典型的数据科学家用户场景,展示编排系统从用户角度的工作方式。其次,我们学习通用的编排系统设计。第三,我们总结构建或评估编排系统的关键设计原则。通过阅读本节内容,您将了解编排系统的一般工作原理,从而可以自信地评估或使用任何编排系统。
虽然工作流程的过程在不同的场景下有很大的差异,但对于数据科学家来说,用户场景是相当标准的。大多数工作流使用可以分为两个阶段:开发阶段和执行阶段。请参考图9.4,了解数据科学家Vena的工作流用户体验。让我们一步一步地跟随图9.4中Vena的用户场景进行说明。
开发阶段
在开发阶段,数据科学家将他们的训练代码转化为工作流。以下是Vena的示例:
为了让您了解工作流在实际中的含义,以下代码展示了Vena的一个伪代码工作流(在第9.3节中,我们将讨论实际的工作流系统):
#defineworkflowDAGwithDAG(description='Vena’ssampletrainingworkflow',schedule_interval=timedelta(months=1),start_date=datetime(2022,1,1),)asdag:#defineexecutionlogicforeachstepdata_parse_step=BashOperator(......)data_augment_step=BashOperator(......)dataset_building_step=BashOperator(......)training_step=BashOperator(......)#Declaresstepdependenciesdata_parse_step>>data_augment_step>>dataset_building_step>>training_step执行阶段
在执行阶段,编排服务执行模型训练工作流,就像Vena的示例一样:
注意:工作流应该始终保持轻量级。工作流用于自动化一个过程,其目标是将一系列任务进行分组和连接,并按照定义的顺序执行。使用工作流的重要好处是人们可以共享和重用任务,从而更快地自动化他们的过程。因此,工作流本身不应进行任何繁重的计算,真正的工作应由工作流中的任务完成。
现在让我们转向通用的工作流编排系统。为了帮助您理解编排系统的工作原理并研究开源编排系统,我们准备了一个高级系统设计。通过放大详细实现细节并仅保留核心组件,这个设计适用于大多数编排系统,包括将在第9.3节中讨论的开源系统。请参考图9.5的设计提案。
一个工作流编排系统通常包含以下五个组件:
对象存储和元数据数据库对编排系统的所有组件都是可访问的,包括调度器、Web服务器和工作节点的组件。通过集中存储数据,核心组件可以解耦,使得Web服务器、调度器和工作节点可以独立工作。
工作流是怎么执行的?
其次,Vena通过Web界面或命令行将工作流(包括依赖代码)提交给Web服务器。工作流被保存在元数据数据库中。
第四步,工作节点从共享的作业队列中获取一个任务;它从元数据数据库中读取任务定义,并通过运行任务的操作符执行任务。在执行过程中,工作节点将任务的输出值保存到对象存储中,并将任务的执行状态报告给元数据数据库。
最后但同样重要的是,Vena使用托管在Web服务器组件上的Web用户界面来监视工作流的执行。由于调度器/控制器组件和工作节点实时向元数据数据库报告状态,因此Web用户界面始终显示最新的工作流状态。
因为我们已经了解了工作流编排系统的内部和外部工作原理,现在是时候审视使一个工作流编排系统在深度学习场景下脱颖而出的设计原则了。我们希望您可以将这些原则作为指导,用于改进您的系统或评估开源方法。
注意,从工程角度来看,工作流编排系统是深度学习系统中最复杂的组件之一,因此在最初的几个版本中,不必过于担心使您的系统与这些原则完全匹配。
原则1:关键性
工作流编排本质上是一个作业调度挑战,因此任何编排系统的底线都是提供稳定的工作流执行体验。有效的工作流应该能够正确、可重复地按计划执行。
原则2:易用性
在深度学习环境中,编排系统的易用性衡量标准在于它是否能提高数据科学家的生产力。大多数数据科学家与编排系统的交互都是创建、测试和监视工作流。因此,用户友好的编排系统应该让用户能够轻松地创建、监视和排查工作流。
原则3:可扩展性
为了满足各种各样的深度学习基础设施,人们应该能够轻松地定义自己的任务操作符和执行器,而不必担心它们部署在哪里。编排系统应该提供适合您环境的抽象级别,无论是AmazonEC2还是Kubernetes。
原则4:隔离性
关键的隔离性包括两种:工作流创建隔离和工作流执行隔离。工作流创建隔离意味着在创建工作流时,人们不能相互干扰。例如,如果Vena提交了一个无效的工作流DAG,或者发布了一个被其他工作流引用的常用共享库的新版本,现有的工作流不应受到影响。
原则5:可扩展性
深度学习编排的主要扩展思想是我们应该在系统级别解决性能问题,而不是要求用户编写具有可扩展性意识的代码。这样可以避免降低代码的可读性,增加调试难度并增加运维负担。
原则6:以人为中心支持原型和生产
将数据科学家的本地原型代码与生产工作流连接起来是深度学习特有的要求。这是我们评估编排系统是否适用于深度学习系统的关键指标。
为深度学习设计的编排系统将尊重从原型到生产的迭代式持续开发过程。因此,它将全力帮助数据科学家将本地原型代码无缝转换为生产工作流。
在本节中,我们将介绍三个经过实战验证的工作流编排系统:Airflow、ArgoWorkflows和Metaflow。这三个开源系统在IT行业得到了广泛应用,并且有着活跃的社区支持。除了对它们进行一般性的介绍,我们还将从深度学习项目开发的角度评估这些工作流系统。
为了进行公正的比较,我们将在Airflow、ArgoWorkflows和Metaflow中实现相同工作流的伪代码。基本上,如果有新的数据,我们会首先对数据进行转换并将其保存到数据库中的新表中,然后通知数据科学团队。此外,我们希望工作流每天运行一次。
Airflow的预定义操作符帮助用户在无需编码的情况下实现任务。您还可以使用PythonOperator来运行自定义的Python函数。一旦工作流DAG构建完成并且所有代码部署到Airflow中,我们可以使用UI或以下CLI命令来检查工作流的执行状态。以下是一些示例Shell命令:
关键功能
Airflow提供以下关键功能:
局限性
ArgoWorkflows是一个开源的、基于容器的工作流引擎,用于在Kubernetes上编排并行工作流/任务。ArgoWorkflows解决了与Airflow相同的问题,但采用了不同的方式,它采用了与Kubernetes本地化的方法。
ArgoWorkflows与Airflow之间最大的区别在于,ArgoWorkflows是基于Kubernetes原生构建的。具体而言,ArgoWorkflows中的工作流和任务是以Kubernetes自定义资源定义(CRD)对象的形式实现的,每个任务(步骤)作为一个Kubernetespod执行。请参见图9.6,了解高级系统概述。
在图9.6中,数据科学家Vena首先将工作流和其步骤/任务定义为KubernetesCRD对象,通常以YAML文件的形式呈现。然后,她将工作流提交给ArgoWorkflows,其控制器在Kubernetes集群内创建CRD对象。接下来,Kubernetes动态启动Pod来按照工作流序列运行步骤/任务。您可能还注意到,每个步骤的执行都通过容器和Pod完全隔离;每个步骤使用文件来表示其输入和输出值。ArgoWorkflows会自动将依赖文件挂载到步骤的容器中。
由KubernetesPod创建的任务隔离是ArgoWorkflows的重要优势。同时,简单性也是人们选择ArgoWorkflows的另一个原因。如果您了解Kubernetes,Argo的安装和故障排除都是直接的。我们可以使用ArgoWorkflows命令或标准的KubernetesCLI命令来调试系统。
典型用例
为了更好地理解,让我们看一个ArgoWorkflows的示例。在本节中,我们使用ArgoWorkflows来自动化前面在Airflow部分中看到的相同的数据处理工作。工作流包括首先检查新数据,对数据进行转换,将其保存到数据库中的新表中,然后通过Slack通知数据科学家团队。请参见以下代码示例,其中定义了ArgoWorkflows的工作流。
接下来,步骤transform_data将check-new-data的输出绑定到data-converter模板的输入。这就是变量在步骤和模板之间传递的方式。一旦您提交了工作流(例如,argosubmit-nargosample_workflow.yaml),您可以使用ArgoWorkflows的UI或以下命令来查看工作流运行的详细信息:
#listalltheworkflowsargolist-nargo#getdetailsofaworkflowrunargoget-nargo{workflow_name}除了使用argo命令,我们还可以使用KubernetesCLI命令来检查工作流的执行情况,因为ArgoWorkflows是在Kubernetes上原生运行的;以下是一个示例:
代码Docker化:便捷的生产部署ArgoWorkflows本质上是一个KubernetesPod(Docker镜像)调度系统。尽管它要求将代码编写为一系列的Docker镜像,但它在编排系统内部提供了很大的灵活性和隔离性。由于代码以Docker形式存在,它可以在任何工作节点上执行,而无需担心配置工作节点环境。
ArgoWorkflows的另一个优势是其低成本的生产部署。当您在Docker中本地测试代码时,Docker镜像(原型代码)可以直接在ArgoWorkflows中使用。与Airflow不同,ArgoWorkflows几乎不需要将原型代码转换为生产工作流的工作。
关键特点
ArgoWorkflows具有以下关键特点:
使用ArgoWorkflows的深度学习系统的缺点如下:
在9.1.3节中,我们指出了从原型代码到生产工作流的转换在机器学习开发中引发了很多摩擦。数据科学家必须为每个模型开发迭代构建和测试一个新版本的工作流程。为了弥合原型和生产之间的差距,Metaflow进行了两个改进:首先,简化了工作流程的构建;其次,统一了本地环境和生产环境中的工作流程执行体验(见图9.7)。
在图9.7中,我们可以看到Metaflow将原型和生产环境都视为一流的执行环境。因为Metaflow库提供了一组统一的API来抽象实际的基础架构,无论在哪个环境中运行,工作流程都可以以相同的方式执行。例如,工作流可以通过本地调度程序和生产调度程序运行,而无需进行任何更改。本地调度程序在本地执行工作流程,而生产调度程序则集成到其他生产编排系统中,如AWSStepFunctions或ArgoWorkflows。
典型用户案例
以下是使用Metaflow来自动化之前在9.3.1和9.3.2节中看到的相同数据处理工作的伪代码示例:
这里的一个优点是我们不需要在单独的系统中定义工作流DAG,并将代码重新打包成不同的格式,比如Docker镜像。Metaflow工作流嵌入在我们的代码中。工作流开发和原型代码开发发生在同一个地方,并且可以从整个机器学习开发周期的开始到结束一起进行测试。一旦代码准备好了,我们可以在本地验证和运行工作流。请参考以下示例命令:
#displayworkflowDAGpythondata_process_workflow.pyshow#runtheworkflowlocallypythondata_process_workflow.pyrun一旦我们完成了本地开发和测试,就可以通过以下两个命令将工作流推送到生产环境:
#pushtheworkflowfromlocaltoAWSstepfunctionspythondata_process_workflow.py--withretrystep-functionscreate#pushtheworkflowfromlocaltoArgoworkflowspythondata_process_workflow.py--withretryargo-workflowscreate这些命令将我们在代码清单9.3中定义的数据处理工作流导出到AWSStepFunctions和ArgoWorkflows。然后,您可以在AWSStepFunctionsUI或ArgoWorkflowsUI中通过名称搜索该工作流,并查看导出的工作流。
注意:Metaflow在本地和生产环境之间提供统一的开发体验。由于Metaflow提供了统一的API,我们在本地和生产环境中测试代码和工作流时具有无缝的体验。无论使用的是Metaflow本地调度程序、ArgoWorkflows还是AWSStepFunctions作为后端工作流编排系统,Metaflow在工作流开发方面的用户体验保持一致!
主要功能
Metaflow提供以下主要功能:
在深度学习系统中使用Metaflow的缺点如下:
如果你正在寻找一个用于非机器学习项目自动化工作流执行的编排系统,Airflow和ArgoWorkflows都是很好的选择。它们都有出色的社区支持,并在IT行业广泛使用。如果你的系统运行在Kubernetes上,并且团队对使用Docker感到舒适,那么ArgoWorkflows是一个很好的选择;否则,Airflow也不会让你失望。