Mini-Infer (7.6): 架构重构 - 用“模板元编程”消除内核注册的“样板戏”
Mini-Infer (7.6): 架构重构 - 用“模板元编程”消除内核注册的“样板戏”
1. 问题的本质:一个“模板”的“模板”
我们的问题是:KernelRegistry (注册表) 的类型,依赖于函数指针的类型,而函数指针的类型又依赖于数据类型 (float, int)。
GEMM_NTforfloat->void(*)(const float*, ...)GEMM_NTforint32->void(*)(const int32_t*, ...)
这是一个清晰的模板模式。我们可以把 GEMM_NT 的函数签名定义为一个“函数类型模板”:
1 | template<typename T> |
现在,我们的问题演变为:如何创建一个通用的 KernelRegistry,它接受 GEMMFunc_NT 这样的**“模板”**作为参数,然后再由用户指定 T(如 float)?
2. 解决方案:template<template<typename> class FuncType>
这就是 C++ 模板元编程中的“模板模板参数”。我们来构建一个通用的 KernelRegistry,它不再是一个具体的类,而是一个“注册表的工厂”。
1 | // mini_infer/kernels/kernel_registry_v2.h (一个假想的新文件名) |
我们来拆解这个“魔法”:
template<template<typename> class FuncType>:FuncType不是一个类型(像int),也不是一个类型模板(像std::vector)。- 它是一个接受一个类型参数的模板(像
GEMMFunc_NT)。
class ForType : public KernelRegistryBase<FuncType<T>>:FuncType<T>:这里是“魔法”发生的地方。C++ 会把GEMMFunc_NT和float“组装”起来,得到GEMMFunc_NT<float>,这解析为我们需要的函数指针类型void(*)(const float*, ...)。KernelRegistryBase<GEMMFunc_NT<float>>:我们的ForType类继承自正确的KernelRegistryBase实例化版本。ForType<T>::instance():为每一种T(float,int32…)都提供了一个独立的、静态的单例。
现在,我们可以像这样获取 GEMM_NT 的 float 注册表: KernelRegistry<GEMMFunc_NT>::template ForType<float>::instance()
3. 告别丑陋:用“宏”和“别名”实现“语法糖”
KernelRegistry<...>::template ForType<...>::instance() 这种语法简直是“反人类”的。我们必须用 C++ 的“语法糖”把它藏起来。
第1步:使用 using 别名
1 | // 别名,用于隐藏内部的 ForType |
第2步:使用“宏”来定义别名(DRY 原则) 我们为每种内核类型(GEMM_NN, GEMM_NT…)定义一个易读的别名:
1 | // 定义注册表别名的"宏" |
现在,我们可以在 gemm.h 中这样定义我们的注册表:
1 | // in gemm.h |
现在,“噩梦”变成了“梦想”:
- 旧代码(丑陋):
KernelRegistry<GEMMFunc_NT>::template ForType<float>::instance() - 新代码(优雅):
GEMMRegistry_NT<float>::instance()
4. 用“宏”生成辅助函数
我们还需要 is_backend_available 和 get_best_backend 这样的辅助函数。我们同样不希望为 GEMM_NT, GEMM_NN… 手动各写一套。
我们可以用宏来生成这些“样板戏”代码:
1 | // 宏:定义一个“后端检查器”函数 |
使用:
1 | // in gemm.h |
总结与展望
通过 C++ 模板元编程和宏,我们支付了一次性、高昂的“复杂度税”,将所有的复杂性都封装在了 kernel_registry.h 这一个文件中。
我们换来的是:
- 零代码复用:
GEMM,im2col等所有内核现在都可以免费、类型安全地重用这个注册表。 - 优雅的 API:
GEMMRegistry_NT<float>::instance()。 - 易于维护:我们不再需要手写几十个单例类。
我们的 KernelRegistry 架构现在已经彻底稳定。我们为 Blog 7.5 中那个“丑陋”的 KernelRegistryInitializer 提供了完美的“配套设施”。





