首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >NumExpr教程:让NumPy计算提速4倍以上的高性能表达式引擎

NumExpr教程:让NumPy计算提速4倍以上的高性能表达式引擎

作者头像
代码简单说
发布2026-06-16 11:47:06
发布2026-06-16 11:47:06
1920
举报
文章被收录于专栏:代码简单说代码简单说

NumExpr教程:让NumPy计算提速4倍以上的高性能表达式引擎

大家好 这里是「代码简单说」`,欢迎大家关注同名公众号,不定时更新更多实用有趣的教程 也欢迎大家在评论区一起讨论交流!~

关键词:NumExpr教程、NumExpr安装、NumExpr使用方法、NumPy性能优化、Python科学计算加速、数组计算加速、多线程计算、MKL优化、NumExpr与NumPy对比

在这里插入图片描述
在这里插入图片描述

在处理大规模数据分析、机器学习预处理、科学计算时,很多开发者都会遇到一个问题:

代码语言:javascript
复制
c = a * b - 4.1 * a > 2.5 * b

这类代码写起来简单,但当数组达到几百万甚至上亿条数据时,计算速度和内存占用都会成为瓶颈。

最近在优化一个数据分析项目时,发现了一个专门用于加速 NumPy 表达式计算的库——NumExpr

官方测试数据显示:

  • 简单表达式可达到 NumPy 的 0.95~2 倍速度
  • 复杂表达式可达到 4 倍以上速度
  • 某些数学函数甚至可获得 15 倍加速

今天就详细介绍一下这个性能神器。


什么是 NumExpr

NumExpr 是一个专门为 NumPy 数组计算设计的高性能表达式求值器(Numerical Expression Evaluator)。

项目地址:

代码语言:javascript
复制
https://github.com/pydata/numexpr

官方文档:

代码语言:javascript
复制
https://numexpr.readthedocs.io/

它能够直接解析字符串形式的数学表达式:

代码语言:javascript
复制
"3*a+4*b"

然后通过内部虚拟机执行计算。

相比 NumPy 传统运算方式:

代码语言:javascript
复制
result = 3 * a + 4 * b

NumExpr 具有以下优势:

特性

NumPy

NumExpr

避免中间数组

CPU缓存优化

多线程计算

有限

MKL加速

部分支持

大数组性能

一般

优秀


NumExpr为什么这么快

很多开发者以为:

代码语言:javascript
复制
a * b + c

只是一条运算。

实际上 NumPy 内部通常会经历:

代码语言:javascript
复制
temp = a * b
result = temp + c

产生一个中间数组:

代码语言:javascript
复制
a
b
↓
temp
↓
result

如果数组很大:

代码语言:javascript
复制
100000000

那么:

代码语言:javascript
复制
额外内存 = 100000000 × 8 Byte
≈ 800MB

仅临时变量就可能占用数百 MB 内存。


NumExpr的优化方案

NumExpr不会创建完整中间数组。

而是:

代码语言:javascript
复制
数组
↓
切块(chunk)
↓
CPU缓存
↓
计算
↓
输出结果

例如:

代码语言:javascript
复制
100000000元素

被拆分为:

代码语言:javascript
复制
Chunk1
Chunk2
Chunk3
...

每块放入 CPU Cache 后计算。

优点:

  • 更少内存访问
  • 更高缓存命中率
  • 更少临时对象
  • 更好的CPU利用率

NumExpr内部工作原理

NumExpr并不是直接调用Python解释器。

执行流程:

代码语言:javascript
复制
表达式字符串
↓
解析器(Parser)
↓
生成Opcode
↓
虚拟机(VM)
↓
多线程执行
↓
返回结果

例如:

代码语言:javascript
复制
"a*b-4.1*a>2.5*b"

会被转换成内部操作码。

随后:

代码语言:javascript
复制
CPU核心1 → Chunk1
CPU核心2 → Chunk2
CPU核心3 → Chunk3
CPU核心4 → Chunk4

并行执行。

因此在多核CPU上性能提升非常明显。


NumExpr安装教程

使用pip安装

最简单方式:

代码语言:javascript
复制
pip install numexpr

查看版本:

代码语言:javascript
复制
python -c "import numexpr;print(numexpr.__version__)"

Conda安装

如果使用:

  • Anaconda
  • Miniconda

推荐:

代码语言:javascript
复制
conda install numexpr

因为 Conda 版本通常自带 MKL 支持。


测试安装是否成功

执行:

代码语言:javascript
复制
python -c "import numexpr; numexpr.test()"

如果看到:

代码语言:javascript
复制
OK

说明安装成功。


NumExpr基础使用

导入模块

代码语言:javascript
复制
import numpy as np
import numexpr as ne

创建测试数据:

代码语言:javascript
复制
a = np.arange(1000000)
b = np.arange(1000000)

示例1:简单表达式

NumPy:

代码语言:javascript
复制
a + 1

NumExpr:

代码语言:javascript
复制
ne.evaluate("a + 1")

输出:

代码语言:javascript
复制
array([
1.,
2.,
3.,
...
1000000.
])

示例2:复杂条件判断

NumPy:

代码语言:javascript
复制
a * b - 4.1 * a > 2.5 * b

NumExpr:

代码语言:javascript
复制
ne.evaluate(
    "a * b - 4.1 * a > 2.5 * b"
)

返回:

代码语言:javascript
复制
array([
False,
False,
...
True
])

复杂表达式通常能获得更明显加速。


示例3:数学函数

NumExpr支持大量数学运算。

例如:

代码语言:javascript
复制
ne.evaluate(
    "sin(a) + arcsinh(a/b)"
)

结果:

代码语言:javascript
复制
array([...])

支持:

函数类型

示例

三角函数

sin、cos、tan

反三角函数

arcsin、arccos

指数函数

exp

对数函数

log

双曲函数

sinh、cosh

平方根

sqrt

绝对值

abs


示例4:字符串数组

很多人不知道:

NumExpr还支持字符串比较。

代码语言:javascript
复制
s = np.array([
    b'abba',
    b'abbb',
    b'abbcdef'
])

判断:

代码语言:javascript
复制
ne.evaluate(
    "b'abba' == s"
)

结果:

代码语言:javascript
复制
array([
 True,
 False,
 False
])

NumExpr性能测试

NumPy方式

代码语言:javascript
复制
import numpy as np
import time

a = np.random.rand(10000000)
b = np.random.rand(10000000)

start = time.time()

result = a * b - 4.1 * a > 2.5 * b

print(time.time() - start)

NumExpr方式

代码语言:javascript
复制
import numexpr as ne
import numpy as np
import time

a = np.random.rand(10000000)
b = np.random.rand(10000000)

start = time.time()

result = ne.evaluate(
    "a*b-4.1*a>2.5*b"
)

print(time.time() - start)

典型性能对比

官方给出的经验数据:

表达式复杂度

性能提升

a+1

0.95x~1.5x

a+b+c+d

1.5x~2.5x

ab-4.1a>2.5*b

2x~4x

复杂数学函数

5x~15x


MKL加速支持

NumExpr支持:

代码语言:javascript
复制
Intel MKL
Intel VML

即:

代码语言:javascript
复制
Math Kernel Library
Vector Math Library

对于:

代码语言:javascript
复制
sin()
cos()
exp()
log()

等函数可进一步提升速度。


开启MKL

创建:

代码语言:javascript
复制
site.cfg

配置MKL路径:

代码语言:javascript
复制
[mkl]
library_dirs = ...
include_dirs = ...

重新编译:

代码语言:javascript
复制
pip install .

编译日志中会显示:

代码语言:javascript
复制
MKL detected

说明启用成功。


多线程支持

NumExpr最强大的特性之一:

代码语言:javascript
复制
自动多线程

计算时能够同时使用:

代码语言:javascript
复制
CPU核心1
CPU核心2
CPU核心3
CPU核心4
...

例如:

代码语言:javascript
复制
import numexpr as ne

print(
    ne.detect_number_of_cores()
)

输出:

代码语言:javascript
复制
16

设置线程数:

代码语言:javascript
复制
ne.set_num_threads(8)

查看线程数:

代码语言:javascript
复制
ne.get_num_threads()

Python 3.13无GIL支持

从:

代码语言:javascript
复制
CPython 3.13

开始提供 Free Threading 版本。

即:

代码语言:javascript
复制
无GIL模式

NumExpr已经能够在这种环境下运行。

官方建议:

方案1

使用:

代码语言:javascript
复制
Python主线程
+
NumExpr内部多线程

方案2

使用:

代码语言:javascript
复制
多个Python线程
+
NumExpr单线程

避免:

代码语言:javascript
复制
线程过度订阅
(Oversubscription)

导致性能下降。


NumExpr适合哪些场景

数据分析

Pandas底层大量使用NumPy:

代码语言:javascript
复制
DataFrame
Series

大规模筛选时收益明显。


科学计算

例如:

代码语言:javascript
复制
矩阵计算
统计分析
数值模拟

机器学习预处理

特征工程:

代码语言:javascript
复制
归一化
标准化
数学变换

金融量化

指标计算:

代码语言:javascript
复制
RSI
MACD
KDJ
ATR

需要处理大量时间序列数据。


NumExpr与NumPy对比

项目

NumPy

NumExpr

易用性

★★★★★

★★★★☆

生态

★★★★★

★★★☆☆

简单运算

★★★★★

★★★★☆

复杂表达式

★★★☆☆

★★★★★

内存占用

★★★☆☆

★★★★★

多线程能力

★★☆☆☆

★★★★★

超大数组计算

★★★☆☆

★★★★★


总结

NumExpr 是一个专门针对 NumPy 数组表达式优化的高性能计算库。

核心优势包括:

  • 避免创建中间数组
  • 减少内存占用
  • 提高CPU缓存利用率
  • 自动多线程并行计算
  • 支持Intel MKL/VML加速
  • 复杂表达式最高可获得15倍性能提升

如果你的项目中存在大量类似:

代码语言:javascript
复制
a*b+c*d-e
代码语言:javascript
复制
sin(x)+log(y)
代码语言:javascript
复制
(a>0)&(b<100)

这样的 NumPy 数组计算,那么 NumExpr 是非常值得引入的性能优化工具。

项目地址:

资源

链接

GitHub

https://github.com/pydata/numexpr

官方文档

https://numexpr.readthedocs.io/

PyPI

https://pypi.org/project/numexpr/

对于数据分析、机器学习、量化计算以及科学计算场景,NumExpr 往往只需极少代码改动,就能获得可观的性能提升。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-06-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • NumExpr教程:让NumPy计算提速4倍以上的高性能表达式引擎
  • 什么是 NumExpr
  • NumExpr为什么这么快
    • NumExpr的优化方案
  • NumExpr内部工作原理
  • NumExpr安装教程
    • 使用pip安装
    • Conda安装
  • 测试安装是否成功
  • NumExpr基础使用
    • 导入模块
    • 示例1:简单表达式
    • 示例2:复杂条件判断
    • 示例3:数学函数
    • 示例4:字符串数组
  • NumExpr性能测试
    • NumPy方式
    • NumExpr方式
    • 典型性能对比
  • MKL加速支持
    • 开启MKL
  • 多线程支持
  • Python 3.13无GIL支持
    • 方案1
    • 方案2
  • NumExpr适合哪些场景
    • 数据分析
    • 科学计算
    • 机器学习预处理
    • 金融量化
  • NumExpr与NumPy对比
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档