NumExpr加速计算(numpy表达式)

Python 性能优化:NumExpr + Numba + CuPy

一、简介

numexpr(全称:numpy expression)用于在 NumPy 表达式上快速执行元素级运算的 Python 加速库。

  • 优势:将表达式转换为高效的机器码,然后在内部优化执行并行计算。
    • 利用多核处理器并行计算:在计算表达式时并行执行操作,从而加快计算速度。
    • 基于缓存的内存管理策略在计算过程中,避免创建临时数组来减少内存占用。
  • 局限性:只有在处理大型数据集时,才会比标准的 NumPy 表达式速度更快;
  • 适用范围:只适用于 NumPy 表达式;

表达式:是由变量、运算符和函数组成的符号序列,用于表示计算过程或计算结果。如:"(a**2 + b**2) / (a + b + 1e-10)"

  • 变量:表示数据或值的符号,可以是数值、字符串、布尔值等。
  • 运算符:如:算术运算符、逻辑运算符、比较运算符等。Python运算符
  • 函数:如:数学函数、三角函数等。Python函数

二、安装

  • pip安装:pip install numexpr
  • conda安装:conda install numexpr

三、函数详解

"""#####################################################################################################################
# 函数功能:用于在 NumPy 表达式上快速执行元素级运算的 Python 加速库。
# 函数说明:numexpr.evaluate(expression, local_dict=None, global_dict=None, out=None, order='K', casting='safe', **kwargs)
# 参数说明:
#         expression (str):               要评估的数学表达式。
#         local_dict (dict, optional):    本地命名空间中的变量字典。
#         global_dict (dict, optional):   全局命名空间中的变量字典。
#         out (ndarray, optional):        结果存储的数组。若提供,则结果存储在该数组中。
#         order (str, optional):          数组存储顺序。如:'C'(行优先)、'F'(列优先)、'K'(与数组的存储顺序相同)。
#         casting (str, optional):        指定如何处理数据类型转换,如:'no'(不允许转换)、'equiv'(仅当转换安全)、'safe'(只允许安全转换)。
#         **kwargs:其他参数传递给底层的 numexpr 引擎。
# 返回参数:
#         out (ndarray):                  若提供,则返回结果数组;否则返回一个新的数组。
#####################################################################################################################"""

四、性能评估

NumExpr简介

在这里插入图片描述

import time
import numpy as np
import numexpr
import matplotlib.pyplot as plt


def compare_performance():
    numexpr_times = []
    numpy_times = []

    ns = range(10, 500, 10)
    for n in ns:
        # 生成表达式
        np.random.seed(0)
        a = np.random.rand(n, n, n)
        b = np.random.rand(n, n, n)
        expression = "(a**2 + b**2) / (a + b + 1e-10)"

        # 使用numexpr计算
        start_time = time.time()
        x_numexpr = numexpr.evaluate(expression)
        numexpr_time = time.time() - start_time
        numexpr_times.append(numexpr_time)

        # 使用numpy计算
        start_time = time.time()
        x_numpy = (a ** 2 + b ** 2) / (a + b + 1e-10)
        numpy_time = time.time() - start_time
        numpy_times.append(numpy_time)

        print(f"n={n}: numexpr_time={numexpr_time:.5f} seconds, numpy_time={numpy_time:.5f} seconds")

    plt.figure(figsize=(10, 6))
    plt.plot(ns, numexpr_times, marker='o', label='numexpr')
    plt.plot(ns, numpy_times, marker='o', label='numpy')
    plt.title('Performance Comparison of numexpr vs numpy')
    plt.xlabel('Three-dimensional array [n, n, n]')
    plt.ylabel('Time (seconds)')
    plt.legend()
    plt.grid(True)
    plt.show()


if __name__ == "__main__":
    compare_performance()

不循环调用:三维数组 = [1000, 1000, 1000]

import time
import numpy as np

# 创建大型数据集
np.random.seed(0)
n = 1000
a = np.random.rand(n, n, n)  # 三维数组:100x100x100
b = np.random.rand(n, n, n)  # 三维数组:100x100x100
expression = "(a**2 + b**2) / (a + b + 1e-10)"

# (1)使用 numexpr 评估表达式
import numexpr
start_time = time.time()
x_numexpr = numexpr.evaluate(expression)
print(f"numexpr时耗: {time.time() - start_time:.5f} 秒")

# (2)直接使用 Python 原生操作计算
start_time = time.time()
x_python = (a ** 2 + b ** 2) / (a + b + 1e-10)
print(f"Python 时耗: {time.time() - start_time:.5f} 秒")

print(f"结果是否一致: {np.allclose(x_numexpr, x_python)}")

"""
numexpr时耗: 0.97169 秒
Python 时耗: 9.74043 秒
两种方法计算结果是否一致: True
"""

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖墩会武术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值