| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
Could you add some clarity? This PR : The bottleneck is probably: latency from the random lookups and the thruput of the shuffle port. The CPU can have 20+ loads "in-flight" at once. The total loads issued per cycle is not that interesting for unrolling (we always have the same number of loads). It is mostly for scheduling instructions at the assembly level, and to ballpark whether we're IO bound (e.g. do we want to replace a lookup with a calculation, are we spilling and reloading register, etc.). |
Sorry, something went wrong.
|
Tables contain results for sse_convert_latin1_to_utf8 only. But somehow 7761599 commit causes sse_convert_latin1_to_utf8 regression. |
Sorry, something went wrong.
according to uops from Nehalem to Ivy Bridge there are 2 ports for shuffle. But _mm_load_si128 is a bottleneck too. A smaller one. It's latency is 6. My original thought was that it actually might not be pipelined automatically. In this case, 2 sequential calls of it would give 32 bytes instead of 16 for the same latency.
but x86-64 has only 16 sse registers, how could it be 20+? PS: I'm actually new to all these simd stuff so excuse me if I say something stupid) |
Sorry, something went wrong.
These are named registers, but we have many more registers. You can examine the issue experimentally... |
Sorry, something went wrong.
|
A Nehalem would not have a problem with the shuffles. However, a Haswell or Skylake might. On what CPU are you performing the benchmark? The terms would be register renaming and out-of-order execution, I guess. uops.info Code Analyzer is probably a good place to start, if we want to micro-optimize this. |
Sorry, something went wrong.
|
@aqrit A fun one is this PR: #318 The westmere kernel (which is currently just scalar code, but subject to autovectorization) is faster than a reasonable hand-coded AVX2 routine. It is still fine because the differences are small... but it is clear that we could micro-optimize better. |
Sorry, something went wrong.
|
I think I get it roughly. But I struggle to draw parallels with actual code in general. But fortunately, for this PR I'm not into tuning this exact implementation but rather introducing the msvc issue and whether it's present in other compilers as well as unrolling effect with different compilers. I additionally checked clang and icx, both doesn't have this issue at least for this pr. But the results also showed that unrolling is not necessarily consistent between compilers for the same os. clang showed performance degradation for windows and ubuntu, unlike the rest. So, if we use unrolling, we have to choose how to handle such situations. Tomorrow I'll try to found out whether building separately helps with msvc. |
Sorry, something went wrong.
|
It doesn't. But I found that clang can actually benefit from unrolling. Just don't use inlined functions in loop body. For some reason they drop performance a lot. UPD: I replaced inlined functions with macros. Now everything looks much better. Unroll factors are likely not the most optimal, there were some better ones during development. I'm gonna write a script to brute force them. |
Sorry, something went wrong.
replace inline functions in loop body to macros might also help with msvc
If we're willing to do 4 lookups per 16 bytes of input, then we'd only use 2 cache lines for tables. Note: I haven't actually studied the utf16->utf8 function so I don't what that is doing... |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Recently I've learned that all Intel processors since Sandy Bridge can do two _mm_loadu_si128 at the same time with port 2 and 3. So I tried 2 sequential _mm_loadu_si128 and it was a success. Then I also tried 4 and 8. 4 gave me an additional boost, but not 8.
inlined version ======================================================================Alas, when I pulled upstream commits, I got a significant performance penalty for the esperanto file with msvc. So I dropped them and started adding one by one. And I found which one causes it.
7761599 SSE UTF16 => latin1 (#311)
It seems there's nothing special here. It just added a new dependency with 2 other sse implementations.
So I also checked with gcc and there was no penalty.
Could it be a msvc bug?
"the commit" is 7761599,
current branch is sse_convert_latin1_to_utf8_perf
command benchmark -P convert_latin1_to_utf8+westmere -F *.latin1.txt
arch: Sandy Bridge
======================================================================
windows 10
msvc VS 17.5.5
msvc VS 17.7.4
LLVM(clang-cl) 16.0.5
Intel(R) oneAPI DPC++/C++ Compiler 2023.2.0 (2023.2.0.20230627)
mingw-w64-ucrt-x86_64-gcc 13.1.0-7
build error.
======================================================================
wsl2 ubuntu 22.04
gcc 11.4.0
clang 14.0.0-1ubuntu1.1
Intel(R) oneAPI DPC++/C++ Compiler 2023.2.0 (2023.2.0.20230721)
The situation got even funnier when I removed all the loops except this one, and got the opposite result. And it's quite consistent between benchmarks.
msvc VS 17.5.5
"the commit" is 7761599,
current branch is sse_convert_latin1_to_utf8_perf
command benchmark -P convert_latin1_to_utf8+westmere -F *.latin1.txt
arch: Sandy Bridge
======================================================================
windows 10
msvc VS 17.7.4
LLVM(clang-cl) 16.0.5
Intel(R) oneAPI DPC++/C++ Compiler 2023.2.0 (2023.2.0.20230627)
mingw-w64-ucrt-x86_64-gcc 13.1.0-7
build error.
======================================================================
wsl2 ubuntu 22.04
gcc 11.4.0
clang 14.0.0-1ubuntu1.1
Intel(R) oneAPI DPC++/C++ Compiler 2023.2.0 (2023.2.0.20230721)
I'm going to continue the investigation in a couple of days.
plan:
*I suspect that building it as a shared lib might help as it would prevent access of msvc to the rest of the code.
Supposedly, that wouldn't allow it to perform some smart optimisations and thus results should be more stable.
For now, I suggest considering unrolling as unstable.