| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
|
Intriguing. |
Sorry, something went wrong.
|
@Nick-Nuon It is important to realize that if we are consuming latin 1 at 15 GB/s, we are also producing UTF-16 at 30 GB/s. I think that results are likely to differ from run to run because these functions are very bound to loads or stores, and it is an instance with things like memory alignment may matter a lot. Annoying, the SSE kernel is faster than your hand-crafted AVX kernel, and the SSE kernel is still using scalar code. But the scalar code is automatically vectorized to something 'like' what we are doing. It is an instance where having wider registers does not help much. $ ./build/benchmarks/benchmark -P convert_latin1_to_utf16 -F u nicode_lipsum/wikipedia_mars/french.latin1.txt -I 30000 We define the number of bytes to be the number of *input* bytes. We define a 'char' to be a code point (between 1 and 4 bytes). =========================== Using ICU version 67.1 testcases: 1 input detected as unknown current system detected as icelake =========================== convert_latin1_to_utf16+haswell, input size: 432305, iterations: 30000, dataset: unicode_lipsum/wikipedia_mars/french.latin1.txt 0.282 ins/byte, 0.209 cycle/byte, 15.297 GB/s (3.6 %), 3.202 GHz, 1.347 ins/cycle 0.282 ins/char, 0.209 cycle/char, 15.297 Gc/s (3.6 %) 1.00 byte/char convert_latin1_to_utf16+icelake, input size: 432305, iterations: 30000, dataset: unicode_lipsum/wikipedia_mars/french.latin1.txt 0.157 ins/byte, 0.197 cycle/byte, 15.748 GB/s (2.5 %), 3.101 GHz, 0.796 ins/cycle 0.157 ins/char, 0.197 cycle/char, 15.748 Gc/s (2.5 %) 1.00 byte/char convert_latin1_to_utf16+iconv, input size: 432305, iterations: 30000, dataset: unicode_lipsum/wikipedia_mars/french.latin1.txt 31.022 ins/byte, 7.012 cycle/byte, 0.455 GB/s (0.3 %), 3.193 GHz, 4.424 ins/cycle 31.022 ins/char, 7.012 cycle/char, 0.455 Gc/s (0.3 %) 1.00 byte/char convert_latin1_to_utf16+icu, input size: 432305, iterations: 30000, dataset: unicode_lipsum/wikipedia_mars/french.latin1.txt 2.505 ins/byte, 0.640 cycle/byte, 4.992 GB/s (0.8 %), 3.196 GHz, 3.914 ins/cycle 2.505 ins/char, 0.640 cycle/char, 4.992 Gc/s (0.8 %) 1.00 byte/char convert_latin1_to_utf16+westmere, input size: 432305, iterations: 30000, dataset: unicode_lipsum/wikipedia_mars/french.latin1.txt 0.563 ins/byte, 0.193 cycle/byte, 16.590 GB/s (2.3 %), 3.201 GHz, 2.918 ins/cycle 0.563 ins/char, 0.193 cycle/char, 16.590 Gc/s (2.3 %) 1.00 byte/char Overall, I think your PR looks fine. |
Sorry, something went wrong.
| // Zero extend each set of 8 Latin1 characters to 16 16-bit integers | ||
| __m256i out = _mm256_cvtepu8_epi16(in); | ||
| if (big_endian) { | ||
| out = _mm256_shuffle_epi8(out, byteflip); |
There was a problem hiding this comment.
Should this be a shift instead of a shuffle ?
Sorry, something went wrong.
There was a problem hiding this comment.
A shift might be faster but note that the benchmark results above are for the case where big_endian is false. That is, this 'compile time branch' is not taken in the code that we care about (because big endian is uncommon).
Sorry, something went wrong.
Not sure how much more time I should spend on it, but so I checked what godbolt had to say about it : https://godbolt.org/z/ba9rfqGoe LHS is AVX2, RHS is scalar. This is the uica output for the avx2 function: This is the uica output for the scalar I know that the second output is not using all instructions all the time so that 60 cycle per iteration figure is off but, at a glance, it still seems a lot more instructions than my function. Guess we can't judge a book (or a function) by its cover so gonna take a bit more look at it. |
Sorry, something went wrong.
convert_latin1_to_utf16+haswell, input size: 432305, iterations: 30000, dataset: /home/leorio/unicode_lipsum/wikipedia_mars/french.latin1.txt 0.563 ins/byte, 0.182 cycle/byte, 17.608 GB/s (2.3 %), 3.203 GHz, 3.096 ins/cycle 0.563 ins/char, 0.182 cycle/char, 17.608 Gc/s (2.3 %) 1.00 byte/char convert_latin1_to_utf16+icelake, input size: 432305, iterations: 30000, dataset: /home/leorio/unicode_lipsum/wikipedia_mars/french.latin1.txt 0.157 ins/byte, 0.216 cycle/byte, 14.347 GB/s (2.1 %), 3.100 GHz, 0.726 ins/cycle 0.157 ins/char, 0.216 cycle/char, 14.347 Gc/s (2.1 %) 1.00 byte/char convert_latin1_to_utf16+iconv, input size: 432305, iterations: 30000, dataset: /home/leorio/unicode_lipsum/wikipedia_mars/french.latin1.txt 31.022 ins/byte, 7.011 cycle/byte, 0.455 GB/s (0.3 %), 3.193 GHz, 4.424 ins/cycle 31.022 ins/char, 7.011 cycle/char, 0.455 Gc/s (0.3 %) 1.00 byte/char convert_latin1_to_utf16+icu, input size: 432305, iterations: 30000, dataset: /home/leorio/unicode_lipsum/wikipedia_mars/french.latin1.txt 2.505 ins/byte, 0.640 cycle/byte, 4.993 GB/s (0.8 %), 3.195 GHz, 3.915 ins/cycle 2.505 ins/char, 0.640 cycle/char, 4.993 Gc/s (0.8 %) 1.00 byte/char convert_latin1_to_utf16+westmere, input size: 432305, iterations: 30000, dataset: /home/leorio/unicode_lipsum/wikipedia_mars/french.latin1.txt 0.563 ins/byte, 0.182 cycle/byte, 17.567 GB/s (2.6 %), 3.202 GHz, 3.090 ins/cycle 0.563 ins/char, 0.182 cycle/char, 17.567 Gc/s (2.6 %) 1.00 byte/char I just wanted to reach par and that did it. It doesn't use AVX2 instructions in the C++ code but gcc uses AVX2 instructions in the underlying assembly. Not sure if I spent too much time on it so I will move on to another ticket for now. |
Sorry, something went wrong.
Very sensible. If you think that this is ready, just mark it as 'ready for review'. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
These are my benchmark on big1 and gcc 11.3.1: