有没有更快的方法来解析文本而不是文本的每个字节?
我想知道是否有任何特殊的CPU(x86 / x64)指令用于字符串库使用的字符串操作,它以某种方式用于优化解析例程。
例如指令,如在字符串中查找可由硬件运行的标记,而不是循环每个字节,直到找到标记为止。
*编辑 - >注意:我要求更多的算法而不是CPU架构,所以我真正的问题是,是否有任何特殊的算法或特定技术可以优化字符串操作例程给定当前的cpu架构。 / p>
答案 0 :(得分:5)
x86有一些字符串指令,但它们在现代处理器上不受欢迎,因为它们变得比执行相同操作的更原始指令慢。
处理器世界越来越多地转向RISC,即简化的指令集。
引自Wikipedia(强调我的):
第一个高度(或紧密)流水线x86实现,来自Intel,AMD,Cyrix和IBM的486设计,支持其前任所做的每条指令,但仅在相当简单的x86子集上实现了最高效率类似于典型的RISC指令集(即没有典型的RISC加载存储限制)。
今天的x86处理器仍然如此。
你可以一次略微更好地处理四个字节,假设文本中的每个“标记”都是四字节对齐的。显然,大多数文本都不是这样......所以最好坚持逐字节扫描。
答案 1 :(得分:3)
是的,有特殊的CPU指令;实现像strchr
这样的函数的运行时库可以用汇编语言编写。
一种比行走字节更快的技术是走双字,即一次处理32位数据。
在字符串的上下文中行走大于最小可寻址内存单元块的问题是对齐
在函数的开头和结尾添加代码(在循环之前和之后),以处理不均匀/未对齐的字节[s]。 (耸肩)它使你的代码更快:不简单。 以下是一些声称是strchr的改进版本的源代码。它使用特殊的CPU指令,但它并不简单(并且有未对齐字节的额外代码):
PATCH: Optimize strchr/strrchr with SSE4.2 - “这个补丁增加了SSE4.2优化的strchr / strrchr。它可以在英特尔酷睿i7上加速strchr / strrchr最多2倍”
答案 2 :(得分:2)
虽然(某些)处理器确实有字符串指令,但它们在生成更快的代码方面几乎没用。首先,正如@ zildjohn01所指出的那样,它们通常比当前处理器的其他指令慢。更重要的是,无论如何,它几乎没有太大的区别 - 如果你正在扫描很多文本,那么瓶颈通常是从内存到CPU的带宽,所以你对改变指令所做的任何事情都可能产生重大影响无论如何。
也就是说,特别是如果您要查找的令牌很长,更好的算法可能会有用。 Boyer-Moore搜索(或变体)可以避免查看某些文本,这可以带来实质性的改进。
答案 3 :(得分:1)
嗯,你必须在某种程度上看一切了解文本的一切。可以说,您可以使用某种结构化文本,它可以为您提供有关在某种空间分区中每个点行走的更多信息。但是,当文件创建时,“解析”部分已经完成。从0信息开始,您需要触摸每个字节以了解所有内容。
答案 4 :(得分:0)
是。由于您的编辑专门要求算法,我想添加一个示例。
您将了解正在解析的语言,并且在构建解析器时可以使用该知识。例如,一种语言,其中每个标记必须至少两个字符,但令牌之间可能出现任何长度的空白。现在,当您通过空格扫描下一个标记时,您可以跳过每一个字符。只有当您点击第一个非空格时,才需要备份一个字符。
示例:
01234567890123456789
FOO BAR
当扫描下一个标记时,你会探测4,6,8,10和12.只有当你看到A时你回头看11才能找到B.你从未看过3,5,7和9。
的特例答案 5 :(得分:0)
即使这个问题早已不复存在,我还有另一个答案。
解析的最快方法是根本不解析。咦?!
我的意思是,从统计上来说,大多数源代码文本以及从该源代码生成的大多数代码和数据都不会从编译变为编译。
因此,您可以使用称为渐进式编译的技术。第一次编译源代码时,将其划分为粗粒度块,例如,在全局声明和函数体的边界处。您必须保留块的源,或其签名或校验和,以及有关边界的信息,它们编译的内容等。
下次你需要重新编译同一个源时,在相同的环境下,你可以驰骋源代码寻找变化。一种简单的方法是将当前代码(一次是长字)与上次保存的代码的持久快照进行比较。只要长字匹配,您就跳过源;而不是解析和编译,您从上次重用该部分的快照编译结果。
如“C#'88”,QuickC 2.0和VC ++ 4.0增量重新编译中所示。
快乐的黑客攻击!
答案 6 :(得分:0)
有没有更快的方法来解析文本而不是文本的每个字节?
是的,有时您可以跳过数据。 Boyer-Moore string search algorithm基于这个想法。
当然,如果解析操作的结果需要以某种方式包含文本中的所有信息,那么就无法读取所有内容。如果您想避免CPU负载,我可以使用hardware which processes data构建direct memory access。