如果您的 CPU 具有 CPUID ERMSB 位,则 rep movsb 和 rep stosb 命令的执行方式与旧处理器不同。
请参阅Intel Optimization Reference Manual,第 3.7.6 节增强的 REP MOVSB 和 REP STOSB 操作 (ERMSB)。
手册和我的测试都表明,与通用 32 位寄存器移动相比,rep stosb 在 Skylake 微架构的 32 位 CPU 上的优势仅出现在大于 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 实现将经历更可忽略的降级。
基准测试
我做了一些基准测试。代码多次填充同一个固定大小的缓冲区,因此缓冲区停留在缓存中(L1、L2、L3),具体取决于缓冲区的大小。迭代次数是这样的,总执行时间应该是两秒左右。
天空湖
在 2015 年 9 月发布的 Intel Core i5 6600 处理器上,基于 Skylake-S 四核微架构(3.30 GHz 基本频率,3.90 GHz 最大 Turbo 频率),具有 4 x 32K L1 缓存、4 x 256K L2 缓存和 6MB L3 缓存,我可以在 REP STOSB 上获得约 100 GB/秒的 32K 块。
使用REP STOSB的memset()实现:
- 1297920000 个 16 字节块:13.6022 秒 1455.9909 兆字节/秒
- 0648960000 个 32 字节块:06.7840 秒 2919.3058 兆字节/秒
- 1622400000 个 64 字节块:16.9762 秒 5833.0883 兆字节/秒
- 817587402 个 127 字节的块:8.5698 秒 11554.8914 兆字节/秒
- 811200000 个 128 字节块:8.5197 秒 11622.9306 兆字节/秒
- 804911628 个 129 字节的块:9.1513 秒 10820.6427 兆字节/秒
- 407190588 个 255 字节的块:5.4656 秒 18117.7029 兆字节/秒
- 405600000 个 256 字节的块:5.0314 秒 19681.1544 兆字节/秒
- 202800000 个 512 字节的块:2.7403 秒 36135.8273 兆字节/秒
- 101400000 个 1024 字节的块:1.6704 秒 59279.5229 兆字节/秒
- 3168750 个 32768 字节的块:0.9525 秒 103957.8488 兆字节/秒 (!),即 10 GB/秒
- 2028000 块 51200 字节:1.5321 秒 64633.5697 兆字节/秒
- 413878 块 250880 字节:1.7737 秒 55828.1341 兆字节/秒
- 19805 块 5242880 字节:2.6009 秒 38073.0694 兆字节/秒
使用MOVDQA [RCX],XMM0的memset()实现:
- 1297920000 个 16 字节块:3.5795 秒 5532.7798 兆字节/秒
- 0648960000 个 32 字节的块:5.5538 秒 3565.9727 兆字节/秒
- 1622400000 个 64 字节块:15.7489 秒 6287.6436 兆字节/秒
- 817587402 个 127 字节的块:9.6637 秒 10246.9173 兆字节/秒
- 811200000 个 128 字节块:9.6236 秒 10289.6215 兆字节/秒
- 804911628 个 129 字节的块:9.4852 秒 10439.7473 兆字节/秒
- 407190588 个 255 字节的块:6.6156 秒 14968.1754 兆字节/秒
- 405600000 个 256 字节的块:6.6437 秒 14904.9230 兆字节/秒
- 202800000 个 512 字节的块:5.0695 秒 19533.2299 兆字节/秒
- 101400000 个 1024 字节的块:4.3506 秒 22761.0460 兆字节/秒
- 3168750 个 32768 字节的块:3.7269 秒 26569.8145 兆字节/秒 (!) 即 26 GB/秒
- 2028000 块 51200 字节:4.0538 秒 24427.4096 兆字节/秒
- 413878 块 250880 字节:3.9936 秒 24795.5548 兆字节/秒
- 19805 块 5242880 字节:4.5892 秒 21577.7860 兆字节/秒
请注意,使用 XMM0 寄存器的缺点是它是 128 位(16 字节),而我可以使用 256 位(32 字节)的 YMM0 寄存器。无论如何,stosb 使用非 RFO 协议。自 1996 年的 Pentium Pro (P6) 以来,Intel x86 就拥有“快速字符串”。P6 快速字符串采用 REP MOVSB 或更大,并使用 64 位微码加载和存储以及非 RFO 缓存协议来实现它们。与 Ivy Bridge 中的 ERMSB 不同,它们没有违反内存排序。有关详细信息和来源,请参阅https://stackoverflow.com/a/33905887/6910868。
无论如何,即使您只比较我提供的两种方法,即使第二种方法远非理想,如您所见,在 64 位块上rep stosb 速度较慢,但从 128 字节开始块,rep stosb 开始优于其他方法,并且从 512 字节块和更长的块开始,差异非常显着,前提是您在缓存中一次又一次地清除相同的内存块。
因此,对于REP STOSB,最大速度为每秒 103957(十万三千九百五十七)兆字节,而使用 MOVDQA [RCX],XMM0 的最大速度仅为 26569(二万六千五百六十六)九)26569。
如您所见,最高性能是在 32K 块上,相当于我进行基准测试的 CPU 的 32K L1 缓存。
冰湖
REP STOSB 与 AVX-512 商店
我还在 2019 年 8 月发布的 Intel 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/秒,以 256 字节对齐的目的地(对齐到 256 字节,即 $7FF4FDCFFF00)。之后,速度并没有提高,即使目标对齐了 32KB(例如 $7FF4FDD00000),仍然是 224850 MB/秒。
rep stosb 和 rep stosq 的速度没有差异。
在以 32K 对齐的缓冲区上,AVX-512 存储的速度与 rep stosb 的速度完全相同,对于从循环中的 2 个存储开始的循环 (227777 MB/秒) 并且对于展开的循环没有增长4 家甚至 16 家商店。但是,对于只有 1 个存储的循环,速度会稍低一些 - 203145 MB/秒。
但是,如果目标缓冲区仅错位 1 个字节,则 AVX512 存储的速度会急剧下降,即 2 倍以上,降至 93811 MB/秒,而在类似缓冲区上的 rep stosb 则为 175231 MB /秒。
缓冲区大小
- 对于 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 stosb 和 rep 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/s,
rep stosb: 220515 MB/s - 现在终于!我们正在接近我的 CPU 的 L0 数据缓存大小 - 48Kb!这是每秒 220 GB!
- 对于 64K (65536) 块,AVX-512 有 61405 MB/s,
rep stosb: 70395 MB/s!
- 当我们用完 L0 缓存时,降幅如此巨大!而且,很明显,从这一点开始,
rep stosb 的表现开始优于 AVX-512 商店。
- 现在让我们检查 L1 缓存大小。对于 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 的两倍!
我还尝试使用非临时指令来填充 32K 缓冲区 vmovntdq [rcx], zmm31,但性能比 vmovdqa64 [rcx], zmm31 慢了大约 4 倍。在填充内存缓冲区时如何利用vmovntdq?是否应该有一些特定大小的缓冲区以便vmovntdq 发挥优势?
此外,如果目标缓冲区至少按 64 位对齐,vmovdqa64 与 vmovdqu64 之间没有性能差异。因此,我确实有一个问题:当我们有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
缓存内多次清空同一内存块的性能总结
Ice Lake CPU 上的rep stosb 开始优于 AVX-512 存储,仅用于重复清除大于 L0 缓存大小的相同内存缓冲区,即 Intel i7 1065G7 CPU 上的 48K。在小内存缓冲区上,AVX-512 存储速度要快得多:1KB - 快 3 倍,512 字节 - 快 5 倍。
但是,AVX-512 存储区容易受到未对齐缓冲区的影响,而rep stosb 对未对齐则不那么敏感。
因此,我发现 rep stosb 开始优于 AVX-512 存储,仅在超过 L0 数据缓存大小或 48KB 的缓冲区上,如 Intel i7 1065G7 CPU。这个结论至少在 Ice Lake CPU 上是有效的。较早的英特尔建议,字符串复制从 2KB 缓冲区开始优于 AVX 复制,也应该针对较新的微架构重新测试。
清空不同的内存缓冲区,每个只用一次
我之前的基准测试是连续多次填充同一个缓冲区。更好的基准可能是分配许多不同的缓冲区,并且每个缓冲区只填充一次,以免干扰缓存。
在这种情况下,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 上填充总计 8 GB 的各种内存块的速度基准测试(以 MB/秒为单位),总内存为 16 GB,单线程。 “AVX”是指“AVX-512”普通商店,“stosb”是指“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 种不同的方法:
-
vmovdqa64 [rcx+imm], zmm31 的普通 AVX-512 存储(循环 4 个存储然后比较计数器);
-
vmovntdq [rcx+imm], zmm31 存储的非临时 AVX-512(4 个存储的相同循环);
-
rep stosb.
对于小缓冲区,普通的 AVX-512 存储是赢家。然后,从 4KB 开始,non-temporal store 领先,而rep stosb 仍然落后。
然后,从 256KB 开始,rep stosb 的性能优于 AVX-512,但不是非临时存储,从那以后,情况没有改变。获胜者是一家非临时性 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 转换惩罚
对于所有的 AVX-512 代码,我使用了ZMM31 寄存器,因为 SSE 寄存器来自 0 到 15,所以 AVX-512 寄存器 16 到 31 没有对应的 SSE,因此没有招致过渡惩罚。