Ⅰ JIT(上):Tensorflow如何实现即时编译
Tensorflow的JIT(just-in-time)是指在运行 @tf.function 修饰的python函数时,由 jit 、 tf2xla 和 XLA 一起完成一系列如子图构造、子图优化、图编译和图执行等操作。编译后的可执行程序-- executable 会存放到cache中,供再次调用时直接获取执行。JIT的好处在 开篇 已经讲过了,这里不再赘述。
JIT的流程可以概括为:Tensorflow子图构造/优化,graph -> HLO,编译/执行,合并计算结果到Tensorflow图这四部分。本文只涉及图编译和图执行。
函数中ops在子图构造阶段被包裹进一个cluster node,并替换成 xla_compile 和 xla_run 这两op,而 XlaCompileOp 和 XlaRunOp 就是它们的 OpKernel ,分别用于图编译和执行。
XlaCompileOp通过 XlaCompilationCache 获取或编译executable,并将其封装成 XlaExecutableClosure ,并缓存在 XlaExecutableClosureStore 。 XlaRunOp 用从XlaCompileOp传递来的key在cache中查找并执行executable。
从编译流程图可以看到,XLA的编译结果会缓存到XlaCompilationCache,后续调用可以根据 signature 在cache中查找executable。
函数的 signature 是由 BuildSignature(function, args) 根据函数和arguments生成的。即使是同一个函数,只要input tensors不同,signature也会不一样,这就是 power() 被编译两次的原因:第三次函数调用时,由于无法通过signature在cache中找到executable而触发编译。
signature表示唯一的计算图:只要函数中的ops序列和arguments(type/shape)是确定的,那么计算图也是确定的。
编译之前需要通过 tf2xla 将图转换成XLA支持的语言 HLO 。tf2xla为每个Tensorflow op创建了生成HLO的 XlaOp ,因此,只要执行该Tensorflow子图,就可以生成具有相同的拓扑排序的HLO -- XlaComputation 。
XlaComputation (HLO)可以认为是一个运行在device上的纯函数,它的input/output会伴随着host-to-device(H2D)和device-to-host(D2H)的数据传输。
我们知道,Tensorflow图中的input tensor有两种: tf.Placeholder 和 tf.Variable ,前者每个step都会将新data发送到device,而后者是模型参数,它们会常驻内存,只在store/load checkpoint才会有H2D/D2H。
而纯函数的定义是:
不管是input还是output,虽然variable和其他argument一样存在于HLO的参数列表和返回值列表中,但它们实际上是常驻于device的,不需要也不应该H2D/D2H。
因此,HLO在编译时还需要通过 argument_input_indices 、 resource_input_indices 和 resource_update_to_input_index 等options来区分arguments和variables。
此外,如果有input是常数,为了避免无谓的H2D开销,可以把它固化到函数内部。同理,对于常数output,它没必要出现在函数中,可以直接定义在 XlaCompilationResult 的output buffer。
XlaCompilationResult是 Graph -> HLO 的output,它封装了HLO以及上述部分metadata、buffers。
XlaCompileOp会把编译好的executable、metadata、input/output buffers、options等统统封装进一个closure -- XlaExecutableClosure ,并将其缓存在 XlaExecutableClosureStore 供 XlaRunOp 获取。
XlaRunOp 可以通过一个数字字符串key(从0开始累加)从cache中查找并执行XlaExecutableClosure,这个key由XlaCompileOp提供。
Ⅱ java中的JIT编译到底是什么意思
在JIT编译器生成本机代码后,它会重写存根例程,插入一个jmp指令跳转到刚才JIT编译器的代码。只有当要调用某个方法时,JIT编译器才会将CIL的方法体编译为相应的本机机器码版本。这样可以优化程序的工作集。
Ⅲ JIT编译器的分类
事实上,JIT编译器分成两种:经济编译器和普通编译器。 普通JIT编译器则是缺省的运行时配置,它会对其产生的代码进行即时优化。这样做无形中给予了.NET超出传统预编译语言的一个优点:预编译语言只能对其处理的代码将要运行于其上的平台做一番大致的事前估计。
JIT编译器可以经过准确调节达到当前运行时状态,结果可以完成一些预编译语言无法完成的工作:更高效地利用和分配CPU寄存器。在适当的情况下实施低级代码优化,比如常量重叠、拷贝复制、取消范围检查、取消常规副表达式以及方法内联等
在代码执行期间监控当前的物理和虚拟内存需求从而更高效地利用内存
产生特定的平台指令以准确、充分地利用实际的处理器模式
NET编译的结果就是JIT所带来的额外负载要求并没有产生显着的性能损失。 JIT Compiler(Just-in-time Compiler) 即时编译
最早的Java建置方案是由一套转译程式(interpreter),将每个Java指令都转译成对等的微处理器指令,并根据转译后的指令先后次序依序执行,由于一个Java指令可能被转译成十几或数十几个对等的微处理器指令,这种模式执行的速度相当缓慢。针对这个问题,业界首先开发出JIT(just in time)编译器。当Java执行runtime环境时,每遇到一个新的类别(class:类别是Java程式中的功能群组),类别是Java程式中的功能群组-JIT编译器在此时就会针对这个类别进行编译(compile)作业。经过编译后的程式,被优化成相当精简的原生型指令码(native code),这种程式的执行速度相当快。花费少许的编译时间来节省稍后相当长的执行时间,JIT这种设计的确增加不少效率,但是它并未达到最顶尖的效能,因为某些极少执行到的Java指令在编译时所额外花费的时间可能比转译器在执行时的时间还长,针对这些指令而言,整体花费的时间并没有减少。基于对JIT的经验,业界发展出动态编译器(dynamic compiler),动态编译器仅针对较常被执行的程式码进行编译,其余部分仍使用转译程式来执行。也就是说,动态编译器会研判是否要编译每个类别。动态编译器拥有两项利器:一是转译器,另一则是JIT,它透过智慧机制针对每个类别进行分析,然后决定使用这两种利器的哪一种来达到最佳化的效果。动态编译器针对程式的特性或者是让程式执行几个循环,再根据结果决定是否编译这段程式码。这个决定不见得绝对正确,但从统计数字来看,这个判断的机制正确的机会相当高。事实上,动态编译器会根据“历史资料”做决策,所以程式执行的时间愈长,判断正确的机率就愈高。以整个结果来看,动态编译器产生的程式码执行的速度超越以前的JIT技术,平均速度可提高至50%。
JIT 页面渲染引擎
JIT 页面渲染是 COMSHARP CMS 为了实现网站内容即时更新而开发的页面生成技术,JIT页面渲染引擎直接从数据库获取网站最新内容,瞬间生成页面输出给访问者,并通过 URL 转写技术实现纯静态地址。JIT 页面渲染技术是针对传统 CMS 生成静态 HTML 文件而言。传统 CMS 由于使用脚本代码模板技术,页面生成前,需要将数据库中的页面内容用外部模板进行解析与渲染,导致严重的性能问题,为了解决这个问题,传统 CMS 一般采用生成 HTML 静态文件技术,即,在内容创作完成后,对全站的内容执行一个静态 HTML 文件生成过程,最终,全站内容以静态 HTML 文件的形式存在。静态 HTML 文件技术最显着的优势是性能出众,然而这种技术最严重的问题在于,用户对站点任何修改与更新,必须首先经过一次全站 HTML 文件重新生成过程,然后才能被访问者看到。根据不同 CMS 产品的性能和站点规模,这个 HTML 生成过程可能长到十几分钟到几十分钟或更长。也有个别 CMS 产品使用触发式页面渲染模式,即内容更新后,并不立即生成 HTML 文件,而是在用户第一次访问该页面时,触发生成该页面的 HTML 文件,这种技术的问题在于,用户第一次访问被更新页面的时候,可能经历非常漫长的等待,因为站点内各个页面之间并非孤立的,他们可能相互引用,虽然访问的只是一个页面,为了对引用页面同步更新,需要重新生成 HTML 文件的页面可能有多个。JIT 页面渲染如何工作?下图,是 COMSHARP CMS JIT 渲染引擎与传统 CMS 生成 HTML 静态页面模式对比。可以看出,JIT 渲染引擎直接将网站最新内容从数据库渲染给访问用户,而传统 CMS 的站点内容在到达访问用户之前,首先要经历一个 HTML 的转换过程。COMSHARP CMS JIT 页面渲染如何实现毫秒级的渲染速度?COMSHARP CMS 在页面渲染的时候,JIT 引擎可以在数十毫秒的时间内容完整整个页面的生成,这样就保证用户访问的时候,不会因 JIT 渲染造成延迟。事实上,COMSHARP CMS 网站访问速度只取决于服务器带宽,页面生成过程带来的延迟可以忽略不计。我们有两项技术保证这样的性能:编译级主题模板COMSHARP CMS 的编译级主题模板直接内嵌在系统的 DLL 中,主题模板的套用是在运行时(Run Time)完成,这和传统 CMS 的调用脚本代码模板解释运行是截然不同。
Ⅳ JIT编译器的简介
在Java编程语言和环境中,即时编译器(JIT compiler,just-in-time compiler)是一个把Java的字节码(包括需要被解释的指令的程序)转换成可以直接发送给处理器的指令的程序。当你写好一个Java程序后,源语言的语句将由Java编译器编译成字节码,而不是编译成与某个特定的处理器硬件平台对应的指令代码(比如,Intel的Pentium微处理器或IBM的System/390处理器)。字节码是可以发送给任何平台并且能在那个平台上运行的独立于平台的代码。
Ⅳ Java使用JIT编译器,执行效率与C++相比哪个
我猜测:JAVA即使编译成机器码,其执行效率也不如C++的。
从整体来看,JAVA有一些需要额外的消耗是C++没有的,比如:内存回收、反射、数组越界判断等。
内存回收这一机制要求编译后的执行文件除了我们自己写的逻辑之外,还要有一个线程来管理内存。
反射一方面要有一块内存用来做类型字典,另一方面又要对反射调用做安全检查。
……
另外,如果JIT编译之后仍然有类加载器这类的东西,那么这个程序就还要内部集成一个.class文件到机器指令的解释器或编译器。
……
总之,JIT编译后的文件不得不为JAVA自身的复杂性增加一系列机制在里面,但C++的文件除了我们自己写的逻辑和本地可执行文件头之外就什么都没有了。
Ⅵ JIT编译的介绍
JIT 编译 (JIT compilation),运行时需要代码时,将 Microsoft 中间语言 (MSIL) 转换为机器码的编译。
Ⅶ JIT编译器的介绍
JIT编译器,英文写作Just-In-Time Compiler,中文意思是即时编译器。JIT编译器能够将MSIL编译成为各种不同的机器代码,以适应对应的系统平台,最终使得程序在目标系统中得到顺利地运行。