当前位置:首页>python>MLIR CodeDocs 1 Python 绑定:设计与构建

MLIR CodeDocs 1 Python 绑定:设计与构建

  • 2026-04-19 07:23:35
MLIR CodeDocs 1 Python 绑定:设计与构建

当前状态:开发中,默认未启用

  • 构建

    • 前置依赖

    • CMake变量

    • 推荐开发实践

  • 设计

    • 使用场景

    • 可组合模块

    • 子模块

    • 加载器

    • 基于C-API实现

    • 核心IR的所有权管理

    • 核心IR的可选参数与参数顺序

  • 用户级API

    • 上下文管理

    • 查看IR对象

    • 创建IR对象

  • 编码风格

    • 属性 vs get*()方法

    • __repr__方法

    • 驼峰式(CamelCase)vs 蛇形(snake_case)

    • 优先使用伪容器

    • 为通用操作提供一站式辅助函数

  • 测试

    • 示例FileCheck测试

  • 与ODS集成

    • 生成_{方言命名空间}_ops_gen.py包装模块

    • 扩展包装模块的搜索路径

    • 包装模块代码组织

  • 为方言(Dialect)提供Python绑定

    • 操作(Operation)

    • 属性(Attribute)与类型(Type)

    • Pass(Pass)

    • 其他功能

  • 在Python中扩展MLIR

    • 方言(Dialect)

    • Pass(Pass)

    • 重写模式(Rewrite Pattern)

  • 无全局解释器锁(无GIL/Free-threading)支持


构建(Building)

前置依赖(Pre-requisites)

  • 较新版本的Python3

  • 安装mlir/python/requirements.txt中指定的Python依赖

CMake变量(CMake variables)

  • MLIR_ENABLE_BINDINGS_PYTHON:布尔型(BOOL)

启用Python绑定的编译,默认关闭(OFF)。

  • Python3_EXECUTABLE:字符串型(STRING)

指定用于LLVM编译的Python可执行文件,包括为Python绑定确定头文件/链接标志。在存在多个Python版本的系统上,强烈建议显式设置为首选的python3可执行文件。

推荐开发实践(Recommended development practices)

建议使用Python虚拟环境。创建虚拟环境的方式有多种,推荐以下两种:

# 确认当前使用的python为预期版本。多Python版本系统中可能带版本后缀;# 在Linux和macOS同时存在python2/python3的系统中,建议使用python3which pythonpython -m venv ~/.venv/mlirdevsource ~/.venv/mlirdev/bin/activate

若已安装uv,可通过以下命令创建虚拟环境(示例指定Python 3.12):

uv venv ~/.venv/mlirdev --seed -p 3.12source ~/.venv/mlirdev/bin/activate

可按需修改Python版本(-p参数)——若请求的Python解释器未安装,uv会尝试下载,除非指定--no-python-downloads。uv安装方式参考官方文档:https://docs.astral.sh/uv/getting-started/installation/

# 许多LTS发行版自带的pip版本过旧,无法下载部分平台最新二进制包# 可通过python -m pip --version查看pip版本;Linux环境需核对最低版本要求:# https://github.com/pypa/manylinux# 建议升级pippython -m pip install --upgrade pip# 此时python命令指向虚拟环境,包将安装到该环境python -m pip install -r mlir/python/requirements.txt# uv创建的虚拟环境可执行:uv pip install -r mlir/python/requirements.txt# 执行cmake、ninja等编译命令# 运行MLIR测试,例如仅通过ninja运行Python绑定测试:ninja check-mlir-python

交互式使用时,只需将编译目录下的tools/mlir/python_packages/mlir_core/加入PYTHONPATH,典型配置:

export PYTHONPATH=$(cd build && pwd)/tools/mlir/python_packages/mlir_core

若已执行安装(如ninja install),所有启用项目的Python包会位于安装目录的python_packages/下(如python_packages/mlir_core)。官方发行版使用更专用的构建配置。


设计(Design)

使用场景(Use cases)

MLIR Python绑定主要有两大核心场景:

  1. 支持用户期望安装LLVM/MLIR后,可直接import mlir并开箱即用纯Python API。

  2. 下游集成方希望将部分API纳入私有命名空间或定制库,通常与其他Python原生组件混合使用。

可组合模块(Composable modules)

为支持场景2,Python绑定被组织为可组合模块,下游集成方可按需引入并重新导出到自身命名空间。这要求遵循以下设计原则:

  • nb::module的构造/填充与NB_MODULE全局构造函数分离。

  • 为仅C++的包装类引入头文件,便于其他相关C++模块交互。

  • 将依赖可选组件的初始化逻辑分离到独立模块/依赖项(当前registerAllDialects等属于此类)。

共享库链接、分发等关联问题均受此影响。将代码拆分为可组合模块(而非单一cpp文件),可灵活应对后续各类需求。此外,pybind的模板元编程编译耗时随翻译单元内定义数量增加,拆分多个翻译单元可显著降低大表面积API的编译时间。

子模块(Submodules)

C++代码库中绝大多数对象归属于mlir命名空间。为实现模块化并提升Python绑定可读性,定义了与MLIR功能单元目录结构大致对应的子包,例如:

  • mlir.ir

  • mlir.passespass是Python保留字)

  • mlir.dialect

  • mlir.execution_engine(除命名空间隔离外,此类重量级/可选组件需独立封装)

此外,隐含可选依赖的初始化函数应放在带下划线的(名义上私有)模块(如_init)中并单独链接。这让下游集成方可完全定制默认包含的组件,覆盖方言注册、Pass注册等场景。

加载器(Loader)

LLVM/MLIR是复杂的Python原生项目,可能与其他复杂原生扩展共存。因此,原生扩展(.so/.pyd/.dylib)以私有顶层符号(_mlir)导出,同时在mlir/_cext_loader.py及同级文件中提供少量Python代码,用于加载并重新导出。

这种拆分提供了在共享库加载到Python运行时准备环境的代码入口,也为一次性初始化代码提供了独立于模块构造函数的执行位置。

建议尽量避免使用__init__.py,直到代表独立组件的叶子包。核心规则:__init__.py的存在会导致无法将该层级及以下命名空间拆分到不同目录、部署包、wheel包等。

更多说明参考:https://packaging.python.org/guides/packaging-namespace-packages/

基于C-API实现(Use the C-API)

Python API应尽可能基于C-API封装,尤其是核心、与方言无关的部分。这种绑定方式可规避跨C++ ABI边界的分发难题,同时解决基于RTTI的模块(pybind派生对象)与非RTTI多态C++代码(LLVM默认编译模式)混合使用的棘手问题。

核心IR的所有权管理(Ownership in the Core IR)

核心IR中有若干顶层类型由Python侧引用强持有

  • PyContextmlir.ir.Context

  • PyModulemlir.ir.Module

  • PyOperationmlir.ir.Operation)——有特殊说明

所有其他对象均为依赖对象,会保留对最近顶层容器对象的反向引用(保活)。依赖对象分为两类:a) 唯一化对象(生命周期与上下文一致);b) 可变对象。可变对象需要额外机制跟踪其背后C++实例是否失效(通常因IR修改、删除、批量操作导致)。

核心IR的可选参数与参数顺序(Optionality and argument ordering in the Core IR)

以下类型支持作为上下文管理器绑定到当前线程:

  • PyLocationloc: mlir.ir.Location = None

  • PyInsertionPointip: mlir.ir.InsertionPoint = None

  • PyMlirContextcontext: mlir.ir.Context = None

为支持函数参数的可组合性,这些类型作为参数时必须置于末尾,且按上述顺序、使用指定名称(通常对应特殊场景下显式传参的优先级),默认值为py::none(),通过手动/自动转换解析显式传参或线程上下文管理器的值(如DefaultingPyMlirContextDefaultingPyLocation)。

设计依据:Python中右侧尾部关键字参数可组合性最强,支持参数透传、默认值等多种用法。保持函数签名可组合,能更轻松构建领域特定语言(DSL)与高层API,减少冗余样板代码。

统一遵循该规则可实现极简IR构造风格:极少需要显式指定上下文、位置(Location)、插入点(InsertionPoint),需要精细控制时可自由指定。

操作层级(Operation hierarchy)

PyOperation特殊之处在于可处于顶层或依赖状态,生命周期单向:操作可创建为分离状态(顶层),加入另一操作后则终身为依赖状态。若操作被加入仍处于分离状态的传递父节点,需在状态转换时额外处理(所有新增子节点初始归属最外层分离操作,外层操作加入已附着操作后,子节点重新归属到容器模块)。

基于有效性与父节点管理需求,PyOperation持有区域(Region)与块(Block),且仅操作允许处于分离状态

注意:多个PyOperation对象(Python层对象)可别名指向同一mlir::Operation。例如py_op1py_op2包装同一mlir::Operation op,对op执行Pass后,通过任一Python对象遍历MLIR抽象语法树(AST)均会看到相同结果,此用法安全且受支持。不支持的场景:存在多个Python包装对象时使操作失效,随后操作这些包装对象

例如py_op1/py_op2包装根节点py_op3下的同一操作,py_op3被修改导致该操作被擦除,py_op1/py_op2即变为“未定义”状态,任何操作均被严格禁止。符号表(SymbolTable)修改同理,视为对根符号表操作的修改。

最佳实践建议按以下结构编码:

  1. 先查询/操作各类Python包装对象(py_op1py_op2py_op3等);

  2. 再通过单一根对象执行AST修改/操作擦除等;

  3. 使所有查询节点失效(如op._set_invalid())。

理想情况下在函数体内完成,使步骤3对应函数结束,避免Python包装对象泄漏/过度存活。简言之:按嵌套层级修改,先修改叶子节点再向上层操作,极少情况下在修改父节点后再查询嵌套操作。

C/C++ API允许Region/Block分离,Python API消除该可能性以简化所有权模型,使Region/Block完全依赖所属操作管理。Python的Region/Block实例与底层MlirRegion/MlirBlock的别名无害,且这些对象不会像操作一样在上下文内驻留。

若后续需重新引入分离的Region/Block,可新增DetachedRegion等类实现,避免复杂度。当前设计无需为Region/Block维护全局存活列表,未来若需操作本地列表可按需扩展。


用户级API(User-level API)

上下文管理(Context Management)

绑定依赖Python上下文管理器(with语句)简化IR对象创建与处理,省略重复传参(如MLIR上下文、操作插入点、位置)。上下文管理器为同线程内后续所有绑定调用设置默认对象,特定调用可通过专用关键字参数覆盖默认值。

MLIR上下文(MLIR Context)

MLIR上下文是持有属性与类型的顶层实体,几乎所有IR结构都会引用它,同时在C++层提供线程安全保障。Python绑定中,MLIR上下文也是Python上下文管理器,示例:

from mlir.ir import Context, Modulewith Context() as ctx:# 使用ctx作为上下文构造IR# 从字符串解析MLIR模块需要上下文  Module.parse("builtin.module {}")

引用上下文的IR对象通常通过.context属性访问上下文。多数IR构造函数要求以某种方式传入上下文:属性与类型可从包含的属性/类型提取上下文;操作统一从位置(Location)提取上下文;无法从参数提取时,API要求传入context关键字参数,未提供或为None(默认)时,从绑定维护的当前线程隐式上下文栈查找,无上下文则抛出错误。

上下文管理器内外均可手动指定MLIR上下文:

from mlir.ir import Context, Modulestandalone_ctx = Context()with Context() as managed_ctx:# 在managed_ctx中解析模块  Module.parse("...")# 在standalone_ctx中解析模块(覆盖上下文管理器)  Module.parse("...", context=standalone_ctx)# 不使用上下文管理器解析模块Module.parse("...", context=standalone_ctx)

只要存在引用上下文的IR对象,上下文对象就会保持存活。

插入点与位置(Insertion Points and Locations)

构造MLIR操作需要两个关键信息:

  • 插入点:指定操作创建在IR的区域/块/操作结构中的位置(通常在另一操作前后或块末尾);可省略,此时操作创建为分离状态

  • 位置:包含操作来源的用户可读信息(如文件/行/列),必须提供,且持有MLIR上下文引用。

两者均可通过上下文管理器或操作构造函数的关键字参数(ip/loc)显式传入,上下文管理器内外均生效。

from mlir.ir import Context, InsertionPoint, Location, Module, Operationwith Context() as ctx:  module = Module.create()# 准备向模块体插入操作,指定操作来源为f.mlir文件42行1列with InsertionPoint(module.body), Location.file("f.mlir", line=42, col=1):# 操作插入到模块体末尾,使用上下文管理器设置的位置    Operation(<...>)# 操作插入到模块体末尾(前一操作之后),使用关键字参数指定位置    Operation(<...>, loc=Location.file("g.mlir", line=1, col=10))# 操作插入到块开头而非末尾    Operation(<...>, ip=InsertionPoint.at_block_begin(module.body))

构造位置(Location)需要MLIR上下文,可从当前线程上下文管理器获取,或显式传入:

from mlir.ir import Context, Location# 同一with语句创建上下文与对应位置with Context() as ctx, Location.file("f.mlir", line=42, col=1, context=ctx):pass

位置由上下文持有,只要被Python代码(传递)引用就会存活。

与位置不同,构造操作时可省略插入点(或设为None/False),此时操作创建为分离状态——未加入其他操作的区域,由调用者持有。顶层IR容器(如模块)通常为此状态。操作包含的区域、块、值会反向引用并保活该操作。

查看IR对象(Inspecting IR Objects)

查看IR是Python绑定的核心功能,可遍历IR的操作/区域/块结构,检查操作属性、值类型等特征。

操作、区域与块(Operations, Regions and Blocks)

操作有两种表示形式:

  • 通用Operation类:适合未注册操作的通用处理;

  • OpView特定子类:提供更语义化的操作属性访问器。

OpView子类可通过.operation属性获取OperationOperation可通过.opview属性获取对应OpView(前提是加载对应方言的Python模块)。默认遍历IR树时返回OpView形式。

可通过Pythonisinstance判断操作类型:

operation = <...>opview = <...>ifisinstance(operation.opview, mydialect.MyOp):passifisinstance(opview, mydialect.MyOp):pass

可通过属性检查操作组成部分:

  • attributes:操作属性集合,支持字典与序列下标访问(如operation.attributes["value"]/operation.attributes[0]),按序列遍历属性时不保证顺序。

  • operands:操作操作数序列集合。

  • results:操作结果序列集合。

  • regions:操作附加区域序列集合。

操作数与结果对象拥有.types属性,存储对应值的类型序列。

from mlir.ir import Operationoperation1 = <...>operation2 = <...>if operation1.results.types == operation2.operand.types:pass

特定操作的OpView子类提供更简洁的属性访问器,例如命名属性、操作数、结果可直接作为子类属性访问(operation.const_value替代operation.attributes["const_value"])。若名称为Python保留字,添加下划线后缀。

操作本身可迭代,按顺序访问附加区域:

from mlir.ir import Operationoperation = <...>for region in operation:  do_something_with_region(region)

区域在概念上是块的序列,Region对象可迭代访问块,也可使用.blocks属性。

# 区域可直接迭代访问块for block1, block2 inzip(operation.regions[0], operation.regions[0].blocks)assert block1 == block2

块包含操作序列,另有若干附加属性。Block对象可迭代访问内部操作,.operations属性效果相同。块的参数列表可通过.arguments序列集合访问。

Python绑定中,块与区域归属于父操作并保活该操作,可通过.owner属性访问所属操作。

属性与类型(Attributes and Types)

属性与类型大多是上下文持有的不可变对象,有两种表示形式:

  • 不透明Attribute/Type对象:支持打印与比较;

  • 具体子类:可访问属性/类型的内部特征。

Attribute/Type对象可通过子类构造函数转为具体子类,类型不匹配时抛出ValueError

from mlir.ir import Attribute, Typefrom mlir.<dialect> import ConcreteAttr, ConcreteTypeattribute = <...>type = <...>try:  concrete_attr = ConcreteAttr(attribute)  concrete_type = ConcreteType(type)except ValueError as e:# 处理类型不匹配

具体属性/类型类提供静态isinstance方法,判断不透明对象能否向下转型:

from mlir.ir import Attribute, Typefrom mlir.<dialect> import ConcreteAttr, ConcreteTypeattribute = <...>type = <...># 无需处理错误if ConcreteAttr.isinstance(attribute):  concrete_attr = ConcreteAttr(attribute)if ConcreteType.isinstance(type):  concrete_type = ConcreteType(type)

与操作不同,遍历IR时默认返回不透明Attribute/Type,需要手动向下转型。

具体属性/类型类通常将内部特征暴露为Python只读属性,例如张量类型的元素类型可通过.element_type访问。

值(Values)

MLIR值分为两类:块参数(BlockArgument)与操作结果(OpResult)。值的处理与属性/类型类似,有两种表示:

  • 通用Value对象;

  • 具体BlockArgument/OpResult对象。

通用Value提供比较、类型访问、打印等基础功能;具体子类可访问定义块/操作及值在其中的位置。遍历IR时默认返回通用Value,向下转型方式与属性/类型一致:

from mlir.ir import BlockArgument, OpResult, Valuevalue = ...# 转为具体值子类try:  concrete = BlockArgument(value)except ValueError:# 值必为块参数或操作结果,此处不会再抛出ValueError  concrete = OpResult(value)

接口(Interfaces)

MLIR接口是无需知晓操作具体类型、仅依赖部分特征即可与IR交互的机制。操作接口在Python中以与C++同名的类提供,可从以下对象构造:

  • Operation/OpView子类对象:可调用所有接口方法;

  • OpView子类+上下文:仅可调用静态接口方法(无关联操作)。

构造时若操作类在指定上下文未实现该接口,抛出ValueError。MLIR上下文可通过外层上下文管理器设置。

from mlir.ir import Context, InferTypeOpInterfacewith Context():  op = <...># 尝试将操作转为接口try:    iface = InferTypeOpInterface(op)except ValueError:print("Operation does not implement InferTypeOpInterface.")raise# 从Operation/OpView构造的接口对象可调用所有方法  iface.someInstanceMethod()# 也可从OpView子类构造接口,需指定上下文(显式/上下文管理器)try:    iface = InferTypeOpInterface(some_dialect.SomeOp)except ValueError:print("SomeOp does not implement the interface.")raise# 从类构造的接口对象调用实例方法会抛出TypeErrortry:    iface.someInstanceMethod()except TypeError:pass# 仍可调用静态接口方法  iface.inferOpReturnTypes(<...>)

若接口对象从Operation/OpView构造,可通过.operation/.opview属性访问原对象。

当前Python绑定仅提供部分操作接口,属性与类型接口暂未支持。

创建IR对象(Creating IR Objects)

Python绑定支持IR的创建与修改。

操作、区域与块(Operations, Regions and Blocks)

创建操作需要位置(Location)与可选插入点(InsertionPoint)。批量创建操作时,使用上下文管理器指定位置与插入点更便捷。

具体操作可通过对应OpView子类构造函数创建,默认构造函数参数:

  • 操作结果类型序列(可选,results);

  • 操作操作数值序列/产生该值的另一操作(可选,operands);

  • 操作属性字典(可选,attributes);

  • 后继块序列(可选,successors);

  • 附加区域数量(默认0,regions);

  • 关键字参数loc:操作位置,未指定则使用最近上下文管理器的位置,无则抛异常;

  • 关键字参数ip:插入点,未指定则使用最近上下文管理器的插入点,无则创建为分离状态。

多数操作会自定义构造函数,仅保留相关参数。例如无结果操作可省略results,结果类型可从操作数类型唯一推导的操作也可省略。示例:内置函数操作可通过函数名、参数类型、结果类型元组构造。

from mlir.ir import Context, Modulefrom mlir.dialects import builtinwith Context():  module = Module.create()with InsertionPoint(module.body), Location.unknown():    func = func.FuncOp("main", ([], []))

也可通过通用Operation.create基于操作标准字符串名构造,参数与OpView默认构造函数一致。不推荐此方式,仅用于通用操作处理。

from mlir.ir import Context, Modulefrom mlir.dialects import builtinwith Context():  module = Module.create()with InsertionPoint(module.body), Location.unknown():# 通用方式创建操作    func = Operation.create("func.func", results=[], operands=[],        attributes={"function_type":TypeAttr.get(FunctionType.get([], []))},        successors=None, regions=1)# 若可用,结果会向下转型为具体OpView子类assertisinstance(func, func.FuncOp)

区域在C++侧构造操作时创建,Python中不可直接构造,且不允许脱离操作存在(C++支持分离区域)。

块可在指定区域内创建,并插入到同区域另一块之前/之后,使用Block类的create_before()/create_after()方法,或静态方法create_at_start()。块不允许脱离区域存在(C++支持分离块)。

from mlir.ir import Block, Context, Operationwith Context():  op = Operation.create("generic.op", regions=1)# 在区域创建第一个块  entry_block = Block.create_at_start(op.regions[0])# 创建后续块  other_block = entry_block.create_after()

块可用于创建插入点(InsertionPoint),指向块开头、末尾或终止符之前。OpView子类通常提供.body属性用于构造插入点,例如内置ModuleFuncOp提供.body.add_entry_blocK()

属性与类型(Attributes and Types)

属性与类型可通过上下文(Context)或已持有上下文的其他属性/类型对象创建。为标识其由上下文持有,通过具体属性/类型类的静态get方法获取,参数为构造所需数据,无法从其他参数推导上下文时需显式传入context关键字参数。

from mlir.ir import Context, F32Type, FloatAttr# 属性与类型需要MLIR上下文,直接传入或通过其他上下文持有对象获取ctx = Context()f32 = F32Type.get(context=ctx)pi = FloatAttr.get(f32, 3.14)# 可使用外层上下文管理器设置的上下文with Context():  f32 = F32Type.get()  pi = FloatAttr.get(f32, 3.14)

部分属性提供额外构造方法以提升可读性:

from mlir.ir import Context, IntegerAttr, IntegerTypewith Context():  i8 = IntegerType.get_signless(8)  IntegerAttr.get(i8, 42)

内置属性常可从结构相似的Python类型直接构造,例如ArrayAttr从属性序列构造,DictAttr从字典构造:

from mlir.ir import ArrayAttr, Context, DictAttr, UnitAttrwith Context():  array = ArrayAttr.get([UnitAttr.get(), UnitAttr.get()])  dictionary = DictAttr.get({"array": array, "unit": UnitAttr.get()})

可通过register_attribute_builder注册操作创建时使用的自定义属性构造器,例如I32Attr

@register_attribute_builder("I32Attr")def_i32Attr(x: int, context: Context):return IntegerAttr.get(        IntegerType.get_signless(32, context=context), x)

注册后,创建带I32Attr的操作可直接写:

foo.Op(30)

替代原写法:

foo.Op(IntegerAttr.get(IndexType.get_signless(32, context=context), 30))

注册基于ODS名称,纯Python实现。每个ODS属性类型仅允许注册一个自定义构造器(如I32Attr对应一个,可映射多个底层IntegerAttr类型)。


编码风格(Style)

MLIR核心部分的Python绑定应与底层C++结构基本同构,同时兼顾实用性与Python风格。

属性 vs get()方法(Properties vs get() methods)

优先将getContext()getName()isEntryBlock()等简单方法转为Python只读属性(如context)。绑定代码中只需使用def_prop_ro而非def,显著提升Python侧使用体验。

__repr__方法

为对象实现友好的打印表示效果极佳,合理的打印形式绑定到__repr__方法(并通过doctest验证)可大幅提升开发效率。

驼峰式(CamelCase)vs 蛇形(snake_case)

函数/方法/属性使用蛇形(snake_case),类使用驼峰式(CamelCase)。遵循PEP 8规范,让API更贴合Python生态。

优先使用伪容器(Prefer pseudo-containers)

许多核心IR结构直接在实例上提供计数、迭代器方法,优先将其提升为专用伪容器。

例如区域内的块,不推荐:

region = ...for block in region:pass

推荐:

region = ...for block in region.blocks:passprint(len(region.blocks))print(region.blocks[0])print(region.blocks[-1])

避免暴露STL风格标识符(frontback等),在绑定中转为合适的魔法方法与迭代器包装。

注意适度使用,若遇到语义复杂的场景(如块参数的查找与修改难以合理建模),直接镜像C/C++ API即可。

为通用操作提供一站式辅助函数(Provide one stop helpers for common things)

鼓励封装跨多个底层实体的一站式辅助函数,例如为Context添加parse_asm方法,避免显式构造SourceMgr。一站式辅助函数可与更完整的底层映射共存。


测试(Testing)

测试代码放在mlir/test/python目录,通常为带lit运行指令的.py文件。

使用基于litFileCheck的测试方式:

  • 生成式测试(产生IR):定义Python模块构造/打印IR,通过管道传给FileCheck

  • 解析测试:使用原始常量与合适的parse_asm调用,保持模块自包含。

  • 文件I/O代码通过临时文件处理,不依赖测试模块外的文件产物/路径。

  • 方便起见,非生成式API交互也用相同机制,按需打印并CHECK验证。

示例FileCheck测试(Sample FileCheck test)

# RUN: %PYTHON %s | mlir-opt -split-input-file | FileCheckTODO: 后续移入测试工具类defprint_module(f):  m = f()print("// -----")print("// TEST_FUNCTION:", f.__name__)print(m.to_asm())return f# CHECK-LABEL: TEST_FUNCTION: create_my_op@print_moduledefcreate_my_op():  m = mlir.ir.Module()  builder = m.new_op_builder()# CHECK: mydialect.my_operation ...  builder.my_op()return m

与ODS集成(Integration with ODS)

MLIR Python绑定与基于TableGen的ODS系统集成,为MLIR方言与操作提供易用的包装层,集成要点如下(细节略):主仓库中mlir.dialects下的构建规则与Python代码为标准使用方式。

用户需提供{方言命名空间}.py(或带__init__.py的同级目录)作为入口。

生成_{方言命名空间}_ops_gen.py包装模块(Generating _{DIALECT_NAMESPACE}_ops_gen.py wrapper modules)

每个映射到Python的方言需要生成对应的_{方言命名空间}_ops_gen.py包装模块,通过mlir-tblgen处理Python绑定专用TableGen包装文件实现,该文件包含样板代码与方言专属.td文件。以Func方言(命名空间特例为func)为例:

#ifndef PYTHON_BINDINGS_FUNC_OPS#define PYTHON_BINDINGS_FUNC_OPSinclude "mlir/Dialect/Func/IR/FuncOps.td"#endif // PYTHON_BINDINGS_FUNC_OPS

主仓库中通过CMake函数declare_mlir_dialect_python_bindings编译包装层,执行:

mlir-tblgen -gen-python-op-bindings -bind-dialect={方言命名空间} \ {PYTHON_BINDING_TD_FILE}

生成的操作类需像C++生成头文件一样,在{方言命名空间}.py中导入:

from ._my_dialect_ops_gen import *

扩展包装模块的搜索路径(Extending the search path for wrapper modules)

Python绑定查找包装模块时会查询dialect_search_path。主仓库中该路径硬编码包含mlir.dialects模块(上述构建规则输出包装层的位置)。外部方言可通过以下代码将模块加入搜索路径:

from mlir.dialects._ods_common import _cext_cext.globals.append_dialect_search_prefix("myproject.mlir.dialects")

包装模块代码组织(Wrapper module code organization)

包装模块TableGen生成器输出:

  • _Dialect类(继承mlir.ir.Dialect),带DIALECT_NAMESPACE属性;

  • 每个操作的{操作名}类(继承mlir.ir.OpView);

  • 上述类的注册装饰器。

为避免命名冲突,包装模块的所有内部名称以_ods_为前缀。

每个具体OpView子类定义若干公开属性:

  • OPERATION_NAME:字符串类型,完整操作名(如math.absf);

  • __init__方法:若操作定义/推导了默认构造器则实现;

  • 每个操作数/结果的@property getter(无名对象自动生成名称);

  • 每个声明属性的@property getter/setter/deleter。

同时输出供子类化与自定义的私有属性(默认情况使用OpView默认值,省略这些属性):

  • _ODS_REGIONS:区域数量与类型说明,当前为(最小区域数,无可变参数区域)元组。API仅做轻量校验,核心用于记录默认构造与区域访问器生成所需信息。

  • _ODS_OPERAND_SEGMENTS/_ODS_RESULT_SEGMENTS:黑盒值,标记操作数/结果的可变参数结构,用于OpView._ods_build_default解析含可变参数的操作数/结果列表。

默认构造器(Default Builder)

当前仅将单一默认构造器映射到__init__方法,意图是该__init__对应C++生成的最具体构造器,当前仅实现通用形式:

  • 每个声明结果对应一个参数:

    • 单值结果:接受mlir.ir.Type

    • 可变结果:接受List[mlir.ir.Type]

  • 每个声明操作数/属性对应一个参数:

    • 单值操作数:接受mlir.ir.Value

    • 可变操作数:接受List[mlir.ir.Value]

    • 属性:接受mlir.ir.Attribute

  • 尾部专用可选关键字参数:

    • loc:显式位置,默认使用线程绑定位置,无则抛错;

    • ip:显式插入点,默认使用线程绑定插入点。

每个OpView继承build_generic方法,支持通过(可变参数嵌套)results/operands序列构造,用于Python暂不支持的操作的默认构造,代价是签名通用化。

扩展生成的操作类(Extending Generated Op Classes)

构建系统为每个带Python绑定的方言生成_{方言命名空间}_ops_gen.py,常需以生成类为基础自定义,绑定提供便捷扩展机制:常规继承+OpView注册。例如arith.constant的默认构造器:

classConstantOp(_ods_ir.OpView):  OPERATION_NAME = "arith.constant"  _ODS_REGIONS = (0True)def__init__(self, value, *, loc=None, ip=None):    ...

要求valueTypedAttr(如IntegerAttr/FloatAttr),自然扩展是支持传入MLIR类型与Python值,实例化对应TypedAttr

from typing importUnionfrom mlir.ir importType, IntegerAttr, FloatAttrfrom mlir.dialects._arith_ops_gen import _Dialect, ConstantOpfrom mlir.dialects._ods_common import _cext@_cext.register_operation(_Dialect, replace=True)classConstantOpExt(ConstantOp):def__init__(        self, result: Type, value: Union[intfloat], *, loc=None, ip=None):ifisinstance(value, int):super().__init__(IntegerAttr.get(result, value), loc=loc, ip=ip)elifisinstance(value, float):super().__init__(FloatAttr.get(result, value), loc=loc, ip=ip)else:raise NotImplementedError(f"Building `arith.constant` not supported for {result=}{value=}")

扩展后可直接构造arith.constant

from mlir.ir import F32Typea = ConstantOpExt(F32Type.get(), 42.42)b = ConstantOpExt(IntegerType.get_signless(32), 42)

扩展机制三大要点:

  1. ConstantOpExt直接继承生成的ConstantOp

  2. 最简场景只需调用父类初始化方法super().__init__(...)

  3. @_cext.register_operation(_Dialect, replace=True)装饰类,将ConstantOpExt注册为mlir.ir.Operation.opview返回的首选OpView必须指定replace=True

复杂场景需通过OpView.build_generic显式构造(同生成构造器逻辑),即调用OpView.build_generic并将结果传入OpView.__init__,需调用祖父类方法,示例:

from mlir.dialects._scf_ops_gen import _Dialect, ForOpfrom mlir.dialects._ods_common import _cext@_cext.register_operation(_Dialect, replace=True)classForOpExt(ForOp):def__init__(self, lower_bound, upper_bound, step, iter_args, *, loc=None, ip=None):        ...super(ForOp, self).__init__(self.build_generic(...))

此处通过super(ForOp, self).__init__调用OpView.__init__,也可直接写OpView.__init__


为方言提供Python绑定(Providing Python bindings for a dialect)

Python绑定设计支持MLIR开放方言生态,方言可作为mlir.dialects子模块暴露给Python,与其他绑定互通。

仅含操作的方言只需提供操作的Python API,大部分样板代码可从ODS生成。

含属性与类型的方言需通过C API对接,无通用创建机制。

Pass需在上下文注册,才能在文本格式的Pass管理器中使用,可在Python模块加载时完成。

其他功能可参考属性/类型,暴露对应C API并封装Python API。

操作(Operations)

方言操作通过为通用mlir.ir.Operation包装操作专属构造函数与属性提供Python支持,无需单独实现C API。

ODS定义的操作通过mlir-tblgen -gen-python-op-bindings -bind-dialect=<方言命名空间>从声明式描述生成Python API。只需新建.td文件包含原ODS定义,作为mlir-tblgen输入源,此类文件放在python/mlir/dialects/

mlir-tblgen输出按约定命名为_<方言命名空间>_ops_gen.py。生成的操作类可按上述方式扩展。MLIR提供CMake函数自动化生成。

最后创建python/mlir/dialects/<方言命名空间>.pypython/mlir/dialects/<方言命名空间>/__init__.py,导入生成文件,支持import mlir.dialects.<方言命名空间>

属性与类型(Attributes and Types)

方言属性与类型分别作为mlir.ir.Attributemlir.ir.Type的子类提供Python支持。属性/类型的Python API必须对接对应的C API(需先实现)。

Attribute/Type子类的绑定可通过include/mlir/Bindings/Python/PybindAdaptors.hinclude/mlir/Bindings/Python/NanobindAdaptors.h工具定义,模仿pybind11/nanobind API。

绑定放在独立模块,工具自动实现C API句柄MlirAttribute/MlirType与Python对象的转换,绑定实现可直接使用C API句柄。

绑定的方法与属性遵循上述风格原则。

方言的属性/类型绑定可放在lib/Bindings/Python/Dialect<名称>.cpp,编译为独立“Python扩展”库,放到python/mlir/_mlir_libs,Python运行时加载。MLIR提供CMake函数自动化生成。

该库需在方言主文件(python/mlir/dialects/<方言命名空间>.py/__init__.py)中import,确保从Python加载方言时类型可用。

Pass(Passes)

方言专属Pass需在上下文注册,才能在Python的Pass管理器中使用,依赖从文本解析Pass管道的API。

实现方式:新建nanobind模块(lib/Bindings/Python/<方言>Passes.cpp),调用C API注册(需先实现)。

TableGen声明式定义的Pass,通过mlir-tblgen -gen-pass-capi-header-mlir-tblgen -gen-pass-capi-impl自动生成C API。

nanobind模块编译为独立“Python扩展”库,可在方言主文件导入,或放到独立passes子模块(python/mlir/dialects/<方言命名空间>/passes.py),避免随方言默认加载。

其他功能(Other functionality)

方言的非IR对象/Pass功能(如辅助函数)可参考属性/类型暴露给Python。需先实现对应C API,再通过pybind11+PybindAdaptors.h或nanobind+NanobindAdaptors.h封装,对接Python API。

绑定可放在独立模块或与属性/类型同模块,随方言加载。


在Python中扩展MLIR(Extending MLIR in Python)

MLIR Python绑定支持在Python中定义自定义组件,主要包括方言、Pass、重写模式,各部分实现方式如下。

方言(Dialects)

可通过Python的IRDL方言绑定定义方言,IRDL绑定提供load_dialects函数,将包含irdl.dialect操作的MLIR模块转为MLIR方言。详情参考IRDL方言文档。

Pass(Passes)

可通过PassManager.add API将Python可调用对象定义为Pass,内部包装为mlir::PassPassManager.run时作为Pass管道执行。

可调用对象的op参数为当前待转换操作,pass_参数提供当前Pass对象的访问,支持signalPassFailure()等操作。

可调用对象的生命周期至少延长到PassManager销毁。示例:

defdemo_pass(op, pass_):# 处理传入的oppasspm = PassManager('any')pm.add(demo_pass)pm.add('some-cpp-defined-passes')...pm.run(some_op)

重写模式(Rewrite Patterns)

可通过mlir.rewrite.RewritePatternSetadd方法注册重写模式,参数为待重写的操作类型与定义“匹配-重写”逻辑的Python可调用对象。

Python可调用对象需保证:匹配成功才执行重写,对应返回值可转为False

RewritePatternSet可通过freeze方法转为FrozenRewritePatternSet,通过贪心模式驱动应用到操作:apply_patterns_and_fold_greedily。典型用法:

defto_muli(op, rewriter):with rewriter.ip:        new_op = arith.muli(op.lhs, op.rhs, loc=op.location)    rewriter.replace_op(op, new_op)patterns = RewritePatternSet()patterns.add(arith.AddIOp, to_muli)  # 将arith.addi重写为arith.mulipatterns.add(...)frozen = patterns.freeze()module = ...apply_patterns_and_fold_greedily(module, frozen)

PDL方言绑定支持在Python中定义生成重写模式,mlir.rewrite.PDLModule接收包含pdl.pattern操作的模块,通过freeze方法转为FrozenRewritePatternSet,再通过贪心重写驱动应用到操作。详情参考PDL方言文档。


无全局解释器锁(无GIL)支持(Free-threading (No-GIL) support)

无GIL支持指CPython解释器(≥3.13)关闭全局解释器锁,详情参考PEP-703与Python无GIL指南。

MLIR Python绑定兼容无GIL(存在例外),安全场景:独立上下文的多线程操作。安全用法示例:

# python3.13t example.pyimport concurrent.futuresimport mlir.dialects.arith as arithfrom mlir.ir import Context, Location, Module, IntegerType, InsertionPointdeffunc(py_value):with Context() as ctx:        module = Module.create(loc=Location.file("foo.txt"00))        dtype = IntegerType.get_signless(64)with InsertionPoint(module.body), Location.name("a"):            arith.constant(dtype, py_value)return modulenum_workers = 8with concurrent.futures.ThreadPoolExecutor(max_workers=num_workers) as executor:    futures = []for i inrange(num_workers):        futures.append(executor.submit(func, i))assertlen(list(f.result() for f in futures)) == num_workers

无GIL兼容例外(线程不安全):

  • IR打印(如PassManager启用enable_ir_printing(),调用线程不安全的llvm::raw_ostream);

  • Location.emit_error使用;

  • Module.dump使用;

  • mlir.dialects.transform.interpreter使用;

  • mlir.dialects.gpugpu-module-to-binary使用。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-04-20 01:37:02 HTTP/2.0 GET : https://f.mffb.com.cn/a/485024.html
  2. 运行时间 : 0.089076s [ 吞吐率:11.23req/s ] 内存消耗:4,710.07kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=2756046b118de78358a9358018d2f7f8
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000559s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000575s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000800s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.001641s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000529s ]
  6. SELECT * FROM `set` [ RunTime:0.000197s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000581s ]
  8. SELECT * FROM `article` WHERE `id` = 485024 LIMIT 1 [ RunTime:0.000507s ]
  9. UPDATE `article` SET `lasttime` = 1776620222 WHERE `id` = 485024 [ RunTime:0.003694s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000226s ]
  11. SELECT * FROM `article` WHERE `id` < 485024 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.001201s ]
  12. SELECT * FROM `article` WHERE `id` > 485024 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000366s ]
  13. SELECT * FROM `article` WHERE `id` < 485024 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002832s ]
  14. SELECT * FROM `article` WHERE `id` < 485024 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.000882s ]
  15. SELECT * FROM `article` WHERE `id` < 485024 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000817s ]
0.090762s