jit和jitx区别_【加速实践】番外篇:numba&jit

本文介绍了Python中的Numba库及其使用的JIT技术,如何通过Numba提升Python代码性能。Numba是一个开源的JIT编译器,可以将Python和NumPy代码转换为高效的机器码。文章讲解了@numba.jit的使用,包括指定签名、编译选项(nopython、object模式)以及Vectorize等功能,展示了Numba如何帮助Python实现接近C/C++的执行效率。
摘要由CSDN通过智能技术生成

背景

加速实践原本只分了三篇的(算法篇、工程代码篇,硬件篇),但是写的过程中觉得有必要要介绍一下神库numba,说实话当年第一次使用的时候,真有一种想见恨晚的感觉,后来工作中用它为公司写了回测系统,速度能 达到原本C++系统的100倍以上(是的你没看错我也没写错,就是C++;除了jit外这主要还得益于矩阵运算和并行计算的使用,另外C++系统是稳定跑了3年多的系统,所以baseline不低;当然C++花时间认真写的话可以达到甚至超过这个效率,但是python当时只花了两周左右的时间,这性价比绝对是我目前做过的项目里最高的之一)

JIT是什么

jit 的全称是 Just-in-time,在 numba 里面则特指 Just-in-time compilation(即时编译),它是一种编译技术,下面的对比即可对jit进行清晰的定位编译方式动态编译(dynamic compilation):指的是“在运行时进行编译”;与之相对的是事前编译(ahead-of-time compilation,简称AOT),也叫静态编译(static compilation)

JIT编译(just-in-time compilation)狭义来说是当某段代码即将第一次被执行时进行编译,因而叫“即时编译”。JIT编译是动态编译的一种特例。JIT编译一词后来被泛化,时常与动态编译等价;但要注意广义与狭义的JIT编译所指的区别

自适应动态编译(adaptive dynamic compilation)也是一种动态编译,但它通常执行的时机比JIT编译迟,先让程序“以某种式”先运行起来,收集一些信息之后再做动态编译。这样的编译可以更加优化。

注意事项但是jit技术并不总是能够如预期的加速代码,甚至有可能降低代码效率,这于代码的结构有关,不过绝大多数情况还是能够有明显的效果的

JIT之于PythonPython啥都好,就是太“动态”了,导致去运行效率不高,jit之于python那简直是如虎添翼

Numbahttps://numba.pydata.org/

首页第一句话便是:Numba是一个开源的JIT编译器,它可以将Python和NumPy代码的子集转换为高效的机器码。numba使用LLVM编译器架构将纯Python代码生成优化过的机器码,将面向数组和使用大量数学的python代码优化到与c,c++和Fortran类似的性能,而无需改变Python的解释器。入门:@numba.jit

import jit

@numba.jit

def add(x,y):

return x + y

上面这段代码是numba.jit的简单应用,在函数第一次执行的时候,numba推断出参数类型,然后基于这个信息生产优化后的代码进阶1:指定签名

import numba

@numba.jit(int32(int32, int32))

def add_signatured(x,y):

return x+y编译器将控制类型选择,并不允许其他特性(即其他类型的参数输入,如float),这回带来速度上的优势类型检查速度优势

签名规范

显式的@jit签名可以使用许多类型。以下是一些常见的例子:void是什么都不返回的函数的返回类型(即:Python调用时实际上返回None)

intp和uintp是指针大小的整数(分别是有符号和无符号的)

intc和uintc等价于C整型和无符号整型

int8, uint8, int16, uint16, int32, int32, int64, uint64是对应位宽的固定宽度整数(有符号和无符号)

float32和float64分别是单精度浮点数和双精度浮点数

complex64和complex128分别是单精度复数和双精度复数

数组类型可以通过索引任意数值类型来指定,例如:用于一维单精度数组的float32[:],用于8位整数的二维数组的int8[:,:]

编译选项:nopython vs object

nopython和object是numba的两种编译模式,前者编译的代码更快,但是可能会因为某些限制但是退化为object, 通过nopython=True可以阻止退化并抛出异常进阶2:编译模式

# 官方例子

import numba

import random

@numba.jit(nopython=True)

def monte_carlo_pi(nsamples):

acc = 0

for i in range(nsamples):

x = random.random()

y = random.random()

if (x ** 2 + y ** 2) < 1.0:

acc += 1

return 4.0 * acc / nsamples

其它选项:nogil: 如果设置为True的话将在进入函数之后释放gil锁,这样可以利用多核算力

cache:将编译结果保存到一个基于文件的缓存中

parallel: 将函数中的操作自动并行化(慎用,搞不好的话可能更慢,例如代码里只是简单的for循环的话开启的效果就会比较明显)

generated_jit:允许用户在编译期控制不同的特性的选择,下面是参考资料2给的例子

import numpy as np

from numba import generated_jit, types

@generated_jit(nopython=True)

def is_missing(x):

"""Return True if the value is missing, False otherwise."""

if isinstance(x, types.Float):

return lambda x: np.isnan(x)

elif isinstance(x, (types.NPDatetime, types.NPTimedelta)):

# The corresponding Not-a-Time value

missing = x('NaT')

return lambda x: x == missing

else:

return lambda x: Falsegenerated_jit有以下几点需要注意:调用装饰器函数是使用Numba的类型作为参数,而不是他们的值。

装饰器函数并不真的计算结果,而是返回一个对于给定类型,可调用的实际定义的函数执行。

可以在编译期预先计算一些数据,使其在编译后执行过程中重用。

函数定义使用和装饰器函数中相同名字的参数,这将确保通过名字传递参数能够如期望的工作。

Vectorize

Numba的vectorize允许Python函数将标量输入参数作为Numpy的ufunc使用,将纯Python函数编译成ufunc,使之速度与使用c编写的传统的ufunc函数一样。

关于Vectorize和其它高级特性,参考资料2已经做了详细的介绍,这里就不再赘述了,后续用到的话,再回来这里补充更多的实例促进理解# 加速python运行-numba​www.jianshu.com

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值