首页 / 知识
关于c ++:在哪里可以找到世界上最快的atof实现?
2023-04-17 12:17:00
Where can I find the world's fastest atof implementation?我正在寻找针对美国语言环境,ASCII和非科学符号进行了优化的IA32上极其快速的atof()实现。 Windows多线程CRT在此痛苦地崩溃,因为它在每次调用isdigit()时检查区域设置的更改。 我们目前的最佳表现来自于perl + tcl的atof实现的最佳表现,并且比msvcrt.dll的atof表现高出一个数量级。 我想做得更好,但是没有主意。 与BCD相关的x86指令似乎很有希望,但我无法胜过perl / tcl C代码。 任何SO's员工都能挖掘出与最佳人才的联系吗? 也欢迎非基于x86程序集的解决方案。 根据初步答案作出的澄清:
约2 ulp的误差对此应用程序很好。 您的准确性要求是什么?如果您真正需要它"正确"(总是获得最接近指定小数点的浮点值),则可能很难击败标准库版本(除了删除已经支持的语言环境之外),因为这需要进行任意精度的算术运算。如果您愿意容忍一个或两个错误(并且超过次标准错误的容忍度),那么cruzer提出的这种方法可以行得通,并且可能会更快,但绝对不会产生<0.5ulp的输出。您将在精度方面做得更好,分别计算整数和小数部分,并在末尾计算分数(例如,对于12345.6789,将其计算为12345 + 6789 / 10000.0,而不是6 * .1 + 7 * .01 + 8 * .001 + 9 * 0.0001),因为0.1是不合理的二进制分数,并且当您计算0.1 ^ n时,误差会迅速累积。这也使您可以使用整数而不是浮点数来进行大多数数学运算。 自(IIRC)286起,BCD指令就尚未在硬件中实现,如今已被微码化。它们不太可能具有很高的性能。 我刚刚完成编码的此实现的运行速度是台式机上内置的" atof"的两倍。它可以在2秒内转换1024 * 1024 * 39个数字输入,而与我系统的标准gnu'atof'相比则是4秒。 (包括设置时间和获取内存等)。
更新: https://github.com/matiu2/yajp 有趣的文件是: https://github.com/matiu2/yajp/blob/master/tests/test_number.cpp https://github.com/matiu2/yajp/blob/master/number.hpp 另外,您可能对执行转换的状态机感兴趣:
在我看来,您想要手动构建一个状态机,其中每个状态都处理第N个输入数字或指数数字。这个状态机的形状像一棵树(没有循环!)。目标是在可能的情况下进行整数算术,并且(显然)要隐式记住状态中的状态变量("前导负号","位置3的小数点"),以避免赋值,存储和以后取回/测试这些值。仅在输入字符上使用普通的旧" if"语句实现状态机(这样,您的树将成为一组嵌套的ifs)。内联访问缓冲区字符;您不希望对 可以简单地抑制前导零。您可能需要在此处循环以处理可笑的长前导零序列。可以在不将累加器置零或乘以十的情况下收集第一个非零数字。前4-9个非零数字(对于16位或32位整数)可以用整数乘以常数10(由大多数编译器转换为几个移位和加法)来收集。 [最重要的是:零数字不需要任何工作,直到找到一个非零数字,然后需要对N个连续零乘以10 ^ N;您可以将所有这些连接到状态机]。根据您计算机字的大小,可以使用32或64位乘法来收集前4-9之后的数字。由于您不关心准确性,因此在收集了32或64位的值之后,您就可以简单地忽略数字。我猜想,当您有固定数量的非零数字时,实际上可以停止运行,具体取决于您的应用程序对这些数字的实际处理方式。在数字字符串中找到一个小数点只会在状态机树中引起一个分支。该分支知道该点的隐式位置,因此知道以后如何按十的幂进行缩放。如果您不喜欢此代码的大小,则可以轻松地组合一些状态机子树。 [在顶部:将整数和小数部分保留为单独的(小)整数。这将需要在末尾进行额外的浮点运算以将整数部分和小数部分组合在一起,这可能不值得]。
[在顶部:将数字对的2个字符收集到一个16位值中,查找16位值。 遇到" E"时,如上收集指数作为整数;在一个预先计算的乘数表中精确地查找预先计算的/按比例缩放的10的幂(如果指数中存在"-"号,则为倒数),然后将所收集的尾数相乘。 (永远不要进行浮点分隔)。由于每个指数采集例程位于树的不同分支(叶)中,因此它必须通过抵消十索引的幂来调整小数点的表观或实际位置。
[最重要的是:如果知道数字的字符线性存储在缓冲区中并且没有越过缓冲区边界,则可以避免 如果做得正确,此方案将对每个非零数字进行一次廉价的乘法加法,对尾数进行一次强制转换为浮点运算,并进行一次浮点乘法以按指数和小数点位置缩放结果。 我还没有实现以上。我已经用循环实现了它的版本,它们非常快。
我已经实施了一些您可能会觉得有用的东西。
我记得我们有一个Winforms应用程序,它在解析某些数据交换文件时执行得如此缓慢,我们都认为这是数据库服务器的崩溃,但是我们的老大实际上发现瓶颈在于将解析后的字符串转换为小数点! 最简单的方法是为字符串中的每个数字(字符)循环,保持连续的总数,将总数乘以10,然后加上下一个数字的值。继续这样做,直到到达字符串的末尾或遇到一个点。如果遇到点,则将整数部分与小数部分分开,然后使用乘数将其自身除以每个数字10。继续添加它们。 示例:123.456
跑步总数= 0,加1(现在是1) 当然,测试一个数字的正确性以及负数将使它更加复杂。但是,如果您可以"假设"输入正确,则可以使代码更加简单和快捷。 您是否考虑过让GPU完成这项工作?如果您可以将字符串加载到GPU内存中并对其进行处理,那么您可能会发现一种好的算法,其运行速度将比处理器快得多。 或者,在FPGA中进行操作-有一些FPGA PCI-E板可用于制造任意协处理器。使用DMA将FPGA指向包含您要转换的字符串数组的内存部分,并使其通过它们,从而将转换后的值抛在后面。 您是否看过四核处理器?在大多数情况下,真正的瓶颈是内存访问。 -亚当 |
最新内容
相关内容
linux多线程下载命令?
linux多线程下载命令?,软件,工具,平台,中心,系统,代理,网络,网站,手机,官方网站,从linux服务器中下载或上传文件wget是linux下一个从网络上自linux查看多线程命令?
linux查看多线程命令?,系统,第一,线程,地址,数据,进程,命令,名称,软件,情况,如何查看linux服务器的cpu数量,内核数,和cpu线程数如何查看linuxlinux下载命令多线程?
linux下载命令多线程?,系统,单位,概念,数据,线程,进程,产品,地址,代码,状态,谁有linux下多线程库的源码啊,要确实可用的,确实可以免费下载的,linux多线程跑命令?
linux多线程跑命令?,系统,代码,单位,地址,工具,入口,信息,管理,位置,服务,Linux多线程之同步互斥锁和读写锁:提供对临界资源的保护,当多线程试图Python3多线程爬虫讲解
Python3多线程爬虫讲解,代码,分时,系统,网络,状态,培训,做多,时间,线程,爬虫,多线程概述多线程使得程序内部可以分出多个线程来做多件事情,充什么是Python的多进程和多线程?
什么是Python的多进程和多线程?,代码,工作,线程,进程,培训,技术,系统,数据,通讯,任务,学Python的朋友听说过进程和线程吗?其实,不仅是Python,学Python的多线程
Python的多线程,数据,线程,状态,地址,时间,队列,标准,情况,概念,暂停,多线程类似于同时执行多个不同程序,多线程运行有如下优点:使用线程可以把如何优化 Python
如何优化 Python,代码,项目,情况,在线,技术,电脑,大规模,合法,策略,培训,我最喜欢Python的一点就是它可以让你一步一步地优化你的代码。比如Python 多线程与速度
Python 多线程与速度,代码,数据,项目,设计,有限,服务,生产,工作,受益,有望,问题:Python的总体性能较慢,有限的线程与孱弱的多处理能力成为其未优化 Python 程序的内存占用
优化 Python 程序的内存占用,代码,数据,情况,培训,对象,字典,内存,垃圾,程序,机制,Python的垃圾回收机制通过引用计数来决定一个对象要不要被如何提速优化python代码?
如何提速优化python代码?,代码,时间,数据,新增,写法,包装,情况,下来,面临,工作,Python是一种脚本语言,相比C/C++这样的编译语言,在效率和性能方Python 多线程死锁问题的巧妙解决
Python 多线程死锁问题的巧妙解决方法,异常,持有,代码,情况,信息,管理,数据,包装,策略,预期,死锁死锁的原理非常简单,用一句话就可以描述完。