0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

什么是Triton-shared?Triton-shared的安装和使用

jf_pmFSk4VX 来源:GiantPandaCV 2023-12-19 09:47 次阅读

经过前面几章关于triton在nv gpu上调优的讲解,我们这章开始来看看triton的一个third_party库,该库是为了让triton去支持更多其他的backend。该项目的地址如下所示,并且已经在triton的main分支中,作为third_party进行了官方支持,在clone triton的时候,只需要带上recursive的flag就可以完成对triton-shared的使用。

什么是triton-shared?

关于triton-shared的官方具体实现,如下github repo所示:

GitHub - microsoft/triton-shared: Shared Middle-Layer for Triton Compilationgithub.com/microsoft/triton-shared

如下所示为官方对triton-shared的解释:

Asharedmiddle-layerfortheTritonCompiler.

Currentlythemiddlelayerisnotcompletebuthasenoughfunctionalitytodemonstratehowitcanwork.ThegeneralideaisthatTritonIRisloweredintoanMLIRcoredialecttoallowittobebothsharedacrossTritontargetsaswellasallowback-endstobesharedwithotherlanguages.

Thebasicintendedarchitecturelookslikethis:

[TritonIR]->[MiddleLayer]->[HWspecificIR]

Themiddle-layerusesMLIR'sLinalgandTenorDialectsforoperationsonTritonblockvalues.OperationsonTritonpointersusetheMemrefDialect.

triton-shared其实就是为了提供一个胶水一样的中间层,通过对middle-layer的设计来方便我们的编程语言或者编译器对接到下游不同的硬件生态,因为triton自身已经把nv和amd这两个比较常见的GPU后端实现了,如果第三方的厂商想通过复用triton的前端来对自己的芯片搞一套编译flow,那么triton-shared就起到了决定性的作用。下面这个图是triton的codebase所希望支持的一个愿景,可以看出来,中间这条垂直下来的分支就是triton所支持的nv gpu的优化路线,当用户写完的triton dsl会被翻译成python的AST,然后再从AST到对应的triton dialect,从这一步开始,也就正式将用户手写的成分转到了MLIR这套生态,然后再从triton dialect进一步优化到triton gpu dialect,从trition gpu dialect开始,就走了比较标准的LLVM代码生成,从LLVM IR一路lower到PTX,再到SASS,最终可以成功运行在NV的GPU上,这套codegen的路线相比TVM等其他编译框架来说更加的激进,直接越过了nvcc compiler,从而使得整个过程都变成了透明的,对于性能优化来说带来了更多的可能。

f9381d06-9da9-11ee-8b88-92fbcf53809c.pngimg

添加图片注释,不超过 140 字(可选)

triton-shared其实主要是用来cover最右边的分支,因为熟悉MLIR的朋友都知道,在右边的分支中,Linalg dialect是一个非常重要dialect,该dialect可以去承接很多不同的backend,在主流一些backend的编译优化环节,都会将Linalg作为主要的dialect来进行上下游不同dialect之间的转换与对接。

Triton-shared的安装

Triton-shared的安装其实也很简单,只需要一开始通过recursive来clone整个triton的主分支,然后使用

exportTRITON_CODEGEN_TRITON_SHARED=1

来指明,我们在build triton整个项目的过程中需要使用到triton-shared这个第三方的库。接下来的流程按照triton官方repo的readme一步一步进行即可,有关LLVM我是使用的具体commit id下手动编译得到的llvm

LLVMcommitid:b1115f8ccefb380824a9d997622cc84fc0d84a89
Tritoncommitid:1c2d2405bf04dca2de140bccd65480c3d02d995e

为什么要选择如上两个固定的commit id,其实理由很简单,因为我前面做过一些关于triton和llvm的开发都是基于上面两个id做的,所以后面我的所有教程以及案例展示都是以这两个commit id为主进行。如果不知道怎么从0开始编译triton,可以参考我之前的教程:

科研败犬丶:OpenAI/Triton MLIR 第零章: 源码编译70 赞同 · 7 评论文章

Triton-shared的使用

讲解完了什么是triton-shared,以及triton-shared怎么安装,接下来,我们就来谈谈如何使用已经被编译好的triton-shared。当你按照我的上述流程编译好triton后,会在该路径下:

/triton/build/tools/triton-shared-opt

看到一个triton-shared-opt的可执行文件,熟悉MLIR的同学可能很快发现该方法其实就是MLIR中最基本的opt,该二进制文件可以完成从一个dialect向另外一个dialect的lowering,那么我们使用--help来看看triton-shared-opt的所有功能。如果能在终端中输出如下所示的信息,说明你的triton-shared已经全部安装完毕了。

OVERVIEW:Triton-Sharedtestdriver

AvailableDialects:arith,builtin,cf,gpu,math,scf,triton_gpu,tt
USAGE:triton-shared-opt[options]

OPTIONS:

ColorOptions:

--color-Usecolorsinoutput(default=autodetect)

Generaloptions:

--abort-on-max-devirt-iterations-reached-AbortwhenthemaxiterationsfordevirtualizationCGSCCrepeatpassisreached
--allow-unregistered-dialect-Allowoperationwithnoregistereddialects
Compilerpassestorun
Passes:
--affine-data-copy-generate-Generateexplicitcopyingforaffinememoryoperations
--fast-mem-capacity=-SetfastmemoryspacecapacityinKiB(default:unlimited)
--fast-mem-space=-Fastmemoryspaceidentifierforcopygeneration(default:1)
--generate-dma-GenerateDMAinsteadofpoint-wisecopy
--min-dma-transfer=-MinimumDMAtransfersizesupportedbythetargetinbytes
--skip-non-unit-stride-loops-Testingpurposes:avoidnon-unitstrideloopchoicedepthsforcopyplacement
--slow-mem-space=-Slowmemoryspaceidentifierforcopygeneration(default:0)
--tag-mem-space=-Tagmemoryspaceidentifierforcopygeneration(default:0)
--affine-expand-index-ops-Loweraffineoperationsoperatingonindicesintomorefundamentaloperations
--affine-loop-coalescing-Coalescenestedloopswithindependentboundsintoasingleloop
--affine-loop-fusion-Fuseaffineloopnests
...

这里先来展示

--triton-to-linalg-ConvertTritontoLinalgdialect

这个pass的使用,因为triton-shared主要就是用来做该优化的。他表示的就是将triton dialect作为输入,然后经过triton-to-linalg这个pass,将其lowering到具有相同语义的linalg dialect上,那triton dialect从哪里来得到呢?不要慌,triton-shared的repo为我们提供了很多MLIR格式的文件来方便我们使用该功能,具体路径如下:

/triton/third_party/triton_shared/test/Conversion/TritonToLinalg/*

在该教程中,我们使用dot.mlir作为案例进行分析,具体代码如下所示:

//RUN:triton-shared-opt--triton-to-linalg%s|FileCheck%s
module{
tt.func@kernel(
%arg0:!tt.ptr,
%arg1:!tt.ptr,
%arg2:!tt.ptr
)
{
%0=tt.make_range{end=128:i32,start=0:i32}:tensor<128xi32>
%c64=arith.constant128:i32
%1=tt.splat%c64:(i32)->tensor<128xi32>
%2=arith.muli%0,%1:tensor<128xi32>
%3=tt.expand_dims%2{axis=1:i32}:(tensor<128xi32>)->tensor<128x1xi32>
%4=tt.broadcast%3:(tensor<128x1xi32>)->tensor<128x64xi32>
%5=tt.make_range{end=64:i32,start=0:i32}:tensor<64xi32>
%6=tt.expand_dims%5{axis=0:i32}:(tensor<64xi32>)->tensor<1x64xi32>
%7=tt.broadcast%6:(tensor<1x64xi32>)->tensor<128x64xi32>
%8=arith.addi%4,%7:tensor<128x64xi32>
%10=tt.make_range{end=256:i32,start=0:i32}:tensor<256xi32>
%11=tt.expand_dims%10{axis=1:i32}:(tensor<256xi32>)->tensor<256x1xi32>
%12=tt.broadcast%11:(tensor<256x1xi32>)->tensor<256x64xi32>
%13=tt.make_range{end=64:i32,start=0:i32}:tensor<64xi32>
%c256=arith.constant256:i32
%14=tt.splat%c256:(i32)->tensor<64xi32>
%15=arith.muli%13,%14:tensor<64xi32>
%16=tt.expand_dims%15{axis=0:i32}:(tensor<64xi32>)->tensor<1x64xi32>
%17=tt.broadcast%16:(tensor<1x64xi32>)->tensor<256x64xi32>
%18=arith.addi%12,%17:tensor<256x64xi32>
%20=tt.splat%c256:(i32)->tensor<128xi32>
%21=arith.muli%0,%20:tensor<128xi32>
%22=tt.expand_dims%21{axis=1:i32}:(tensor<128xi32>)->tensor<128x1xi32>
%23=tt.broadcast%22:(tensor<128x1xi32>)->tensor<128x256xi32>
%24=tt.expand_dims%10{axis=0:i32}:(tensor<256xi32>)->tensor<1x256xi32>
%25=tt.broadcast%24{axis=0:i32}:(tensor<1x256xi32>)->tensor<128x256xi32>
%26=arith.addi%23,%25:tensor<128x256xi32>
%30=tt.splat%arg0:(!tt.ptr)->tensor<128x64x!tt.ptr>
%31=tt.addptr%30,%8:tensor<128x64x!tt.ptr>,tensor<128x64xi32>
%32=tt.load%31{cache=1:i32,evict=1:i32,isVolatile=false}:tensor<128x64xbf16>
%40=tt.splat%arg1:(!tt.ptr)->tensor<256x64x!tt.ptr>
%41=tt.addptr%40,%18:tensor<256x64x!tt.ptr>,tensor<256x64xi32>
%42=tt.load%41{cache=1:i32,evict=1:i32,isVolatile=false}:tensor<256x64xbf16>
%43=tt.trans%42:(tensor<256x64xbf16>)->tensor<64x256xbf16>
%50=tt.splat%arg2:(!tt.ptr)->tensor<128x256x!tt.ptr>
%51=tt.addptr%50,%26:tensor<128x256x!tt.ptr>,tensor<128x256xi32>
%52=tt.load%51{cache=1:i32,evict=1:i32,isVolatile=false}:tensor<128x256xbf16>
%60=tt.dot%32,%43,%52{allowTF32=false,maxNumImpreciseAcc=0:i32}:tensor<128x64xbf16>*tensor<64x256xbf16>->tensor<128x256xbf16>
tt.store%51,%60:tensor<128x256xbf16>
tt.return
}
}

上述MLIR其实很容易看懂,在%0->%10其实都是triton dialect的内容,该内容表示的就是从上层的triton dsl通过lower转换到对应的triton dialect的过程。其中tt就是表示的该MLIR所处的dialect是triton dialect,然后tt.xxx则表示了该dialect所支持的所有operation,有关如何定义一个MLIR dialect,我准备拿一个单独的教程来讲。

接下来,只需要在终端中输入

./triton-shared-opt--triton-to-linalg/triton/third_party/triton_shared/test/Conversion/TritonToLinalg/dot.mlir

就可以得到从triton dialect转到linag dialect部分对应的内容

#map=affine_map<(d0, d1) ->(d0,d1)>
module{
func.func@kernel(%arg0:memref<*xbf16>,%arg1:memref<*xbf16>,%arg2:memref<*xbf16>,%arg3:i32,%arg4:i32,%arg5:i32,%arg6:i32,%arg7:i32,%arg8:i32){
%c256=arith.constant256:index
%c128=arith.constant128:index
%reinterpret_cast=memref.reinterpret_cast%arg0tooffset:[0],sizes:[128,64],strides:[%c128,1]:memref<*xbf16>tomemref<128x64xbf16, strided<[?, 1]>>
%alloc=memref.alloc():memref<128x64xbf16>
memref.copy%reinterpret_cast,%alloc:memref<128x64xbf16, strided<[?, 1]>>tomemref<128x64xbf16>
%0=bufferization.to_tensor%allocrestrictwritable:memref<128x64xbf16>
%reinterpret_cast_0=memref.reinterpret_cast%arg1tooffset:[0],sizes:[256,64],strides:[1,%c256]:memref<*xbf16>tomemref<256x64xbf16, strided<[1, ?]>>
%alloc_1=memref.alloc():memref<256x64xbf16>
memref.copy%reinterpret_cast_0,%alloc_1:memref<256x64xbf16, strided<[1, ?]>>tomemref<256x64xbf16>
%1=bufferization.to_tensor%alloc_1restrictwritable:memref<256x64xbf16>
%2=tensor.empty():tensor<64x256xbf16>
%transposed=linalg.transposeins(%1:tensor<256x64xbf16>)outs(%2:tensor<64x256xbf16>)permutation=[1,0]
%reinterpret_cast_2=memref.reinterpret_cast%arg2tooffset:[0],sizes:[128,256],strides:[%c256,1]:memref<*xbf16>tomemref<128x256xbf16, strided<[?, 1]>>
%alloc_3=memref.alloc():memref<128x256xbf16>
memref.copy%reinterpret_cast_2,%alloc_3:memref<128x256xbf16, strided<[?, 1]>>tomemref<128x256xbf16>
%3=bufferization.to_tensor%alloc_3restrictwritable:memref<128x256xbf16>
%4=tensor.empty():tensor<128x256xbf16>
%5=linalg.matmulins(%0,%transposed:tensor<128x64xbf16>,tensor<64x256xbf16>)outs(%4:tensor<128x256xbf16>)->tensor<128x256xbf16>
%6=linalg.generic{indexing_maps=[#map,#map,#map],iterator_types=["parallel","parallel"]}ins(%5,%3:tensor<128x256xbf16>,tensor<128x256xbf16>)outs(%5:tensor<128x256xbf16>){
^bb0(%in:bf16,%in_4:bf16,%out:bf16):
%7=arith.addf%in,%in_4:bf16
linalg.yield%7:bf16
}->tensor<128x256xbf16>
memref.tensor_store%6,%reinterpret_cast_2:memref<128x256xbf16, strided<[?, 1]>>
return
}
}

关于其他更加具体的operator,我们可以都按照上述流程来进行操作,一旦你的编译框架是基于MLIR来开发的,那么如果能很好的转到Linalg,那么就说明了后续在接入自己的backend以及适配一些ISA的过程就会方便不少,这也从另外一个角度彰显了为什么现在的趋势都是将自己的compiler通过MLIR进行重构。最重要的原因,其实就是以最小的开发成本方便的接入各种软件或者硬件的生态。

后记

对triton的研究已经有一段时间了,由于当时学triton也是基于源码一步一步硬吃过来的,并且triton也没有比较好的中文教程,所以后面会利用空闲时间将我目前对于使用triton来做codegen的各种优化方法(不同backend以及不同IR层面的pass)和细节(底层layout的设计)进行一个详细的梳理,来帮助更多想要使用triton来做codegen的同学。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • gpu
    gpu
    +关注

    关注

    27

    文章

    4508

    浏览量

    127520
  • Triton
    +关注

    关注

    0

    文章

    16

    浏览量

    6998
  • 代码
    +关注

    关注

    30

    文章

    4596

    浏览量

    67330
  • 编译器
    +关注

    关注

    1

    文章

    1587

    浏览量

    48796

原文标题:OpenAI/Triton MLIR 第三章: Triton-shared开箱

文章出处:【微信号:GiantPandaCV,微信公众号:GiantPandaCV】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Triton编译器的原理和性能

    Triton是一种用于编写高效自定义深度学习原语的语言和编译器。Triton的目的是提供一个开源环境,以比CUDA更高的生产力编写快速代码,但也比其他现有DSL具有更大的灵活性。Triton已被采用
    的头像 发表于 12-16 11:22 1453次阅读
    <b class='flag-5'>Triton</b>编译器的原理和性能

    【BBuf的CUDA笔记】OpenAI Triton入门笔记一

    这里来看官方的介绍:https://openai.com/research/triton ,从官方的介绍中我们可以看到OpenAI Triton的产生动机以及它的目标是什么,还可以看到一些经典算法的实现例子展示。
    的头像 发表于 01-23 10:00 1826次阅读
    【BBuf的CUDA笔记】OpenAI <b class='flag-5'>Triton</b>入门笔记一

    在AMD GPU上如何安装和配置triton

    最近在整理python-based的benchmark代码,反过来在NV的GPU上又把Triton装了一遍,发现Triton的github repo已经给出了对应的llvm的commit id以及对应的编译细节,然后跟着走了一遍,也顺利的
    的头像 发表于 02-22 17:04 1591次阅读
    在AMD GPU上如何<b class='flag-5'>安装</b>和配置<b class='flag-5'>triton</b>?

    GTC2022大会黄仁勋:NVIDIA Triton是AI部署的“中央车站”

    GTC2022大会黄仁勋:NVIDIA Triton是AI部署的“中央车站”,支持在每一代NVIDIA GPU、x86和ARM CPU上部署模型。
    的头像 发表于 03-23 16:23 1354次阅读
    GTC2022大会黄仁勋:NVIDIA <b class='flag-5'>Triton</b>是AI部署的“中央车站”

    NVIDIA Triton推理服务器简化人工智能推理

    GKE 的 Triton 推理服务器应用程序是一个 helm chart 部署程序,可自动安装和配置 Triton ,以便在具有 NVIDIA GPU 节点池的 GKE 集群上使用,包括
    的头像 发表于 04-08 16:43 1981次阅读
    NVIDIA <b class='flag-5'>Triton</b>推理服务器简化人工智能推理

    Triton DataCenter云管理平台

    triton.zip
    发表于 04-25 10:06 1次下载
    <b class='flag-5'>Triton</b> DataCenter云管理平台

    NVIDIA Triton系列文章:开发资源说明

    这里最重要的是 “server documents on GitHub” 链接,点进去后会进入整个 Triton 项目中最完整的技术文件中心(如下图),除 Installation
    的头像 发表于 11-09 16:17 586次阅读

    NVIDIA Triton 系列文章(4):创建模型仓

    推理模型仓(inference model repository) 是 Triton 推理服务器的最基础元件 ,如同数据库(database)服务器必须先创建一个数据库是类似的道理。要使
    的头像 发表于 11-15 21:20 716次阅读

    NVIDIA Triton 系列文章(6):安装用户端软件

    在前面的文章中,已经带着读者创建好 Triton 的模型仓、安装并执行 Triton 推理服务器软件,接下来就是要 安装 Triton 用户
    的头像 发表于 11-29 19:20 929次阅读

    NVIDIA Triton 系列文章(8):用户端其他特性

    前面文章用 Triton 开源项目提供的 image_client.py 用户端作示范,在这个范例代码里调用大部分 Triton 用户端函数,并使用多种参数来配置执行的功能,本文内容就是简单剖析
    的头像 发表于 12-20 19:45 899次阅读

    NVIDIA Triton 系列文章(9):为服务器添加模型

    前面已经用  https://github.com/triton-inference-server/server/doc/examples 开源仓的范例资源,创建一个最基础的模型仓以便执行一些
    的头像 发表于 12-27 21:20 831次阅读

    NVIDIA Triton 系列文章(10):模型并发执行

    前面已经做好了每个推理模型的基础配置,基本上就能正常让 Triton 服务器使用这些独立模型进行推理。接下来的重点,就是要让设备的计算资源尽可能地充分使用,首先第一件事情就是模型并发执行
    的头像 发表于 01-05 11:55 778次阅读

    Triton的具体优化有哪些

    上一章的反响还不错,很多人都私信催更想看Triton的具体优化有哪些,为什么它能够得到比cuBLAS更好的性能。
    的头像 发表于 05-16 09:40 1172次阅读
    <b class='flag-5'>Triton</b>的具体优化有哪些

    如何使用triton的language api来实现gemm的算子

    前言 通过前两章对于triton的简单介绍,相信大家已经能够通过从源码来安装triton,同时通过triton提供的language前端写出自己想要的一些计算密集型算子。这章开始,我们
    的头像 发表于 05-29 14:34 1287次阅读
    如何使用<b class='flag-5'>triton</b>的language api来实现gemm的算子

    Vivado IP核Shared Logic选项配置

    在给Vivado中的一些IP核进行配置的时候,发现有Shared Logic这一项,这里以Tri Mode Ethernet MAC IP核为例,如图1所示。
    的头像 发表于 09-06 17:05 846次阅读
    Vivado IP核<b class='flag-5'>Shared</b> Logic选项配置