Kaggle知识点:使用Numba加速代码
Numba介绍
https://numba.pydata.org/
Numba是一个用于优化Python函数的库,它利用行业标准的LLVM编译器库,在运行时将Python函数转换为优化的机器码。使用Numba编译的数值算法在Python中可以接近C或FORTRAN的速度。
Numba不需要替换Python解释器,运行额外的编译步骤,甚至安装C/C++编译器。只需将Numba的一个装饰器应用于Python函数,剩下的工作将由Numba完成。
Numba使用场景
并行计算:Numba提供了一系列选项,可以将代码并行化在CPU和GPU上运行,通常只需要进行少量的代码更改。使用Numba的并行功能,可以将计算在多个CPU核心上自动执行,并且编写并行循环非常简单。
分布式计算:Numba与分布式执行框架(例如Dask和Spark)非常兼容。通过结合Numba和这些框架,可以在分布式计算环境中高效地执行数值计算任务。
GPU加速:Numba支持NVIDIA CUDA,可以完全使用Python编写并行GPU算法。通过利用GPU的并行计算能力,可以加速复杂的计算任务,特别是涉及大规模数据处理和深度学习等领域。
Numba与Pandas案例
首先我们来创建一个模拟数据,数据存储了多列。接下来一些例子将使用这个数据来对比处理速度。
import pandas as pd
import numpy as npdata = np.random.rand(int(1e5), 5)
df = pd.DataFrame(data=data, columns=list("ABCDE"))
df["Type"] = np.random.choice(["Class1","Class2"], size=(len(df)))
案例1: 设置engine
在这个案例中,我们比较了使用不同的引擎(engine)进行计算所需要的时间。结果显示,使用Numba引擎进行计算只需要大约5.62毫秒的时间。与默认引擎相比,Numba引擎显著提高了性能。
%time out = rolling_df.mean()
# CPU times: user 14.1 ms, sys: 402 µs, total: 14.5 ms%time out = rolling_df.mean(engine='cython')
# CPU times: user 12.6 ms, sys: 0 ns, total: 12.6 ms
%time out = rolling_df.mean(engine='numba')
# CPU times: user 5.62 ms, sys: 2.26 ms, total: 7.88 ms
案例2:自定义函数
我们可以将自定义函数编译为高效的机器码,以提高计算速度。在这个案例中,使用Numba引擎可以将计算时间缩短到原来的一半左右。
def custom_mean(x):
return (x * x).mean() %time out = rolling_df.apply(custom_mean, raw=True)
# CPU times: user 2.89 s, sys: 392 µs, total: 2.89 s
%time out = rolling_df.apply(custom_mean, engine='cython', raw=True)
# CPU times: user 2.88 s, sys: 3.62 ms, total: 2.89 s
%time out = rolling_df.apply(custom_mean, engine='numba', raw=True)
# CPU times: user 1.23 s, sys: 117 µs, total: 1.23 s
案例3:Numba jit
通过使用jit装饰器,我们可以将普通的Python函数即时编译为优化的机器码,以提高计算速度。在这个案例中,使用Numba的即时编译可以将计算时间缩短到原来的一半左右,使得函数的执行更加高效。
from numba import jit, njit, vectorize, float64def custom_mean(x):
return (x * x).mean()
@jit(cache=True)
def custom_mean_jitted(x):
return (x * x).mean()
%time out = rolling_df.apply(custom_mean, raw=True)
# CPU times: user 2.9 s, sys: 143 µs, total: 2.9 s
%time out = rolling_df.apply(custom_mean_jitted, raw=True)
# CPU times: user 951 ms, sys: 0 ns, total: 951 ms
%time out = rolling_df.apply(custom_mean, engine='cython', raw=True)
# CPU times: user 2.87 s, sys: 3.87 ms, total: 2.87 s
%time out = rolling_df.apply(custom_mean_jitted, engine='cython', raw=True)
# CPU times: user 856 ms, sys: 0 ns, total: 856 ms
%time out = rolling_df.apply(custom_mean, engine='numba', raw=True)
# CPU times: user 1.57 s, sys: 48 µs, total: 1.57 s
%time out = rolling_df.apply(custom_mean_jitted, engine='numba', raw=True)
# CPU times: user 1.5 s, sys: 0 ns, total: 1.5 s
案例4:Python Loop
通过使用jit装饰器,我们可以将Python中的循环即时编译为优化的机器码,以提高计算速度。
from numba import jit, njit, vectorize, float64def custom_mean(x):
return (x * x).mean()
@jit(float64(float64[:]), nopython=True, cache=True)
def custom_mean_loops_jitted(x):
out = 0.0
for i in x:
out += (i*i)
return out / len(x)
%time out = rolling_df.apply(custom_mean, raw=True)
# CPU times: user 2.9 s, sys: 7.83 ms, total: 2.9 s
%time out = rolling_df.apply(custom_mean, engine='numba', raw=True)
# CPU times: user 1.21 s, sys: 3.93 ms, total: 1.21 s
%time out = rolling_df.apply(custom_mean_loops_jitted, raw=True)
# CPU times: user 689 ms, sys: 0 ns, total: 689 ms