组件最佳实践¶
本节列出了您可能希望对组件执行的常见操作以及相应的最佳实践。组件旨在灵活,因此您可以根据需要偏离这些实践,但这些是我们在内置 TorchX 组件中使用的最佳实践。
有关如何使用 TorchX 编写应用程序的信息,请参见 应用程序最佳实践。
入口点¶
在可能的情况下,最好通过 python -m <module>
调用可重用组件,而不是指定主模块的路径。这样做可以使组件在不同的环境中使用(如 docker 和 slurm),因为组件依赖于 Python 模块解析而不是目录结构。
如果您的应用程序不是基于 Python,则可以将应用程序放在 PATH 上的文件夹中,这样无论目录结构如何都可以访问它。
def trainer(img_name: str, img_version: str) -> AppDef:
return AppDef(roles=[
Role(
entrypoint="python",
args=[
"-m",
"your.app",
],
)
])
简化¶
编写组件时,您希望保持每个组件尽可能简单,以使其他人更容易重用和理解它。
参数处理¶
参数处理使得在其他环境中使用组件变得困难。尤其是对于图像,我们希望直接将图像字段传递给 AppDef,因为任何形式的操作都将使其无法在其他具有不同图像命名约定的环境中使用。
def trainer(image: str):
return AppDef(roles=[Role(image=image)...)
分支逻辑¶
您应该避免在组件中使用分支逻辑。如果您遇到感觉需要在组件中使用 if
语句的情况,您应该更倾向于创建具有共享逻辑的多个组件。复杂的参数使其他人难以理解如何使用它。
def trainer_test():
return _trainer(num_replicas=1)
def trainer_prod() -> AppDef:
return _trainer(num_replicas=10)
# not a component just a function
def _trainer(num_replicas: int) -> AppDef:
return AppDef(roles=[Role(..., num_replicas=num_replicas)])
文档¶
文档是可选的,但最好对组件函数进行文档记录,尤其是在您想分享组件的情况下。有关更多详细信息,请参见 :ref:Component Authoring<components/overview:Authoring>。
命名资源¶
编写组件时,最好使用 TorchX 的命名资源支持,而不是手动指定 CPU 和内存分配。命名资源使您的组件与环境无关,并允许通过使用 t 恤尺寸来实现更好的调度行为。
有关更多信息,请参见 torchx.specs.get_named_resources()
。
组合组件¶
对于常见的组件样式,我们提供基本组件定义。这些可以从您的自定义组件定义中调用,并且是替代从头开始创建完整的 AppDef 的方法。
请参见
torchx.components.base
用于简单的单节点组件。torchx.components.dist.ddp()
用于分布式组件。
对于更复杂的组件,可以将多个现有组件合并到一个组件中。例如,您可以使用指标 UI 组件并将其中的角色合并到训练组件角色中,以便在您的主要训练作业中拥有一个旁路服务。
分布式组件¶
如果您正在编写用于分布式训练或其他类似分布式计算的组件,我们建议您使用 torchx.components.dist.ddp()
组件,因为它提供了对 torch.distributed.elastic
作业的开箱即用支持。
您可以通过编写一个简单地导入 ddp
组件并使用您的应用程序配置调用它的自定义组件来扩展 ddp
组件。
定义所有参数¶
最好将所有组件参数定义为函数参数,而不是使用参数字典。这样可以使用户更容易找出选项,并且可以在与 pyre 或 mypy 一起使用时提供静态类型。
单元测试¶
您可以像对待正常的 Python 代码一样对组件定义进行单元测试,因为它们是有效的 Python 定义。
我们建议您使用 ComponentTestCase
来确保您的组件可以被 TorchX CLI 解析。CLI 对文档字符串的要求比纯 Python 更加严格,因为文档字符串用于解析 CLI 参数。
- class torchx.components.component_test_base.ComponentTestCase(methodName='runTest')[source]¶
- run_component(component: Callable[[...], AppDef], args: Optional[Dict[str, Any]] = None, scheduler_params: Optional[Dict[str, Any]] = None, scheduler: str = 'local_cwd', interval: float = 0.1, timeout: float = 1) Optional[AppStatus] [source]¶
辅助函数,隐藏了设置运行器和轮询结果的复杂性。注意:该方法会阻塞,直到调度器退出或达到超时时间(对于非阻塞调度器)。
- 参数:
components – 组件函数,用于 AppDef 的工厂
args – 可选的组件工厂参数
scheduler_params – 可选的调度器工厂方法参数
scheduler – 调度器名称
interval – 调度器完成轮询间隔
timeout – 调度器完成的最大时间
集成测试¶
您可以通过使用编程运行器 API 或编写一个调用 CLI 的 bash 脚本,来设置您的组件的集成测试。
您可以在 TorchX 调度器集成测试中看到两种方式的使用。