7 ms·
I'm wondering how you guys would optimize that code ? My naive approach would be something like this: const int numCountryIndicies = however many there are..;
by dusted 6y ago
I'm wondering how you guys would optimize that code ?
My naive approach would be something like this:
const int numCountryIndicies = however many there are..;
const char* countries = "A1\0A2\0...";
return (cc < numCountryIndicies)?countries[cc*2]:"UNKNOWN";
- rantwasp 6y agoit’s probably a switch on the index (or in this case you could actually have an array and use the index). I don’t know my compilers that well but if I had to guess I would say there is a good chance this will be optimized away by the compiler.
- fallingknife 6y agoDoes a ternary actually eliminate a logic branch? I always assumed it was just high level shorthand, and would be the same in assembly as writing out the if block.
- throwaway744678 6y agoIt does not eliminate the conditional jump, it's just synctatic sugar.
- PixelOfDeath 6y agoUntil after C++11, ternary was the only way to use "if then" in constexpr functions. So it has slightly more use from a C++ point of view.
- gpderetta 6y agoIn a funny turn of events, in C++17 there is no ?: shorthand for 'constexpr if' .
- MaxBarraclough 6y agoFollowing that line, it's never exactly been syntactic sugar. When initializing a const local, you can use the ternary operator on the right hand side of the assignment, but you can't get the same effect using if (short of writing a new function). Similarly, C++ lets you use the ternary operator for the left hand side of an assignment, (a ? b : c) = 42; although you could use an if for this pretty easily.
- andromeduck 6y agoWow I had no idea you could use it on the LHS. TIL.
- MaxBarraclough 6y agoA TIL of my own: it seems not to be allowed in C.
- saagarjha 6y agoIt works if you take the address of the b and c and then dereference. I assume this works without those in C++ because of references.
- TonyTrapp 6y agoAnd to make it more complicated, both "regular" ifs and ternaries may not generate a branch at all, e.g. by using the CMOV (conditional move) instruction on x86. This avoids a branch but can obviously not eliminate the data dependency between the condition and a later consumer of the result.
- messe 6y agoYou have an off-by-one error. The strings are 3 bytes long. I'd write something similar, more or less; Probably the following, not for optimization, but more as a matter of style: const char countries[][3] = { "A1", "A0", // [...] }; // [...] int total_countries = (int) (sizeof(countries) / sizeof(countries[0])); return cc < total_countries ? countries[cc] : "UNKNOWN"; No need to hard code the length, and the cast is guaranteed to be within the bounds of an int on all platforms as long as you don't go over 2^16-1 countries.
- dusted 6y agoWell caught! I have two off by one errors :D seems they start from 1 instead of 0, and I didn't account for the null byte :D your solution is nicer and easier to read :)
- Cerealkiller050 6y agoThis jives with the overall point of the article of keep it simple and readable. The semi fancy indexing caused 2 errors and the upside is negligible after the compiler gets done with it.
- simias 6y agoI think that's the best solution (the only potential optimization I can think of would be to add a padding byte after every country to force 32bit alignment which would make the offset computation faster on some architectures, although probably not on x86). Stylistically-wise I think the best solution would be to write the array like: const char countries[][3] = { [0] = "A1", [1] = "A0", }; This way the codes are explicit when you read the code and it makes editing the array a little easier. Unfortunately gcc only warns if you set the same index twice with -Wextra, it remains silent with -Wall.
- messe 6y ago> This way the codes are explicit when you read the code Good call. It might have caught the off-by-one mistake I made (the codes start from 1 and not 0 in the blog post). Maybe even switch to using an enum as our index instead of an int.
- majke 6y agoModern freshest gcc 11 can optimize the if's nicely https://godbolt.org/z/771foExcG https://godbolt.org/z/771foExcG getCountry: mov eax, OFFSET FLAT:.LC0 cmp edi, 258 ja .L1 mov edi, edi mov rax, QWORD PTR CSWTCH.1[0+rdi*8] .L1: ret
- qayxc 6y agoclang does the same - I tested it back to clang 7.0. So clang did this for a long time it seems.
- Denvercoder9 6y agoAnyone know what the purpose of the mov edi, edi instruction there is? Edited to add: I understand that it's a NOP, but why would the compiler emit one here?
- JoeAltmaier 6y agoIt does nothing, so its a noop of sorts. I wonder if its a branch-delay tactic of some kind? Surely the algorithm is unchanged if it were removed.
- colejohnson66 6y agoIt’s just a two byte NOP. IIRC, it’s Intel’s recommended form for one of that length. Windows uses it for hot patching,[0], but I can’t imagine that’s the reason here. [0]: https://devblogs.microsoft.com/oldnewthing/20110921-00/?p=9583 https://devblogs.microsoft.com/oldnewthing/20110921-00/?p=95...
- Const-me 6y agoThat instruction clears upper 4 bytes of the rdi register. Note the next instruction uses rdi in the address. edi register is the lower 4 bytes of rdi. Instructions which write these smaller pieces zero out the unused higher bytes of the destination registers. This helps with performance because eliminates data dependencies on the old values in these higher bytes.
- 5y ago
- teachingassist 6y agoI immediately wanted to rewrite it as an array, yep, since the countries are already indexed. And to minimize the risk of errors such as the "Anguila" error above.
- lmilcin 6y ago> I'm wondering how you guys would optimize that code ? Run it on infinite multiverse, construct a mechanism to destroy the Universe every time branch predictor did not predict every single conditional correctly.
- dylan604 6y agowon't we need quantum computing for that first?
- lmilcin 6y agoYou don't need that. The branch predictor can select a random branch, so it doesn't even need to actually predict anything. It should use quantum noise so that it has chance of selecting different branches in different copies of the universe. There is noting to compute, quantum or otherwise. The bomb to destroy the universe will take care of all universes where it made wrong predictions, so that is where we should concentrate our development resources. It has more utility than just branch prediction. Imagine the bomb going off automatically whenever there starts a war. Any copy of the universe that starts a war is automatically eliminated and this guarantees that you, as an observer, will never observe any wars.
- Narishma 6y agoIt reaches out it reaches out it reaches out it reaches out— One hundred and thirteen times a second.