iMalc

Members
  • Content count

    4264
  • Joined

  • Last visited

Community Reputation

2466 Excellent

About iMalc

  • Rank
    Contributor
  1. Sounds like you don't realise that constexpr methods are evaluated at compile time and as such have no run-time penalty whatsoever. And if that's not enough, the int template argument is also determined at compile time. Identical assembly is generated to the code with macros, but without the headache macros bring.   When people writing firmware do this sort of thing it's actually typically because they're stuck using an ancient compiler written at a time when templates were either unheard of, or were still in their infancy.
  2. Confusion with smart pointers

      That's exactly when std::move should be used.   Well sure, if the function signature takes a unique_ptr directly as one of the arguments. Kinda forgot that obvious case as I've almost never been in that situation. I deal mostly with code where the interface in the middle is a C interface, e.g COM, and that sort of thing.
  3. Confusion with smart pointers

    As you are no doubt aware, in C++ it is preferable to avoid new and delete in your program. Modern C++ provides some nicer ways to achieve this with unique_ptr:   Instead of this: std::unique_ptr<Random> SP(new Random()); Use this:   auto SP = std::make_unique<Random>(); I've almost never called std::move on a unique_ptr myself; that should be mostly called by container classes e.g. vector in a normal program, and I you wouldn't often be writing a container. In a normal program if you have to transfer ownership between unique_ptrs, you'll often find yourself doing so by detaching from one unique_ptr, and attaching to another, most likely across a function call boundary.
  4. Or the better option would be for this doit function to be a member function instead, and the mutex is a member variable. That way the caller can't pass in the wrong mutex.
  5. Possible ideas that haven't been mentioned yet: Consider switching Arrays of structures to structures of arrays. Consider adding prefetch inline assembly language instructions or intrinsics. You may be able to calculate partial sums of the values in the dist array, keeping track elsewhere which portions of the array have been touched, or heaven forbid you update the sum upon every change to an item in the dist array if it changes rarely. Okay I'm starting to get in the territory of wild asz guesses now. Context is key. The more context we have, the more optimisations we can apply. There are plenty of things I could suggest, but they would only work under specific conditions which you have not specified. The less info you provide, the more you lose out. You're making this challenge like doing keyhole surgery blindfolded. But here's the kicker... you can't know what we will need to know in order to pick the best ideas. Really, your only option is to be as open as possible and provide as much contextual information as you can.   Believe me I've done plenty of micro-optimisation. If you've heard of John Carmack's famous parallel divide where you get the floating point perspective divide essentially for free as it is done in parallel with integer instructions... well I've managed to achieve exactly that directly in carefully crafted C++ code, without having to resort to inline asm, but I digress.   I've also seen the problem of summing up all values in an array being parallelised in such as way as to actually gain performance by summing up into more than one variable at once, then summing those at the end. I think this was somewhat compiler specific. This should jog someone else's memory to fill in the details for you.
  6. Always will be. Any time you may be removing more than one item, it's probably the better option.
  7. This has been solved by others previously. Here's a thread I had bookmarked about it, with a nice solution: http://www.gamedev.net/topic/261920-a-slick-trick-in-c/
  8. C++ | Fixed Byte Size

    It's only really wrong if you're trying to write 100% portable code that will work everywhere.   Lots of engines write data structures that exactly map to their own custom file formats (with manual padding/alignment), as it allows you to completely skip the "deserialization" step after streaming data from disk. You can just stream complex data structures into RAM and start using them immediately. Yep, this line of discussion is completely off-topic from implementing a ZIP file decoder though! If you do ever need to do make manually-aligned structures, almost all compilers will accept the pack pragma: #pragma pack(push) #pragma pack(1) // one-byte alignment - AKA no padding struct MyUnalignedFudgetry {  ... }; #pragma pack(pop) So in your non-portable, platform-specific data-structure code, you should include the line static_assert( sizeof(uint16_t) == 2 );   Just thought I'd add that although you can generally use pragma pack 1, if the architecture you are using does not allow misaligned reads, (e.g. the ARM we use at work gives a bus error) then it won't behave as desired. I'm not sure what the exact behaviour would be, but I expect it would either cause a bus error when attempting to access the misaligned structures, ignore the request to not add padding, or refuse to compile the code.
  9. I use a branchless table-driven implementation by Jeroen van der Zijp (http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf) which some time ago I wrapped into a class to make it as convenient as a regular float.   The conversions in both directions are two-liners, and the combined size of all of the lookup tables is less than 10K. http://homepages.vodafone.co.nz/~tawa47a/Malc/Useful_Classes.htm It's probably nearly functionally identical to Aressera's   Edit: Bah, Jeroen van der Zijp's original link is now not working for me.   Edit2: Christian Rau has since produced an even more complete version here, which is clearly also based on Jeroen's work, but is more complete than mine, with template meta-programming to avoid unnecessary conversions and such: http://half.sourceforge.net/ Probably best just to use that one.
  10. It might be the case that the world is procedurally generated on demand.   In order to use A* you need to have a starting position and a goal position, and A* will give you the path from start -> finish. So if you have those bits of information and simply want to run the A* algorithm every time the exposed part of the world changes, which might be every frame, then that's do-able in general.   However, if as-it sounds your player is constrained such that they can only move horizontally, whilst the world moves vertically, then you have a bit of a snag because you are limited to moving in the following effective directions: up, diagonally up & left, and diagonally up & right. If the resulting path from A* contains portions which require travelling in other directions, then your player will be unable to follow the path.   It's at this point that I feel you will need to provide a more detailed description of the problem before we can give the right bit of advice. It might be that what you want is something very different, more along the lines of the minimax algorithm, whereby at any point in time you just want to work out which direction (left, right, or neither) is the most ... erm *productive*.
  11. Unused param

    Unless I'm in the situation where the parameter is used in only debug or only release build, I tend to just comment out the parameter name.   I've also seen people just mention the variable name in the function body on a line by itself, without any cast.
  12. My take is that generally in the best case you're only going to be able to completely stop someone who is only as good a hacker as yourself.   But ... yes with the right outside help you can do better.   Still, there's always going to be someone out there with better hacking skills that whoever you learn from. From them, your best defence is to make the reward not worth the effort. Sadly, that is not easy.
  13. Getting Rid of "char*"

    Actually, let's not pretend it's an issue, that's exactly what causes premature optimisation. Here is the procedure to "solve it".   First prove it is an issue, via profiling. You've either done that and not posted results, or you haven't done that. Either way there is more work required at this step.   After that, your first attempt at a resolution should be to see how you can use strings less. E.g. if profiling showed that you had a bottleneck when comparing your string object IDs, then perhaps you could switch to using enumerations instead of strings. Or, if you're getting too many string copies, perhaps there are some critical places where the string is passed by value instead of const-reference.   The next thing to do is to look for a replacement that already exists. That may be in the form of a more-specialised part of the same library, or a whole other library. There is plenty that you can research.   Next, in considering whether to write your own replacement, you need to understand that in proceeding down the path of making your own, you are assuming that you can do a better job than the expert standard library writers. You are then assuming that you are in the top few percent of all C++ coders. Most people like to think that they are in the top few percent of C++ coders, but obviously most aren't. The experts are those who have first learnt to use existing tools very effectively (e.g. strings). One must learn why all the parts of the string class work as they do, in order to not fall into traps that others have already solved.   The final thing to understand is that even when there is a bottleneck, and even when you've done your best to optimise all related code as much as you can, there is always going to be a bottleneck somewhere. It's even possible that no matter what changes you make to a program, string handling could be such an unavoidable bottleneck (although that is generally unlikely, depending on what the program does).
  14. I should note that there is sometimes a bit of a misconception about premature optimisation. Avoiding premature optimisation doesn't mean that you ALWAYS just start with the simplest thing that could possibly work. For example, say you are starting out writing what is planned to be a very good chess AI. You do your research and discover that other people have already studied this area and determined that the only way to get things fast enough is to use bit-boards. Starting out using bit-boards, which is more complex that a straightforward solution, is thus not a premature optimisation. It's an informed need for optimisation, and the only known way to get the required performance.   You either profile then optimise, or you research then optimise, or both.
  15. That's just silly. If you use a goto in a place where it makes the code clear (granted, these situations are exceedingly rare), nobody will have a problem with it.   That's just silly. If you use a goto in a place where it makes the code clear (granted, these situations are exceedingly rare), nobody will have a problem with it. I'm not trying to enter into whether it should be the case, but that's simply how it seems to be. People who use gotos either in interviews, or in the workplace to any noticeable degree, are foolish.