mmd_hook
MMCV核心组件:Hook
0 摘要
Hook 机制在 OpenMMLab 系列框架中应用非常广泛,结合 Runner 类可以实现对训练过程的整个生命周期进行管理。同时内置了多种 Hook,通过注册的形式注入 Runner 中实现了丰富的扩展功能,例如模型权重保存、日志记录等等。
1 Hook 通俗理解
(1)Hook是什么
在wiki百科中的定义如下:
钩子编程(hooking),也称作“挂钩”,是计算机程序设计语,指通过拦截软件模块间的函数调用、消息传递、事件传递来修改或扩展操作系统、应用程序或其他软件组件的行为的各种技术。处理被拦截的函数调用、事件、消息的代码,被称为(钩子hook)
简而言之,就是能改变程序执行流程的一种技术统称。
(2)Hook用途
Hook 技术应用非常广泛,可以随便找一个简单例子来说明其用途。在软件编程的设计模式中,有一种设计模式叫做观察者设计模式,该设计模式实现的功能是:对于被观察者的一举一动,观察者都能够立即观测到,其内部实现机制可以简单通过 hook 机制实现,下面具体说明。
假设气象台可以提供两种对外服务:各大城市未来五天的天气情况和是否会出现地质灾害,你下个月由于要出差想知道深圳未来五天的天气情况,很简单,只需要订阅该气象台发布的其中一个天气预报服务即可,然后每天早上八点你手机会自动收到气象台发布的天气情况,注意:你不需要每时每刻关注气象台是否有发布天气情况,而是等它通知即可,如果不想再收到天气预报了,那么取消订阅即可。
这是非常典型的观察者设计模式:被观察者(气象台)对外提供注册机制,观察者可以通过插入和移除 Hook 实现订阅和取消订阅消息的功能,无论观察者有没有注册 Hook,都不会影响被观察者发布消息,伪代码如下:
class 气象台():
def __init__():
self.天气预报服务=''
self.是否存在地质灾害服务=''
self.天气预报_hooks=[]
self.是否存在地质灾害_hooks=[]
def 订阅天气预报服务(hook_fn)
self.天气预报_hooks.append(hook_fn)
def 取消订阅天气预报服务(hook_fn):
del self.天气预报_hooks[hook_fn]
def 订阅是否存在地质灾害服务(hook_fn)
self.是否存在地质灾害_hooks.append(hook_fn)
def 取消订阅是否存在地质灾害服务(hook_fn):
del self.是否存在地质灾害_hooks[hook_fn]
# 每天早上8点,气象台自动调用
def 发布消息():
=获取天气信息()
天气预报信息=获取是否存在地质灾害信息()
是否存在地质灾害信息for hook in self.天气预报_hooks:
hook(天气预报信息)for hook in self.是否存在地质灾害_hooks:
hook(是否存在地质灾害信息)
针对个人用户气象台伪代码如下所示:
def 天气预报信息_hook(str):
print(str)
我收到消息了,天气预报内容是str
if __name__ == '__main__':
# 实例化
=气象台()
气象台实例# 注册 hook
气象台实例.订阅天气预报服务(天气预报信息_hook)
# 接收消息,此时我就能够自动收到消息了
气象台实例.发布消息()
# 不打算再订阅了
气象台实例.取消订阅天气预报服务(天气预报信息_hook)
注意,实际上气象台实例不需要我们自己实例化,发布消息也不是我们控制的,这些都是被观察者自己的事情,个人用户只需要订阅和取消订阅即可。
在 python 中由于函数是一等公民,实现 hook 机制其实只需要传入一个函数即可,在该函数中我们可以获取到内部信息,可以修改或者访问该内容,从而实现一些类似黑科技一般的功能。
(3)Hook如何用
在 python 中要实现 hook 机制,非常简单,传入一个函数即可,如下是一个简单的 hook,该 hook 的功能是打印内部变量
def hook(d):
print(d)
def add(a,b,c,hook_fn=None):
=a+b
sum1if hook_fn is not None:
hook_fn(sum1)return sum1+c
# 调用
1,2,3,hook) add(