【深度学习】注册机制不能很好地扩展

Posted by ShawnD on May 10, 2023

人们对配置系统有很多不同的看法。在处理过各种风格的配置之后,我还想写一篇关于大规模(从系统复杂性、用户数量等方面来说)系统中一个好的配置子系统应该是什么样子的文章。

设计空间是复杂的,所以在本文中,我将从一个较小的主题开始:配置系统中的注册。我将说明为什么这种常见模式虽然适用于小规模项目,但从长期来看却不能很好地扩展。我还将讨论另一种选择。

Registration for configs

配置通常被限制为只包含基本类型(数字和字符串),并且有很多很好的理由保持这个属性。

配置系统中的全局注册表通常是一个 Mapping[str, Any]。它的目的是允许用户通过配置中的简单字符串引用复杂对象,从而克服原语类型的约束。

对象可以像这样添加到注册表中:

1
2
3
4
5
6
7
# Maps string to a class/type.
@ModelRegistry.register
class MyModel():
  ...

# Maps string to an object.
DatasetRegistry.register("my_dataset", MyDataset(...))

这使得用户可以通过设置 cfg.model.name = "MyModel"cfg.dataset.train = "my_dataset" 来选择 模型/数据。

注册有一个明显的好处,但在更大的范围内,它的一些缺点可能会变得严重。

Pay for what you use

用户应该只为他们使用的东西付费(计算成本和精神成本),这是我发现在软件设计的几乎所有方面都非常重要的一般设计理念。

注册模式通过运行不必要的注册代码打破了这一原则:用户将只在配置中提供一个(或很少的)字符串,但他们必须支付注册用户可能需要的许多候选字符串的开销。

更糟糕的是,开销必须发生在程序的早期,通常是在导入时。导入速度对开发人员的人体工程学至关重要:与其他可能与开发同步运行的代码不同,导入通常会阻碍开发人员。