Moving to use a single lookup table
This is funny here - on Ryzen, the existing code produce this performance
```
Benchmark (size) (specialCharPercentage) Mode Cnt Score Error Units
MyBenchmark.benchReplaceBackslashRawCompressedTable3 65536 0 thrpt 20 26783.951 ± 66.355 ops/s
MyBenchmark.benchReplaceBackslashRawCompressedTable3:CPI 65536 0 thrpt 2 0.297 clks/insn
MyBenchmark.benchReplaceBackslashRawCompressedTable3:IPC 65536 0 thrpt 2 3.370 insns/clk
MyBenchmark.benchReplaceBackslashRawCompressedTable3:L1-dcache-load-misses 65536 0 thrpt 2 2118.079 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:L1-dcache-loads 65536 0 thrpt 2 263567.211 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:L1-icache-load-misses 65536 0 thrpt 2 0.594 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:L1-icache-loads 65536 0 thrpt 2 268.828 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:branch-misses 65536 0 thrpt 2 34.027 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:branches 65536 0 thrpt 2 82121.699 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:cycles 65536 0 thrpt 2 204572.765 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:dTLB-load-misses 65536 0 thrpt 2 0.073 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:dTLB-loads 65536 0 thrpt 2 4.141 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:iTLB-load-misses 65536 0 thrpt 2 0.256 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:iTLB-loads 65536 0 thrpt 2 0.192 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:instructions 65536 0 thrpt 2 689362.358 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:stalled-cycles-frontend 65536 0 thrpt 2 766.591 #/op
```
which is decent and near to what can be obtained with the existing table approach when there are no special chars - but still is underperforming compared to the whoopy 33K with newish Intel - which seems able to perform 2 lookups in parallel in the same cycle, for each read char.
For comparison - the closed pr at https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/pull/114 with Ryzen, was overperforming the existing approach with Intel - even if not by a great margin i.e. ~28K ops/sec
Moving to a single table lookup with Ryzen (4) the performance is the best we could achieve i.e.
```
Benchmark (size) (specialCharPercentage) Mode Cnt Score Error Units
MyBenchmark.benchReplaceBackslashRawCompressedTable3 65536 0 thrpt 20 38490.297 ± 225.671 ops/s
MyBenchmark.benchReplaceBackslashRawCompressedTable3:CPI 65536 0 thrpt 2 0.186 clks/insn
MyBenchmark.benchReplaceBackslashRawCompressedTable3:IPC 65536 0 thrpt 2 5.369 insns/clk
MyBenchmark.benchReplaceBackslashRawCompressedTable3:L1-dcache-load-misses 65536 0 thrpt 2 2098.366 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:L1-dcache-loads 65536 0 thrpt 2 197925.670 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:L1-icache-load-misses 65536 0 thrpt 2 0.656 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:L1-icache-loads 65536 0 thrpt 2 216.512 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:branch-misses 65536 0 thrpt 2 30.163 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:branches 65536 0 thrpt 2 82099.583 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:cycles 65536 0 thrpt 2 140648.734 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:dTLB-load-misses 65536 0 thrpt 2 0.171 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:dTLB-loads 65536 0 thrpt 2 3.432 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:iTLB-load-misses 65536 0 thrpt 2 0.204 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:iTLB-loads 65536 0 thrpt 2 0.195 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:instructions 65536 0 thrpt 2 755059.926 #/op
MyBenchmark.benchReplaceBackslashRawCompressedTable3:stalled-cycles-frontend 65536 0 thrpt 2 589.245 #/op
```
IPC now is much better and `L1-dcache-loads ` are way less - as expected.
I'll give it a shot on Intel to see how it performs - but I start to think we're moving in a land where the CPU frontend design matter enough to give very different outcome with small changes in code
Just for reference., the assembly produced by this version is not really great - which surprise me that it gives so much better performance...
```assembly
0x00007f7b005d75b0: vmovq %xmm0,%rsi
0x00007f7b005d75b5: vmovd %xmm1,%r8d
0x00007f7b005d75ba: movslq %ecx,%rax
0x00007f7b005d75bd: movzbl 0x10(%rsi,%rax,1),%r9d
0x00007f7b005d75c3: mov 0x10(%rdi,%r9,4),%r9d
0x00007f7b005d75c8: cmp %ebx,%r10d
0x00007f7b005d75cb: jae 0x00007f7b005d76cd
0x00007f7b005d75d1: vmovd %r8d,%xmm1
0x00007f7b005d75d6: vmovq %rsi,%xmm0
0x00007f7b005d75db: mov %r9d,%r8d
0x00007f7b005d75de: sar $0x10,%r8d
0x00007f7b005d75e2: lea (%r8,%r10,1),%r13d
0x00007f7b005d75e6: movslq %r10d,%rsi
0x00007f7b005d75e9: mov %r9w,0x10(%rdx,%rsi,1)
0x00007f7b005d75ef: vmovq %xmm0,%r10
0x00007f7b005d75f4: movzbl 0x11(%r10,%rax,1),%r10d
0x00007f7b005d75fa: mov 0x10(%rdi,%r10,4),%r9d
0x00007f7b005d75ff: cmp %ebx,%r13d
0x00007f7b005d7602: jae 0x00007f7b005d76d5
0x00007f7b005d7608: mov %r9d,%r10d
0x00007f7b005d760b: sar $0x10,%r10d
0x00007f7b005d760f: add %r13d,%r10d
0x00007f7b005d7612: movslq %r8d,%r8
0x00007f7b005d7615: add %rsi,%r8
0x00007f7b005d7618: mov %r9w,0x10(%rdx,%r8,1)
0x00007f7b005d761e: vmovq %xmm0,%r8
0x00007f7b005d7623: movzbl 0x12(%r8,%rax,1),%r9d
0x00007f7b005d7629: mov 0x10(%rdi,%r9,4),%r9d
0x00007f7b005d762e: cmp %ebx,%r10d
0x00007f7b005d7631: jae 0x00007f7b005d76c7
0x00007f7b005d7637: mov %r9d,%r8d
0x00007f7b005d763a: sar $0x10,%r8d
0x00007f7b005d763e: lea (%r8,%r10,1),%r13d
0x00007f7b005d7642: movslq %r10d,%rsi
0x00007f7b005d7645: mov %r9w,0x10(%rdx,%rsi,1)
0x00007f7b005d764b: vmovq %xmm0,%r10
0x00007f7b005d7650: movzbl 0x13(%r10,%rax,1),%r10d
0x00007f7b005d7656: mov 0x10(%rdi,%r10,4),%r9d
0x00007f7b005d765b: cmp %ebx,%r13d
0x00007f7b005d765e: jae 0x00007f7b005d76d2
0x00007f7b005d7660: mov %r9d,%r10d
0x00007f7b005d7663: sar $0x10,%r10d
0x00007f7b005d7667: add %r13d,%r10d ; {no_reloc}
0x00007f7b005d766a: movslq %r8d,%r8
0x00007f7b005d766d: add %rsi,%r8
0x00007f7b005d7670: mov %r9w,0x10(%rdx,%r8,1)
0x00007f7b005d7676: add $0x4,%ecx
0x00007f7b005d7679: cmp %r11d,%ecx
0x00007f7b005d767c: jl 0x00007f7b005d75b0
```
Still an unrolling of 4, but more xmm* spilling, likely due to register pressure
合并状态:未合并 6 条评论