MLIR Python绑定
当前状态:正在开发中,默认情况下未启用
build
前提条件
• 相对较新的Python3安装
• pybind11 必须已安装,可被CMake定位(如果通过进行安装,则会自动检测到 python -m pip install pybind11)。注意:所需的最低版本::2.6.0。
CMake的变量
• MLIR_BINDINGS_PYTHON_ENABLED:BOOL
启用构建Python绑定的功能。默认为OFF。
• Python3_EXECUTABLE:STRING
指定python用于LLVM构建的可执行文件,包括用于确定Python绑定的header/link flags标志的可执行文件。在具有多个Python实现的系统上,python3强烈建议将其显式设置为可执行文件首选。
• MLIR_PYTHON_BINDINGS_VERSION_LOCKED:BOOL
将本机扩展链接到Python运行时库,该库在某些平台上是可选的。虽然将此设置为OFF可以带来更大的部署灵活性,但通过这种方式的链接,linker可以报告所有平台上未解析符号的编译时错误,从而使开发工作流程更加顺畅。默认为ON。
推荐的开发实践
建议使用python虚拟环境。存在许多方法,但是以下是最简单的方法:

Make sure your ‘python’ is what you expect. Note that on multi-python

systems, this may have a version suffix, and on many Linuxes and MacOS where

python2 and python3 co-exist, you may also want to use python3.

which python
python -m venv ~/.venv/mlirdev
source ~/.venv/mlirdev/bin/activate

Now the python command will resolve to your virtual environment and

packages will be installed there.

python -m pip install pybind11 numpy

Now run cmake, ninja, et al.

为了进行交互使用,将python目录中的 build/目录添加到中就足够了PYTHONPATH。通常:
export PYTHONPATH=$(cd build && pwd)/python
设计
用例
MLIR python绑定可能有两个主要用例:

  1. 支持用户,期望LLVM / MLIR的已安装版本,能够以import mlir纯开箱即用的方式提供使用API的能力。
  2. 下游集成可能希望将API的某些部分,包含在其私有名称空间或特制的库中,可能将其与其它python本地位混合。
    组合模块
    为了支持用例2,Python绑定被组织成可组合的模块,下游集成商可以包括这些模块,并在需要时将其重新导出到自己的名称空间中。这迫使几个设计要点:
    • 将a的构造/填充py::module与PYBIND11_MODULE 全局构造器分开。
    • 为仅C ++的包装器类引入 headers,因为其它相关的C ++模块将需要与之互操作。
    • 将所有依赖于可选组件的初始化例程,分成自己的模块/依赖关系(当前,诸如此类之registerAllDialects类)。
    共享库链接,issues问题等许多与之相关的问题都会影响到这些因素。将代码组织到可组合的模块中(相对于整体cpp文件),可以灵活地随时间推移解决其中的许多问题。同样,pybind标尺中所有模板元编程的编译时间,与在翻译单元中定义的内容数量成比例。分成多个翻译单元可以极大地帮助大表面积API的编译时间。
    子模块
    通常,C ++代码库将大多数内容都mlir命名为命名空间。但是,为了模块化并使Python绑定更易于理解,定义了sub-packages,这些sub-packages大致映射到MLIR中功能单元的目录结构。
    例子:
    • mlir.ir
    • mlir.passes(pass是保留字:()
    • mlir.dialect
    • mlir.execution_engine (除了命名空间外,重要的是将这样的“庞大” /可选部分隔离开来)
    另外,暗示可选依赖项的初始化函数应放在带下划线的(概念上是私有的)模块中,例如_init和分别链接在一起。这使下游集成商可以完全自定义“盒子”中包含的内容,并涵盖 dialect注册,通行证注册等内容。
    load
    LLVM / MLIR是一个非平凡的python本机项目,很可能与其它非平凡的本机扩展共存。这样,本机扩展(即 .so/ .pyd/ .dylib)将作为概念上专用的顶级符号(mlir)导出,同时在mlir/cext_loader.py和同级中,提供了一小套Python代码,以加载和重新导出它。这种拆分为在共享库加载到Python运行时之前准备环境所需的代码提供了一个放置场所,并且还提供了一个一次性的初始化代码可以与模块构造函数一起调用的地方。
    建议避免使用__init.py文件,直到到达represents 离散组件的叶包为止。要记住的规则是,init.py文件的存在,会阻止将名称空间中该级别或更低级别的任何内容拆分为不同的目录,部署程序包,驱动程序等的功能。
    请参阅文档以获取更多信息和建议:https: //packaging.python.org/guides/packaging-namespace-packages/
    使用C-API
    Python API应该尽可能地在C-API之上分层。特别是对于核心的,与 dialect无关的部分,这种绑定可以实现跨越C ++ ABI边界的困难或不可能的打包决策。此外,以这种方式进行分解,可以避免将基于RTTI的模块(pybind派生的东西)与非RTTI多态C ++代码(LLVM的默认编译模式)结合在一起时,出现的一些非常棘手的问题。
    核心IR中的所有权Ownership
    核心IR中有几种顶级类型,python-side引用对此具有很强的所有权:
    • PyContext(mlir.ir.Context)
    • PyModule(mlir.ir.Module)
    • PyOperation(mlir.ir.Operation)-但有警告
    所有其它对象都是相关的。所有对象都对其最接近的顶级对象保持反向引用(保持活动状态)。此外,从属对象分为两类:a)唯一的(在上下文的生存期内生存)和b)可变的。可变对象需要其它机制,跟踪支持其Python对象的C ++实例,何时不再有效(通常是由于IR,删除或批量操作的某些特定突变)。
    核心IR中的可选性和参数排序
    以下类型支持作为上下文管理器绑定到当前线程:
    • PyLocation(loc: mlir.ir.Location = None)
    • PyInsertionPoint(ip: mlir.ir.InsertionPoint = None)
    • PyMlirContext(context: mlir.ir.Context = None)
    为了支持函数自变量的可组合性,当这些类型作为自变量出现时,应始终排在最后,并以上述顺序和给定名称显示(通常这是在特殊情况下,需要明确表示顺序)。每个都应带有默认值,py::none()并使用手动或自动转换,使用显式值或线程上下文管理器中的值(即DefaultingPyMlirContext或 DefaultingPyLocation)进行解析。
    这样做的理由是,在Python中,最右边的关键字参数是可组合的,从而启用了各种策略,例如kwarg传递,默认值等。使功能签名保持可组合性增加了有趣的DSL和更高级别的API可以提供的机会。不需要很多 exotic boilerplate.的样板就可以建造。
    始终使用,可以实现一种IR构造样式,该样式很少需要使用显式上下文,位置或插入点,但是在需要额外控制时可以随意使用。
    操作层次
    如上所述,PyOperation它是特殊的,因为它可以存在于顶层状态或从属状态。生命周期是单向的:可以分离创建操作(顶层),然后将其添加到另一个操作中,然后在整个生命周期中依赖。当考虑将操作添加到仍然分离的可传递父级的构造场景时,情况更加复杂,需要在此类过渡点处进行进一步核算(即,最初将所有此类添加的子级与最外层的父级一起添加到IR中分离操作,一旦将其添加到附加操作中,则需要将重新父级化到包含模块。
    由于有效性和parenting accounting的需要,PyOperation是区域和块的所有者,并且需要是可以不依赖别名的顶级类型。这让做一些事情,例如在发生突变时有选择地使实例无效,而不必担心层次结构中的同一操作具有某些别名。操作也是唯一一个允许处于分离状态的实体,并且在上下文级别进行检查,因此mlir.ir.Operation唯一的Python对象永远不会超过一个MlirOperation,无论如何获取它。
    C / C ++ API允许还分离Region / Block,大大简化了所有权模型,从而消除了该API中的这种可能性,从而使Region / Block完全依赖于其自己的记帐操作。Python Region/Block实例对基础 MlirRegion/的别名MlirBlock被认为是良性的,并且这些对象不会在上下文中被插入(与操作不同)。
    如果想重新引入分离的区域/块,则可以使用新的“ DetachedRegion”类或类似的类来这样做,并且还可以避免accounting的复杂性。通过现在的方式,可以避免拥有区域和街区的全局实时列表。可能最终需要在待定的某个时间点获得一个操作本地的操作,具体取决于保证突变如何与其Python对等对象进行交互的难度。当到达那座桥时,可以轻松地越过那座桥。
    纯粹从Python API使用模块时,无论如何都不能使用别名,因此可以将其用作顶级引用类型,而无需使用活动列表进行内部访问。如果API曾经更改过以至于无法保证(例如,通过封送本机定义的模块),那么也将需要一个活动表。
    样式
    通常,对于MLIR的核心部分,Python绑定应与底层C ++结构在很大程度上是同构的。但是,出于实用性或为了使生成的库具有适当的“ Pythonic”风格而做出让步。
    属性vs get *()方法
    通常有利于转换琐碎的方法,如getContext(),getName(), isEntryBlock()等,以只读的Python性质(即context)。这主要是在绑定代码中调用def_property_readonlyvs的问题,这def使Python方面感觉更好。
    例如,prefer:
    m.def_property_readonly(“context”, …)
    Over:
    m.def(“getContext”, …)
    repr methods
    具有良好打印表示的东西真的很棒:)如果有合理的打印形式,将其连接到__repr__方法(并使用doctest进行验证 )可以大大提高生产率。
    CamelCase vs snake_case
    在中命名函数/方法/属性snake_case和中的类CamelCase。作为对Python风格的机械让步,这可以使API感觉很适合与Python环境中的同等对象相去甚远。
    如有疑问,请选择可与其它PEP 8样式名称正确配合使用的名称 。
    Prefer pseudo-containers
    许多核心IR构造直接在实例上提供方法来查询计数和开始/结束迭代器。最好将其吊起使用专用的伪容器。
    例如,可以通过以下方式完成区域内块的直接映射:
    region = …

for block in region:

pass
但是,首选这种方式:
region = …

for block in region.blocks:

pass

print(len(region.blocks))
print(region.blocks[0])
print(region.blocks[-1])
不要泄漏STL派生的标识符(front,back等),而是将转换__dunder__为绑定中的适当方法和迭代器包装器。
注意,这可能会做得太远,使用良好的判断力。例如,块参数可能看起来像容器,具有用于查找和突变的定义方法,如果不使语义复杂化,将很难正确地对其进行建模。如果遇到这些问题,只需镜像C / C ++ API。
为常见问题提供一站式帮助器helpers
在多个低层实体上聚集的一站式帮助者会非常有用,并且在合理范围内会受到鼓励。例如,使 Context具有parse_asm或避免显式构造SourceMgr的等效项可能很好。一站式助手不必与支持结构的更完整映射相互排斥。
测试
测试应该添加到test/Bindings/Python目录中,并且通常应该是.py运行状态良好的文件。
使用lit和FileCheck基础的测试:
• 对于生成测试(产生IR的测试),请定义一个Python模块,该模块构造/打印IR并将其通过管道传递FileCheck。
• 通过使用原始常量和适当的parse_asm调用,解析应保持在被测模块内是自包含的。
• 与依赖测试模块外部的文件工件/路径相比,任何文件I / O代码都应通过tempfile进行暂存。
• 为了方便起见,还使用相同的机制(CHECK根据需要打印和记录)来测试非生成式API交互。
样本FileCheck测试

RUN: %PYTHON %s | mlir-opt -split-input-file | FileCheck

TODO: Move to a test utility class once any of this actually exists.

def print_module(f):
m = f()
print("// -----")
print("// TEST_FUNCTION:", f.name)
print(m.to_asm())
return f

CHECK-LABEL: TEST_FUNCTION: create_my_op

@print_module
def create_my_op():
m = mlir.ir.Module()
builder = m.new_op_builder()

CHECK: mydialect.my_operation …

builder.my_op()
return m
与ODS集成
MLIR Python绑定与基于tablegen的ODS系统集成在一起,可为MLIR的 dialect和操作提供用户友好的包装器。集成有多个部分,概述如下。大部分细节都被删除了:有关mlir.dialects 使用此工具的规范方法,请参考下面的构建规则和python源代码。
用户负责提供一个{DIALECT_NAMESPACE}.py(或与__init__.py文件等效的目录)作为入口点。
生成_{DIALECT_NAMESPACE}ops_gen.py包装器模块
每个与python映射的 dialect都需要
{DIALECT_NAMESPACE}_ops_gen.py创建一个适当的 包装器模块。这是通过调用mlir-tblgen特定于python绑定的tablegen包装器来完成的,该包装器包括样板td文件和实际的 dialect特定文件。的示例StandardOps(std为特例分配了名称空间):
#ifndef PYTHON_BINDINGS_STANDARD_OPS
#define PYTHON_BINDINGS_STANDARD_OPS

include “mlir/Bindings/Python/Attributes.td”
include “mlir/Dialect/StandardOps/IR/Ops.td”

#endif
在主存储库中,构建包装器是通过CMake函数完成的,该函数 add_mlir_dialect_python_bindings调用:
mlir-tblgen -gen-python-op-bindings -bind-dialect={DIALECT_NAMESPACE}
{PYTHON_BINDING_TD_FILE}
必须以{DIALECT_NAMESPACE}.py类似于C ++生成的代码包含生成的 headers的方式将生成的op类包含在文件中:
from ._my_dialect_ops_gen import *
扩展包装模块的搜索路径
当python绑定需要定位包装器模块时,会参考 dialect_search_path并使用它来查找适当命名的模块。对于主存储库,此搜索路径经过硬编码以包含mlir.dialects模块,而该 模块是abobe构建规则在其中发出包装器的位置。树外 dialect,并通过调用以下命令将其模块添加到搜索路径中:
mlir.cext.append_dialect_search_prefix(“myproject.mlir.dialects”)
包装器模块代码组织
包装器模块tablegen发射器输出:
• 甲_Dialect类(延伸mlir.ir.Dialect)与DIALECT_NAMESPACE 属性。
• {OpName}每个操作的类(扩展mlir.ir.OpView)。
• 以上每个装饰器均要在系统中注册。
注意:为了避免命名冲突,包装模块使用的所有内部名称均以前缀_ods

每个具体的OpView子类进一步定义了几个公共属性:
• OPERATION_NAME属性具有str完全限定的操作名称(即std.absf)。
• __init__用于缺省构建器的方法(如果为该操作定义或推断了一个方法)。
• @property 每个操作数或结果的getter(使用自动生成的名称表示每个操作数的未命名)。
• @property 每个声明的属性的getter,setter和Deleter。
它还会发出用于子类化和自定义的其它专用属性(默认情况下,省略这些属性,而使用on的默认值OpView):
• _ODS_REGIONS:有关区域数量和类型的规范。当前的元组为(min_region_count,has_no_variadic_regions)。请注意,API对此进行了一些简单的验证,但主要目的是捕获足够的信息以执行其它默认的构建和区域访问器生成。
• _ODS_OPERAND_SEGMENTS和_ODS_RESULT_SEGMENTS:黑盒值,指示关于变量的操作数或结果的结构。用于OpView._ods_build_default对包含列表的操作数和结果列表进行解码。
builders
当前,只有一个默认的构建器映射到该__init__方法。目的是该__init__方法represents 通常为C ++生成的最具体的构建器。但是目前它只是下面的通用形式。
• 每个声明的结果有一个参数:
o 对于单值结果:每个将接受一个mlir.ir.Type。
o 对于可变结果:每个将接受一个List[mlir.ir.Type]。
• 每个声明的操作数或属性有一个参数:
o 对于单值操作数:每个将接受一个mlir.ir.Value。
o 对于可变参数操作数:每个将接受一个List[mlir.ir.Value]。
o 对于属性,它将接受mlir.ir.Attribute。
• 尾随用法特定的,可选的关键字参数:
o loc:明确mlir.ir.Location使用。默认为绑定到线程的位置(即with Location.unknown():),如果未绑定也未指定,则返回错误。
o ip:明确mlir.ir.InsertionPoint使用。默认为绑定到线程的插入点(即with InsertionPoint(…):)。
此外,每个方法都OpView继承了一种build_generic方法,该方法允许通过results和的 序列(在可变参数情况下为嵌套)进行构造operands。这可用于获取Python否则不支持的操作的一些默认构造语义,以牺牲获得非常通用的签名为代价。

MLIR Python绑定相关推荐

  1. Ubuntu16下编译安装Open Babel2.4.1和python绑定

    上一篇介绍的是CentOS 7下编译安装Open Babel2.4.1和python绑定点击打开链接 一.Open Babel简介 Open Babel是一款开源自由软件,使用Open Babel可以 ...

  2. CentOS 7下编译安装Open Babel2.4.1和python绑定

    一.Open Babel简介 Open Babel是一款开源自由软件,使用Open Babel可以将一种化学结构类型的文件格式转换成另一种文件格式,非常方便的进行各种类型的化学结构文件进行相互转换. ...

  3. python编辑svg文件_如何使用librsvg Python绑定调整svg映像文件的大小

    当光栅化svg文件时,我希望能够为生成的png文件设置宽度和高度.使用以下代码,仅将画布设置为所需的宽度和高度,具有原始svg文件尺寸的实际图像内容将呈现在(500,600)画布的左上角. impor ...

  4. python sip模块(为C和C++库创建Python绑定)

    Python的一个特性是,它具有强大的功能,它能够使用C或C++编写的现有库,并使它们成为Python扩展模块.这种扩展模块通常被称为库的绑定. SIP是一种工具,它可以很容易地为C和C++库创建Py ...

  5. Python 绑定:从 Python 调用 C 或 C++

    摘要:您是拥有想要从 Python 中使用的C或 C++ 库的 Python 开发人员吗?如果是这样,那么Python 绑定允许您调用函数并将数据从 Python 传递到C或C++,让您利用这两种语言 ...

  6. 【CGAL+Python】安装CGAL的Python绑定

    由于CGAL是由C++开发的,在Python中使用一般需要创建Python与C++程序的绑定.想了解更多Python调用C/C++程序的细节参见:Python Bindings - 从 Python ...

  7. python:绑定方法和非绑定方法

    类中定义的方法大致可以分为两类:绑定方法和非绑定方法.其中绑定方法又可以分为绑定到对象的方法和绑定到类的方法. 一.绑定方法 1.1 对象的绑定方法 在类中没有被任何装饰器修饰的方法就是 绑定到对象的 ...

  8. python绑定句柄容易么_Python 有什么奇技淫巧?

    更新一个最近发现的技巧,一行代码实现多线程/多进程,来源于python开发者微信公众号. 首先来看下代码: import urllib2 from multiprocessing.dummy impo ...

  9. Python——绑定与方法调用

    绑定与方法调用 在 Python 中,如果用实例去调用方法,这种限制就被称为 Python中的绑定(binging).没有创建实例时,方法就是未绑定的.本次的任务就是让学习者理解什么是绑定,并学会如何 ...

最新文章

  1. VGG卷积神经网络模型加载与运行
  2. C++利用cin输入时检测回车的方法
  3. 【Vegas原创】DataSet相互添加DataTable
  4. shuffleNetv2 测试
  5. 题目1176:树查找
  6. linux怎么查看fastq格式文件,2020-01-11 了解FASTQ格式并处理FASTQ文件
  7. Elasticsearch 如何把SQL转换为DSL
  8. 唐骏给李开复泼冷水:创业不可复制
  9. Java学习之数据库中的范式和反范式
  10. 阿里巴巴大数据实践—实时技术
  11. 为什么强烈推荐你使用单表查询?(续篇)
  12. 通过ISA发布服务器(二)
  13. 图解:如何修改CSDN账号昵称?
  14. 计算机联锁进路控制程序框图,计算机联锁系统技术第四章
  15. 计算机桌面常见故障,电脑常见故障问题以及解决办法
  16. jar 坐标系转换工具_谷歌百度经纬度转换
  17. 如何批量制作ITF-14条码
  18. Staking来袭,10亿级市场打开! | 火星总编时刻NO.31
  19. github网站扩展增强
  20. Hadoop的数据压缩

热门文章

  1. 2022-2028年中国金融云行业市场研究及前瞻分析报告
  2. 2022-2028年中国节能建材行业深度调研及投资前景预测报告
  3. LTV 即用户生命周期价值
  4. LeetCode简单题之检查是否所有 A 都在 B 之前
  5. RabbitMQ超详细安装教程(Linux)
  6. 如何将算子添加到Relay
  7. 用TVM在硬件平台上部署深度学习工作负载的端到端 IR 堆栈
  8. 双圆弧插值算法(一)
  9. 满足实时人工智能的计算需求
  10. 情感分析:基于循环神经网络