CPython 和 PyPy 小数运算性能

2023-11-29

我想使用数百万个数据点(以小数表示)运行 100k+ 次模拟。我选择小数而不是浮点数是为了浮点精度和易于对我的逻辑进行单元测试(因为0.1 + 0.1 + 0.1对于浮点数不等于 0.3...)。

我希望通过使用 PyPy 来加快模拟速度。但在我的测试过程中我遇到 PyPy 不处理decimal.Decimal甚至_pydecimal.Decimal一点也不差——而且比 CPython 解释器(使用 C 语言)慢得多decimal.Decimal算术)。所以我复制/粘贴了我的整个代码库并替换了所有Decimals with float并且性能提升巨大:PyPy 比 CPython 快 60-x70 倍 - 但牺牲了准确性。

是否有任何解决方案可以在 PyPy 中使用小数精度并具有性能优势?我“可以”维护两个代码库:float对于批量运行 100k 次模拟,Decimal用于稍后检查有趣的结果 - 但这需要维护两个代码库的开销......

这是我在上面运行的一些简单测试Raspberry Pi 4 (Ubuntu Server 20.10, 4 x 1.5GHZ ARM Cortex-A72, 8GB RAM)用于复制:

test_decimal.py

import time
from decimal import Decimal

start = time.time()
val = Decimal('1.0')
mul = Decimal('1.000001')
for i in range(10 * 1000 * 1000):
    val *= mul
end = time.time()
print(f"decimal.Decimal: {val:.8f} in {round(end-start,4)} sec")

test_pydecimal.py

import time
from _pydecimal import Decimal

start = time.time()
val = Decimal('1.0')
mul = Decimal('1.000001')
for i in range(10 * 1000 * 1000):
    val *= mul
end = time.time()
print(f"pydecimal.Decimal: {val:.8f} in {round(end-start,4)} sec")

test_float.py

import time
from decimal import Decimal

start = time.time()
val = float('1.0')
mul = float('1.000001')
for i in range(10 * 1000 * 1000):
    val *= mul
end = time.time()
print(f"float: {val:.8f} in {round(end-start,4)} sec")

Results

Test Python 3.8.6 (GCC 10.2.0) Python 3.6.9 -PyPy 7.3.1 with GCC 10.2.0
test_decimal 5.1131 sec 55.0829 sec
test_pydecimal 315.4012 sec 40.1771 sec
test_float 2.5607 sec 0.1273 sec

Edit #1:

  • 更新了示例(使用预先计算的乘法器,测量时间之外print)和结果表:PyPy 和 CPython 在小数上的总体比较保持不变。
  • 模拟主要由对具有变化值的时间序列数据进行基本数学运算(加、减、乘、除)组成。

您可以使用双精度比任意精度算术(即,Decimal)并且比双精度更准确(即float)。双双精度通常比四精度稍差,但大多数平台通常不支持后者。

The 双双Python 包实现了这一点并且与 PyPy 兼容。它不支持字符串解析和格式化,但您可以使用以下两种缓慢的方法来实现:

from decimal import Decimal
from doubledouble import DoubleDouble

def ddFromStr(s):
    hi = float(s)
    lo = float(Decimal(s) - Decimal(hi))
    return DoubleDouble(hi, lo)

def ddToStr(dd):
    return str(Decimal(dd.x) + Decimal(dd.y))

以下是如何使用它:

start = time.time()
val = ddFromStr('1.0')
mul = ddFromStr('1.000001')
for i in range(10 * 1000 * 1000):
    val *= mul
end = time.time()
print(f"doubledouble.DoubleDouble: {ddToStr(val)} in {round(end-start,4)} sec")

以下是我机器上的结果:

CPython:
  float: 22026.35564471 in 0.6692 sec
  decimal.Decimal: 22026.35566283 in 1.4355 sec
  doubledouble.DoubleDouble: 22026.35566283 in 11.62 sec

PyPy:
  float: 22026.35564471 in 0.011 sec
  decimal.Decimal: 22026.35566283 in 16.3268 sec
  doubledouble.DoubleDouble: 22026.355662823 in 0.1184 sec

如你看到的,the doubledoublePyPy 上的包明显更快DecimalCPython 上的包,而在这种情况下,两者提供同样准确(截断)的结果。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CPython 和 PyPy 小数运算性能 的相关文章

随机推荐

  • 事务回滚,但插入一条记录

    大家好 我已经使用 jsf spring 3 0 hybernate JPA 和atomikos 进行了 XA 交易管理 mysql 是我的后端 这里一切正常 但是插入操作 当异常抛出时 交易应该回滚 但是它没有发生 这是我们应用程序的一个
  • 使用jquery附加vue js组件

    我正在尝试动态附加vue使用 jquery 将组件添加到我的应用程序中 但什么也没有发生 附加元素没有渲染 div div 我想要的结果是附加时
  • HSM 和自定义模块

    我们正在实施安全关键系统 其中FIPS 140 2需要兼容的 HSM 硬件安全模块 来生成和存储密钥材料 执行加密 解密以及运行自定义代码 并为自定义模块设置以下要求 模块可通过 RPC 访问 模块可以访问所有 HSM 密钥和服务 模块具有
  • php shell命令错误GLIBCXX_3.4.9未找到

    我试图从 php 执行 shell 命令将文件转换为 pdf 但出现此错误 有人可以详细解释我如何修复它吗 我不太擅长linux 而且 如果我直接通过终端执行命令 一切都会正常 usr lib libreoffice program oos
  • 我为什么可以在 std::vector 中使用前向声明的类?

    我认为您只能创建指向前向声明类的引用或指针成员 然而 我惊讶地发现这个有效 include
  • 在 GAE 上使用 boto3 - 遇到 Popen 问题

    我正在尝试在 Google App Engine 中运行一些 python 代码 该代码向 Amazon SQS 发送消息 我已经安装了 boto3 但在尝试将其导入我的 AppEngine 服务时遇到错误 File base data h
  • 使用 R 中的 Match 函数查找“第一次出现”

    我是 R 和 Stackoverflow 的新手 所以请原谅我提出这个非常基本的问题 我正在尝试在我的数据集中找到第一个女性的 索引 代码快照 我的整个数据集称为 自行车 所以首先我认为分配一个仅包含性别的新向量是个好主意 bike gen
  • 使用填充堆叠不同长度的 Numpy 数组

    a np array 1 2 3 b np array 4 5 l a b 我想要一个功能stack padding这样 assert stack padding l np array 1 2 3 4 5 0 numpy 是否有实现的标准方
  • Prolog 将分钟转换为小时

    这是我创建的代码 mins to hours In H M In lt 60 H 0 M is In mins to hours In H M In gt 60 H is H1 1 In1 is In 60 mins to hours In
  • jQuery AJAX 请求 302 重定向 - 哪些回调可用?

    我正在使用一个使用 jQuery 1 2 6 的旧系统 我正在通过以下方式发送 AJAX 请求jQuery ajax功能 它所访问的 URL 正在发送 302 HTTP 重定向响应 并最终以 200 HTTP OK 响应结束 我已经注册了两
  • 如何将 $SHELL 变量传递到 perl 搜索和替换中

    我有以下两个命令 value grep o Logs txt textFILE perl i wpe s onclick img document getElementById img 1 img style display img sty
  • ftplib.FTP 超时行为不一致

    我正在尝试使用ftplib FTP 使用超时选项作为特定主机名的超时值 但我遇到了奇怪的行为 为了测试它 我编写了一段非常简单的代码 import ftplib from ftplib import FTP ftp ftplib FTP g
  • 将表达式作为参数传递:关键字不能是表达式

    这是我的行动 gt gt gt def show d print d gt gt gt test result True gt gt gt show test result True gt gt gt show test info Some
  • 使用 SDL 2 和 -static 进行编译时收到对各种 Windows 库的未定义引用?

    我正在对 SDL2 中的 Wolfenstein 3D 引擎进行修改 使用 Wolf4SDL 作为基础 并且遇到了一个问题 在链接器选项中使用 static 时 我得到了对各种事物的大量未定义引用 这是我的构建日志来说明我的意思 Build
  • 将数据集动态绑定到 RDLC 报告

    我想将动态数据集绑定到 rdlc 如果我在 ASPX 文件中使用内联数据源 静态绑定 我可以查看报告 但是 如果我使用以下代码 报告查看器将继续显示 正在加载 图像 我已经检查了数据集名称 如果我将数据集名称更改为 Orders2 它会显示
  • 如何修复 AttributeError: 'NoneType' 对象没有属性 'text'...循环时

    我是初学者 这个论坛上的答案非常宝贵 我正在使用 Python 3 和 Beautiful Soup 通过循环页码从同一网站上的多个网页中抓取 非表 数据 它有效 但我不断收到 AttributeError NoneType object
  • 触摸设备(iOS、Android)

    触摸输入上有刻度吗 我知道有灵敏度设置可以说明是否触摸 但它也有硬压力和低压的刻度吗 如果有 规模是多少 0 到 1 或 0 255 或者什么可能性 嗯 这完全取决于 API 以 Android 为例 有一个getPressure Moti
  • 如何在android中播放来自url的动画GIF图像?

    我正在将 giphy 集成到我的 Android 应用程序中 我怎样才能玩animated gifAndroid 中的 URL 中的图像 我应该使用ImageView WebView VideoViewETC 例如 如果我想播放动画this
  • 无法在 JavaScript 警报框中添加新行?

    我在 PHP 中生成一个字符串 然后最终将该字符串传递到 JavaScript 警报框中 我的问题是我实际上无法在警报框中添加换行符 我的代码如下所示 str This is a string n alert str This is the
  • CPython 和 PyPy 小数运算性能

    我想使用数百万个数据点 以小数表示 运行 100k 次模拟 我选择小数而不是浮点数是为了浮点精度和易于对我的逻辑进行单元测试 因为0 1 0 1 0 1对于浮点数不等于 0 3 我希望通过使用 PyPy 来加快模拟速度 但在我的测试过程中我