MLIR的Plugin(插件)系统与动态加载Dialect
从一次诡异的段错误说起
去年冬天调试一个MLIR-based的AI编译器,凌晨三点,GDB里backtrace指向了一个空指针——DialectRegistry里某个Dialect的initialize()方法压根没被调用。诡异的是,同样的代码在同事的Ubuntu 20.04上跑得飞起,我的Arch Linux上就崩。折腾了两小时,发现是动态库加载顺序的问题:系统自带的libMLIR.so先加载了某些Dialect,我的插件Dialect在dlopen时符号冲突,导致初始化被跳过。
那次之后,我花了整整一周把MLIR的Plugin系统翻了个底朝天。今天这篇笔记,就是当时踩坑的记录。
为什么需要动态加载Dialect?
MLIR的Dialect体系默认是静态注册的——你在cmake里target_link_libraries什么Dialect,编译时就全链进去了。这在开发阶段没问题,但生产环境里,你不可能为了支持一个新硬件后端就重新编译整个编译器。更现实的需求是:第三方厂商提供.so文件,你的框架在运行时dlopen它,自动注册自定义的Dialect、Pass、甚至Type和Attribute。
MLIR的Plugin系统本质上就是一套运行时动态注册的机制,