原文链接:https://lemire.me/blog/2022/05/25/parsing-json-faster-with-intel-avx-512/

许多最新的英特尔处理器都受益于称为 AVX-512 的新指令系列。这些指令在宽寄存器(最多 512 位)上运行,并遵循单指令多数据 (SIMD) 范例。这些新的 AVX-512 指令允许您打破一些速度记录,例如以内存副本的速度解码base64数据。

大多数现代处理器都有 SIMD 指令。AVX-512 指令更宽(每个寄存器更多位),但这不一定是它们的主要吸引力。如果您只是采用现有的 SIMD 算法并将它们应用于 AVX-512,您可能不会获得您想要的那么多好处。的确,更宽的寄存器是有益的,但在超标量处理器(每个周期可以发出多条指令的处理器)中,每个周期可以发出的指令数量同样重要。通常地,处理器每个周期可以发出的 512 位 AVX-512 的指令更少,因此这些指令更耗费资源。要想真正充分利用 AVX-512,开发者需要仔细设计代码,而与此同时英特尔还在不断增加新的指令。总的说,AVX-512 不是单个技术,而是一个系列指令集。

此外,AVX-512 指令的早期实现通常会导致可测量的降频:处理器会在使用这些指令后一段时间内降低其频率。值得庆幸的是,支持 AVX-512(Rocket Lake 和 Ice Lake)的最新英特尔处理器已经取消了这种系统的频率限制。值得庆幸的是,在运行时很容易检测到这些最新的处理器。

几年前,我们发布了一个名为 simdjson 的非常快速的 C++ JSON 解析器。它作为解析器有些独特,因为它严重依赖 SIMD 指令。在几个指标上,它曾经是并且仍然是最快的 JSON 解析器,尽管已经出现了其他有趣的竞争对手。

最初,我为 simdjson 编写了一个快速而肮脏的 AVX-512 内核。我们从未合并它,一段时间后,我只是将其删除。然后我就忘记了。

感谢有才华的英特尔工程师(Fangzheng Zhang 和 Weiqiang Wan)的贡献,以及本博客读者(Kim Walisch 和 Jatin Bhateja)的间接贡献,我们制作了一个新的 AVX-512 内核。与往常一样,simdjson 是许多人的工作,是一个由数十名贡献者组成的整个社区。我必须对第一次写信给我关于 AVX-512 端口的张方正表示感谢。

我们刚刚发布了最新版本的 simdjson。它打破了新的速度记录。

考虑一个有趣的测试,您试图扫描整个文件(跨越千字节)以找到与某个标识符对应的值。在simdjson中,代码如下:

1
2
3
4
5
6
7
8
auto doc = parser.iterate(json);    
for (auto tweet : doc.find_field("statuses")) {
if (uint64_t(tweet.find_field("id")) == find_id) {
result = tweet.find_field("text");
return true;
}
}
return false;

在带有 GCC 11 的 Tiger Lake 处理器上,处理速度提高了 60%,以每秒处理的输入字节数表示。

simdjson (512-bit SIMD): new 7.4 GB/s
simdjson (256-bit SIMD): old 4.6 GB/s

速度增益非常重要,因为在这个任务中,我们大多只是读取数据,而我们做的二次处理相对较少。我们不会从 JSON 数据中创建树,也不会创建数据结构。

simdjson 库有一个缩小功能,它只是从输入中去除不必要的空格。也许令人惊讶的是,我们的速度是之前基线的两倍多:

simdjson (512-bit SIMD): new 12 GB/s
simdjson (256-bit SIMD): old 4.3 GB/s

另一个合理的基准是将输入完全解析为具有完全验证的 DOM 树。解析标准 JSON 文件 ( twitter.json ),我获得了近 30% 的收益:

simdjson (512-bit SIMD): new 3.6 GB/s
simdjson (256-bit SIMD): old 2.8 GB/s

虽然 30% 听起来可能并不令人兴奋,但我们是从一个快速的基线开始的。

我们能做得更好吗?肯定的。有许多我们尚未使用的 AVX-512 指令。我们不使用三元布尔运算 ( vpternlog )。我们没有使用新的强大的 shuffle 函数(例如,vpermt2b)。我们有一个共同进化的例子:更好的硬件需要新的软件,这反过来又使硬件大放异彩。

当然,要获得这些新优势,您需要具有足够 AVX-512 支持的最新 Intel 处理器,显然,您还需要相对较新的 C++ 处理器。最近的一些笔记本电脑级英特尔处理器不支持 AVX-512,但如果您依赖 AWS 并拥有大型英特尔节点,您应该没问题。

您可以直接获取我们的版本或等待它到达标准包管理器之一(MSYS2、conan、vcpkg、brew、debian、FreeBSD 等)。