rep stosb 指令如何比等效循环执行得更快?

How can the rep stosb instruction execute faster than the equivalent loop?

指令 rep stosb 怎么能比这段代码执行得更快?

    Clear: mov byte [edi],AL       ; Write the value in AL to memory
           inc edi                 ; Bump EDI to next byte in the buffer
           dec ecx                 ; Decrement ECX by one position
           jnz Clear               ; And loop again until ECX is 0

是否保证在所有现代 CPU 上都是如此?我应该总是更喜欢使用 rep stosb 而不是手动编写循环吗?

在现代 CPU 中,rep stosbrep movsb 的微码实现实际上使用了比 1B 更宽的存储,因此它可以走得更远每个时钟快于一个字节。

(请注意,此 适用于 stos 和 movs,不适用于 repe cmpsbrepne scasb。他们'不幸的是,仍然很慢,与 Skylake 相比,每字节最多 2 个周期,这与实现 memcmp 或 memchr 的 AVX2 vpcmpeqb 相比是可悲的。参见 https://agner.org/optimize/ for instruction tables, and other perf links in the x86 tag wiki

有关 gcc 不明智地内联 repnz scasb 的示例或碰巧变大的 strlen 的不太糟糕的标量 bithack 以及简单的 SIMD 替代方案,请参见 。)


rep stos/movs 具有显着的启动开销,但对于大型 memset/memcpy 来说提升良好。 (请参阅 Intel/AMD 的优化手册,了解何时使用 rep stos 与小型缓冲区的矢量化循环的讨论。)但是,如果没有 ERMSB 功能,rep stosb 被调整为中等到小内存集,最好使用 rep stosdrep stosq(如果您不打算使用 SIMD 循环)。

当使用调试器单步执行时,rep stos 只进行一次迭代(ecx/rcx 的一次递减),因此微码实现永远不会进行。不要让这让您误以为 可以做到。

有关英特尔 P6/SnB-family 微体系结构如何实现 rep movs 的一些详细信息,请参阅

有关 rep movsb 与 SSE 或 AVX 循环的内存带宽考虑,请参见 在 Intel CPUs 上ERMSB 功能。 (特别注意多核 Xeon CPUs 不能只用一个线程使 DRAM 带宽饱和,因为同时有多少缓存未命中以及 RFO 与非 RFO 存储协议的限制.)


现代英特尔 CPU 应该 运行 问题中的 asm 循环每个时钟迭代一次,但 AMD 推土机系列内核可能甚至无法每个时钟管理一个存储。 (处理 inc/dec/branch 指令的两个整数执行端口存在瓶颈。如果循环条件是 edi 上的 cmp/jcc,则 AMD 内核可以宏融合比较和分支。)


Intel P6 和 SnB 系列 CPUs 上所谓的快速字符串操作(rep movsrep stos 的一个主要特征是它们避免了读取所有权存储到以前未缓存的内存时缓存一致性流量。所以这就像使用 NT 存储来写入整个缓存行,但仍然是强顺序的。(ERMSB 功能确实使用弱顺序存储)。

IDK AMD 的实现有多好。


(还有一个更正:我之前说过英特尔 SnB 只能处理每 2 个时钟一个分支的吞吐量,但实际上它可以 运行 每个时钟迭代一次的微小循环。)

查看从 标签 wiki 链接的优化资源(尤其是 Agner Fog 的指南)。


Intel IvyBridge 和后来的 ERMSB,它允许 rep stos[b/w/d/q]rep movs[b/w/d/q] 使用弱顺序存储(如 movnt),允许存储提交到缓存外命令。如果并非所有目标都已在 L1 缓存中热,则这是一个优势。我相信,从文档的措辞来看,,因此任何重新排序仅在字符串操作创建的存储之间可见,而不是在它与其他存储之间可见。即你仍然不需要 sfence after rep movs.

因此,对于 Intel IvB 及更高版本上的大型对齐缓冲区,memsetrep stos 实现可以击败任何其他实现。使用 movnt 存储(不将数据留在缓存中)的存储也应该接近饱和主内存写入带宽,但实际上可能跟不上。请参阅评论以讨论此问题,但我找不到任何数字。

对于小缓冲区,不同的方法有非常不同的开销。微基准测试可以使 SSE/AVX 复制循环看起来比实际情况更好,因为每次都使用相同的大小和对齐方式进行复制可以避免 startup/cleanup 代码中的分支预测错误。 IIRC,建议在 Intel CPUs(不是 rep movs)上对 128B 以下的副本使用矢量化循环。根据 CPU 和周围的代码,阈值可能会更高。

Intel 的优化手册也有一些关于不同 memcpy 实现的开销的讨论,rep movsbmovdqu.

对错位的惩罚更大

查看优化 memset/memcpy 实现的代码,了解有关实际操作的更多信息。 (例如 Agner Fog 的图书馆)。

如果您的 CPU 具有 CPUID ERMSB 位,则 rep movsbrep stosb 命令的执行方式与旧处理器不同。

参见 Intel Optimization Reference Manual,第 3.7.6 节增强的 REP MOVSB 和 REP STOSB 操作 (ERMSB)。

手册和我的测试都表明 rep stosb 与通用 32 位寄存器相比,在 32 位 CPU Skylake 微架构上移动的好处仅出现在大内存块上,更大超过 128 字节。在较小的块上,例如 5 个字节,您显示的代码 (mov byte [edi],al; inc edi; dec ecx; jnz Clear) 会快得多,因为 rep stosb 非常高 - 大约 35 个周期。然而,这种速度差异在 2019 年 9 月推出的 Ice Lake 微架构上已经缩小,引入了 Fast Short REP MOV (FSRM) 功能。此功能可以通过 CPUID 位进行测试。它旨在使 128 字节和更短的字符串更快,但实际上,使用 rep movsb 时,64 字节之前的字符串仍然比使用简单的 64 位寄存器复制慢。除此之外,FSRM 仅在 64 位下实现,而不是在 32 位下实现。至少在我的 i7-1065G7 CPU 上,rep movsb 仅适用于 64 位以下的小字符串,但在 32 位上,字符串必须至少为 4KB 才能 rep movsb 开始超越其他方法。

要在具有 CPUID ERMSB 位的处理器上获得 rep stosb 的优势,应满足以下条件:

  • 目标缓冲区必须与 16 字节边界对齐;
  • 如果长度是64的倍数,性能会更高;
  • 方向位应设置为“正向”(由 cld 指令设置)。

根据英特尔优化手册,当内存块的长度至少为 128 字节时,ERMSB 开始优于通过常规寄存器在 Skylake 上进行的内存存储。正如我所写,内部启动 ERMSB 较高 - 大约 35 个周期。当长度超过 2048 字节时,ERMSB 开始明显优于其他方法,包括 AVX 复制和填充。但是,这主要适用于 Skylake 微架构,而其他 CPU 微架构不一定如此。

在某些处理器上,但在其他处理器上,当目标缓冲区是 16 字节对齐时,使用 ERMSB 的 REP STOSB 可以比 SIMD 方法执行得更好,即,当使用 MMX 或 SSE 寄存器时。当目标缓冲区未对齐时,对于基于英特尔微体系结构代号 Ivy Bridge 的处理器,使用 ERMSB 的 memset() 性能相对于对齐情况会降低约 20%。相比之下,根据英特尔的优化手册,当目标未对齐时,REP STOSB 的 SIMD 实现将经历更微不足道的降级。

基准

我做了一些基准测试。代码多次填充相同的 fixed-size 缓冲区,因此缓冲区保留在缓存中(L1、L2、L3),具体取决于缓冲区的大小。迭代次数如总执行时间应该在两秒左右。

天湖

在 2015 年 9 月发布的英特尔酷睿 i5 6600 处理器上,基于 Skylake-S quad-core 微架构(3.30 GHz 基本频率,3.90 GHz 最大睿频),4 x 32K L1 缓存,4 x 256K L2 缓存和 6MB L3 缓存,我可以在具有 32K 块的 REP STOSB 上获得 ~100 GB/sec。

使用REP STOSB的memset()实现:

  • 1297920000 个 16 字节块:13.6022 秒 1455.9909 Megabytes/sec
  • 0648960000 个 32 字节块:06.7840 秒 2919.3058 Megabytes/sec
  • 1622400000 个 64 字节块:16.9762 秒 5833.0883 Megabytes/sec
  • 817587402 个 127 字节的块:8.5698 秒 11554.8914 Megabytes/sec
  • 811200000 个 128 字节块:8.5197 秒 11622.9306 Megabytes/sec
  • 804911628 个 129 字节的块:9.1513 秒 10820.6427 Megabytes/sec
  • 407190588 个 255 字节的块:5.4656 秒 18117.7029 Megabytes/sec
  • 405600000 个 256 字节块:5.0314 秒 19681.1544 Megabytes/sec
  • 202800000 个 512 字节块:2.7403 秒 36135.8273 Megabytes/sec
  • 101400000 个 1024 字节块:1.6704 秒 59279.5229 Megabytes/sec
  • 3168750 个 32768 字节的块:0.9525 秒 103957.8488 Megabytes/sec (!),即 10 GB/s
  • 2028000 个 51200 字节的块:1.5321 秒 64633.5697 Megabytes/sec
  • 413878 个 250880 字节的块:1.7737 秒 55828.1341 Megabytes/sec
  • 19805 个 5242880 字节的块:2.6009 秒 38073.0694 Megabytes/sec

使用MOVDQA [RCX],XMM0的memset()实现:

  • 1297920000 个 16 字节块:3.5795 秒 5532.7798 Megabytes/sec
  • 0648960000 个 32 字节块:5.5538 秒 3565.9727 Megabytes/sec
  • 1622400000 个 64 字节块:15.7489 秒 6287.6436 Megabytes/sec
  • 817587402 个 127 字节的块:9.6637 秒 10246.9173 Megabytes/sec
  • 811200000 个 128 字节的块:9.6236 秒 10289.6215Megabytes/sec
  • 804911628 个 129 字节的块:9.4852 秒 10439.7473 Megabytes/sec
  • 407190588 个 255 字节的块:6.6156 秒 14968.1754 Megabytes/sec
  • 405600000 个 256 字节的块:6.6437 秒 14904.9230 Megabytes/sec
  • 202800000 个 512 字节块:5.0695 秒 19533.2299 Megabytes/sec
  • 101400000 个 1024 字节块:4.3506 秒 22761.0460 Megabytes/sec
  • 3168750 个 32768 字节的块:3.7269 秒 26569.8145 Megabytes/sec (!) 即 26 GB/s
  • 2028000 个 51200 字节的块:4.0538 秒 24427.4096 Megabytes/sec
  • 413878 个 250880 字节的块:3.9936 秒 24795.5548 Megabytes/sec
  • 19805 个 5242880 字节的块:4.5892 秒 21577.7860 Megabytes/sec

请注意,使用 XMM0 寄存器的缺点是它是 128 位(16 字节),而我可以使用 256 位(32 字节)的 YMM0 寄存器。无论如何,stosb 使用 non-RFO 协议。自 1996 年的 Pentium Pro (P6) 以来,Intel x86 就拥有“快速字符串”。P6 快速字符串采用 REP MOVSB 和更大的字符串,并使用 64 位微代码加载和存储以及 non-RFO 缓存协议来实现它们。与 Ivy Bridge 中的 ERMSB 不同,它们没有违反内存顺序。有关详细信息和来源,请参阅

无论如何,即使您只比较我提供的两种方法,尽管第二种方法远非理想,如您所见,在 64 位块上 rep stosb 速度较慢,但​​开始从 128 字节块开始,rep stosb 开始优于其他方法,从 512 字节块开始,差异非常显着,前提是您在缓存中一次又一次地清除相同的内存块。

因此,对于REP STOSB,最大速度为每秒103957(十万三千九百fifty-seven)兆字节,而使用MOVDQA [RCX],XMM0 时仅为26569(twenty-six千五百sixty-nine)twenty-six千五百sixty-nine.

如您所见,最高性能是在 32K 块上,这相当于我进行基准测试的 CPU 的 32K L1 缓存。

冰湖

REP STOSB 对比 AVX-512 商店

我还在 2019 年 8 月发布的英特尔 i7 1065G7 CPU 上进行了测试(Ice Lake/Sunny Cove 微架构),基本频率:1.3 GHz,最大 Turbo 频率 3.90 GHz。支持AVX512F指令集。它有4 x 32K L1指令缓存和4 x 48K数据缓存,4x512K L2缓存和8 MB L3缓存。

目标对齐

在由 rep stosb 归零的 32K 块上,性能从 175231 MB/s 目标未对齐 1 个字节(例如 $7FF4FDCFFFFF)并迅速上升到 219464 MB/s 对齐 64字节(例如 $7FF4FDCFFFC0),然后逐渐上升到 222424 MB/sec for destinations aligned by 256 bytes(Aligned to 256 bytes,即 $7FF4FDCFFF00)。在那之后,速度没有上升,即使目标对齐了 32KB(例如 $7FF4FDD00000),仍然是 224850 MB/sec.

rep stosbrep stosq 之间的速度没有差异。

在按 32K 对齐的缓冲区上,AVX-512 存储的速度与 rep stosb 完全相同,对于循环中从 2 个存储开始的循环 (227777 MB/sec) 并且没有为 4 甚至 16 家商店展开的循环增长。然而,对于只有 1 个商店的循环,速度稍微低了一点 - 203145 MB/sec.

但是,如果目标缓冲区仅错位 1 个字节,则 AVX512 存储的速度会急剧下降,即下降超过 2 倍,降至 93811 MB/sec,与 rep stosb 相比类似的缓冲区,这给了 175231 MB/sec.

缓冲区大小

  • 对于 1K(1024 字节)块,AVX-512 (205039 KB/s) 比 rep stosb (71817 MB/s)
  • 快 3 倍
  • 对于 512 字节的块,AVX-512 的性能始终与较大的块类型 (194181 MB/s) 相同,而 rep stosb 下降到 38682 MB/s。在这种块类型下,差异是 AVX-512 的 5 倍。
  • 对于 2K (2048) 块,AVX-512 有 210696 MB/s,而对于 rep stosb 它是 123207 MB/s,几乎慢了两倍。同样,rep stosbrep stosq 之间没有区别。
  • 对于 4K (4096) 块,AVX-512 有 225179 MB/s,而 rep stosb:180384 MB/s,几乎赶上了。
  • 对于 8K (8192) 块,AVX-512 有 222259 MB/s,而 rep stosb:194358 MB/s,关闭!
  • 对于 32K (32768) 个块,AVX-512 有 228432 MB/srep stosb220515 MB/s - 现在终于来了!我们正在接近我 CPU 的 L0 数据缓存大小 - 48Kb!这是每秒 220 GB!
  • 对于 64K (65536) 块,AVX-512 有 61405 MB/s,rep stosb:70395 MB/s!
  • 当我们 运行 离开 L0 缓存时,下降如此之大!而且,很明显,从这一点开始,rep stosb 开始跑赢 AVX-512 商店。
  • 现在让我们检查一下一级缓存大小。对于 512K 块,AVX-512 生成 62907 MB/s 和rep stosb 制作了 70653 MB/s。这就是 rep stosb 开始超越 AVX-512 的地方。差异尚不显着,但缓冲区越大,差异越大。
  • 现在让我们使用 1GB (1073741824) 的巨大缓冲区。使用 AVX-512,速度为 14319 MB/s,rep stosb 为 27412 MB/s,即 AVX-512 的两倍!

我也曾尝试使用 non-temporal 指令来填充 32K 缓冲区 vmovntdq [rcx], zmm31,但性能比 vmovdqa64 [rcx], zmm31 慢了大约 4 倍。填充内存缓冲区时如何利用 vmovntdq?是否应该有一些特定大小的缓冲区以便vmovntdq利用?

此外,如果目标缓冲区至少对齐 64 位,则 vmovdqa64vmovdqu64 没有性能差异。因此,我确实有一个问题:当我们有 vmovdqu64 时,指令 vmovdqa64 是否仅用于调试和安全?

图 1:迭代存储到同一缓冲区的速度,MB/s

block     AVX   stosb
-----   -----  ------
 0.5K  194181   38682
   1K  205039  205039
   2K  210696  123207
   4K  225179  180384
   8K  222259  194358 
  32K  228432  220515 
  64K   61405   70395 
 512K   62907   70653 
   1G   14319   27412

多次清除缓存内同一个内存块的性能总结

rep stosb 在 Ice Lake CPUs 上开始优于 AVX-512 存储,仅用于重复清除大于 L0 缓存大小的相同内存缓冲区,即 Intel i7 1065G7 上的 48K CPU。在小内存缓冲区上,AVX-512 存储速度更快:1KB - 快 3 倍,512 字节 - 快 5 倍。

但是,AVX-512 存储容易受到未对齐缓冲区的影响,而 rep stosb 对未对齐不那么敏感。

因此,我发现 rep stosb 开始优于 AVX-512 存储仅在超过 L0 数据缓存大小的缓冲区上,或 48KB,如 Intel i7 1065G7 CPU。这个结论至少在 Ice Lake CPUs 上是有效的。较早的英特尔建议,对于较新的微体系结构,字符串复制从 2KB 缓冲区开始优于 AVX 复制也应该是 re-tested。

清除不同的内存缓冲区,每个缓冲区只有一次

我以前的基准测试连续多次填充同一个缓冲区。更好的基准可能是分配许多不同的缓冲区并且每个缓冲区只填充一次,以免干扰缓存。

在这种情况下,rep stosb 和 AVX-512 商店之间没有太大区别。唯一的区别是当所有数据都没有接近物理内存限制时,在 Windows 10 64 位下。在以下基准测试中,总数据大小低于 8 GB,总物理内存为 16 GB。当我分配大约 12 GB 时,无论使用何种方法,性能都会下降大约 20 倍。 Windows 开始丢弃清除的内存页面,并且可能在内存快满时做了一些其他事情。 i7 1065G7 CPU 上 8MB 的 L3 缓存大小似乎与基准测试无关。重要的是您不必接近物理内存限制,这取决于您的操作系统如何处理这种情况。正如我所说,在 Windows 10 下,如果我只占用一半的物理内存,那还可以,但如果我占用了 3/4 的可用内存,我的基准测试速度会降低 20 倍。我什至没有尝试超过 3/4。正如我所说,总内存大小为 16 GB。根据任务管理器,可用容量为 12 GB。

这是在总内存为 16 GB 的 i7 1065G7 CPU 上用零(在 MB/sec 中)填充总计 8 GB 的各种内存块的速度基准,single-threaded. “AVX”是指“AVX-512”普通商店,“s​​tosb”是指“rep stosb”。

图 2:存储到多个缓冲区的速度,每个缓冲区一次,MB/s

block    AVX  stosb
-----   ----   ----
 0.5K   3641   2759
   1K   4709   3963
   2K  12133  13163
   4K   8239  10295
   8K   3534   4675
  16K   3396   3242
  32K   3738   3581
  64K   2953   3006
 128K   3150   2857
 256K   3773   3914
 512K   3204   3680
1024K   3897   4593
2048K   4379   3234
4096K   3568   4970
8192K   4477   5339

清除缓存内内存的结论

如果您的内存不在缓存中,当您需要用零填充内存时,AVX-512 存储的性能与 rep stosb 大致相同。重要的是缓存,而不是这两种方法之间的选择。

使用non-temporal store 清除不在缓存中的内存

我正在将 6-10 GB 的内存归零,这些内存由按 64 字节对齐的一系列缓冲区分割。没有缓冲区被两次清零。较小的缓冲区有一些开销,而且我只有 16 GB 的物理内存,所以我使用较小的缓冲区将较少的内存归零。我对从 256 字节到每个缓冲区最大 8 GB 的缓冲区进行了各种测试。 我采用了 3 种不同的方法:

  1. 正常的AVX-512 store by vmovdqa64 [rcx+imm], zmm31(循环4个store然后比较计数器);
  2. Non-temporal AVX-512 存储 vmovntdq [rcx+imm], zmm31(4 个存储的相同循环);
  3. rep stosb.

对于小缓冲区,普通的 AVX-512 存储是赢家。然后,从4KB开始,non-temporal存储领先,而rep stosb仍然落后。

然后,从 256KB 开始,rep stosb 优于 AVX-512,但不是 non-temporal 存储,从那以后,情况没有改变。获胜者是一个non-temporal AVX-512 商店,然后是 rep stosb 然后是正常的 AVX-512 商店。

图 3. 存储到多个缓冲区的速度,每个缓冲区一次,MB/s 通过三种不同的方法:正常 AVX-512 存储、非临时 AVX-512 存储和 rep stosb。

Zeroized 6.67 GB: 27962026 blocks of 256 bytes for 2.90s, 2.30 GB/s by normal AVX-512 store
Zeroized 6.67 GB: 27962026 blocks of 256 bytes for 3.05s, 2.18 GB/s by nontemporal AVX-512 store
Zeroized 6.67 GB: 27962026 blocks of 256 bytes for 3.05s, 2.18 GB/s by rep stosb

Zeroized 8.00 GB: 16777216 blocks of 512 bytes for 3.06s, 2.62 GB/s by normal AVX-512 store
Zeroized 8.00 GB: 16777216 blocks of 512 bytes for 3.02s, 2.65 GB/s by nontemporal AVX-512 store
Zeroized 8.00 GB: 16777216 blocks of 512 bytes for 3.66s, 2.18 GB/s by rep stosb

Zeroized 8.89 GB: 9320675 blocks of 1 KB for 3.10s, 2.87 GB/s by normal AVX-512 store
Zeroized 8.89 GB: 9320675 blocks of 1 KB for 3.37s, 2.64 GB/s by nontemporal AVX-512 store
Zeroized 8.89 GB: 9320675 blocks of 1 KB for 4.85s, 1.83 GB/s by rep stosb

Zeroized 9.41 GB: 4934475 blocks of 2 KB for 3.45s, 2.73 GB/s by normal AVX-512 store
Zeroized 9.41 GB: 4934475 blocks of 2 KB for 3.79s, 2.48 GB/s by nontemporal AVX-512 store
Zeroized 9.41 GB: 4934475 blocks of 2 KB for 4.83s, 1.95 GB/s by rep stosb

Zeroized 9.70 GB: 2542002 blocks of 4 KB for 4.40s, 2.20 GB/s by normal AVX-512 store
Zeroized 9.70 GB: 2542002 blocks of 4 KB for 3.46s, 2.81 GB/s by nontemporal AVX-512 store
Zeroized 9.70 GB: 2542002 blocks of 4 KB for 4.40s, 2.20 GB/s by rep stosb

Zeroized 9.85 GB: 1290555 blocks of 8 KB for 3.24s, 3.04 GB/s by normal AVX-512 store
Zeroized 9.85 GB: 1290555 blocks of 8 KB for 2.65s, 3.71 GB/s by nontemporal AVX-512 store
Zeroized 9.85 GB: 1290555 blocks of 8 KB for 3.35s, 2.94 GB/s by rep stosb

Zeroized 9.92 GB: 650279 blocks of 16 KB for 3.37s, 2.94 GB/s by normal AVX-512 store
Zeroized 9.92 GB: 650279 blocks of 16 KB for 2.73s, 3.63 GB/s by nontemporal AVX-512 store
Zeroized 9.92 GB: 650279 blocks of 16 KB for 3.53s, 2.81 GB/s by rep stosb

Zeroized 9.96 GB: 326404 blocks of 32 KB for 3.19s, 3.12 GB/s by normal AVX-512 store
Zeroized 9.96 GB: 326404 blocks of 32 KB for 2.64s, 3.77 GB/s by nontemporal AVX-512 store
Zeroized 9.96 GB: 326404 blocks of 32 KB for 3.44s, 2.90 GB/s by rep stosb

Zeroized 9.98 GB: 163520 blocks of 64 KB for 3.08s, 3.24 GB/s by normal AVX-512 store
Zeroized 9.98 GB: 163520 blocks of 64 KB for 2.58s, 3.86 GB/s by nontemporal AVX-512 store
Zeroized 9.98 GB: 163520 blocks of 64 KB for 3.29s, 3.03 GB/s by rep stosb

Zeroized 9.99 GB: 81840 blocks of 128 KB for 3.22s, 3.10 GB/s by normal AVX-512 store
Zeroized 9.99 GB: 81840 blocks of 128 KB for 2.49s, 4.01 GB/s by nontemporal AVX-512 store
Zeroized 9.99 GB: 81840 blocks of 128 KB for 3.26s, 3.07 GB/s by rep stosb

Zeroized 10.00 GB: 40940 blocks of 256 KB for 2.52s, 3.97 GB/s by normal AVX-512 store
Zeroized 10.00 GB: 40940 blocks of 256 KB for 1.98s, 5.06 GB/s by nontemporal AVX-512 store
Zeroized 10.00 GB: 40940 blocks of 256 KB for 2.43s, 4.11 GB/s by rep stosb

Zeroized 10.00 GB: 20475 blocks of 512 KB for 2.15s, 4.65 GB/s by normal AVX-512 store
Zeroized 10.00 GB: 20475 blocks of 512 KB for 1.70s, 5.87 GB/s by nontemporal AVX-512 store
Zeroized 10.00 GB: 20475 blocks of 512 KB for 1.81s, 5.53 GB/s by rep stosb

Zeroized 10.00 GB: 10238 blocks of 1 MB for 2.18s, 4.59 GB/s by normal AVX-512 store
Zeroized 10.00 GB: 10238 blocks of 1 MB for 1.50s, 6.68 GB/s by nontemporal AVX-512 store
Zeroized 10.00 GB: 10238 blocks of 1 MB for 1.63s, 6.13 GB/s by rep stosb

Zeroized 10.00 GB: 5119 blocks of 2 MB for 2.02s, 4.96 GB/s by normal AVX-512 store
Zeroized 10.00 GB: 5119 blocks of 2 MB for 1.59s, 6.30 GB/s by nontemporal AVX-512 store
Zeroized 10.00 GB: 5119 blocks of 2 MB for 1.54s, 6.50 GB/s by rep stosb

Zeroized 10.00 GB: 2559 blocks of 4 MB for 1.90s, 5.26 GB/s by normal AVX-512 store
Zeroized 10.00 GB: 2559 blocks of 4 MB for 1.37s, 7.29 GB/s by nontemporal AVX-512 store
Zeroized 10.00 GB: 2559 blocks of 4 MB for 1.47s, 6.81 GB/s by rep stosb

Zeroized 9.99 GB: 1279 blocks of 8 MB for 2.04s, 4.90 GB/s by normal AVX-512 store
Zeroized 9.99 GB: 1279 blocks of 8 MB for 1.51s, 6.63 GB/s by nontemporal AVX-512 store
Zeroized 9.99 GB: 1279 blocks of 8 MB for 1.56s, 6.41 GB/s by rep stosb

Zeroized 9.98 GB: 639 blocks of 16 MB for 1.93s, 5.18 GB/s by normal AVX-512 store
Zeroized 9.98 GB: 639 blocks of 16 MB for 1.37s, 7.30 GB/s by nontemporal AVX-512 store
Zeroized 9.98 GB: 639 blocks of 16 MB for 1.45s, 6.89 GB/s by rep stosb

Zeroized 9.97 GB: 319 blocks of 32 MB for 1.95s, 5.11 GB/s by normal AVX-512 store
Zeroized 9.97 GB: 319 blocks of 32 MB for 1.41s, 7.06 GB/s by nontemporal AVX-512 store
Zeroized 9.97 GB: 319 blocks of 32 MB for 1.42s, 7.02 GB/s by rep stosb

Zeroized 9.94 GB: 159 blocks of 64 MB for 1.85s, 5.38 GB/s by normal AVX-512 store
Zeroized 9.94 GB: 159 blocks of 64 MB for 1.33s, 7.47 GB/s by nontemporal AVX-512 store
Zeroized 9.94 GB: 159 blocks of 64 MB for 1.40s, 7.09 GB/s by rep stosb

Zeroized 9.88 GB: 79 blocks of 128 MB for 1.99s, 4.96 GB/s by normal AVX-512 store
Zeroized 9.88 GB: 79 blocks of 128 MB for 1.42s, 6.97 GB/s by nontemporal AVX-512 store
Zeroized 9.88 GB: 79 blocks of 128 MB for 1.55s, 6.37 GB/s by rep stosb

Zeroized 9.75 GB: 39 blocks of 256 MB for 1.83s, 5.32 GB/s by normal AVX-512 store
Zeroized 9.75 GB: 39 blocks of 256 MB for 1.32s, 7.38 GB/s by nontemporal AVX-512 store
Zeroized 9.75 GB: 39 blocks of 256 MB for 1.64s, 5.93 GB/s by rep stosb

Zeroized 9.50 GB: 19 blocks of 512 MB for 1.89s, 5.02 GB/s by normal AVX-512 store
Zeroized 9.50 GB: 19 blocks of 512 MB for 1.31s, 7.27 GB/s by nontemporal AVX-512 store
Zeroized 9.50 GB: 19 blocks of 512 MB for 1.42s, 6.71 GB/s by rep stosb

Zeroized 9.00 GB: 9 blocks of 1 GB for 1.76s, 5.13 GB/s by normal AVX-512 store
Zeroized 9.00 GB: 9 blocks of 1 GB for 1.26s, 7.12 GB/s by nontemporal AVX-512 store
Zeroized 9.00 GB: 9 blocks of 1 GB for 1.29s, 7.00 GB/s by rep stosb

Zeroized 8.00 GB: 4 blocks of 2 GB for 1.48s, 5.42 GB/s by normal AVX-512 store
Zeroized 8.00 GB: 4 blocks of 2 GB for 1.07s, 7.49 GB/s by nontemporal AVX-512 store
Zeroized 8.00 GB: 4 blocks of 2 GB for 1.15s, 6.94 GB/s by rep stosb

Zeroized 8.00 GB: 2 blocks of 4 GB for 1.48s, 5.40 GB/s by normal AVX-512 store
Zeroized 8.00 GB: 2 blocks of 4 GB for 1.08s, 7.40 GB/s by nontemporal AVX-512 store
Zeroized 8.00 GB: 2 blocks of 4 GB for 1.14s, 7.00 GB/s by rep stosb

Zeroized 8.00 GB: 1 blocks of 8 GB for 1.50s, 5.35 GB/s by normal AVX-512 store
Zeroized 8.00 GB: 1 blocks of 8 GB for 1.07s, 7.47 GB/s by nontemporal AVX-512 store
Zeroized 8.00 GB: 1 blocks of 8 GB for 1.21s, 6.63 GB/s by rep stosb

避免AVX-SSE t运行sition惩罚

对于所有 AVX-512 代码,我使用了 ZMM31 寄存器,因为 SSE 寄存器从 0 到 15,所以 AVX-512 寄存器 16 到 31 没有对应的 SSE ,因此不会招致 t运行sition 惩罚。