Voodoo and the register keyword
When the C programming language was born, the language was very close to the machine. But both compiler technology and computer architecture have moved on since the invention of C in the early 1970s, and modern optimizing compilers sometimes translate in mysterious ways. Writing high-performance code now can be as much about exposing opportunities for optimization and letting the compiler do its job as it is about micromanaging the details of what the compiler should do. Human beings are better than compilers at seeing high-level aspects of an algorithm that might lead to better or worse performance; and compilers are typically much better at low-level tasks like scheduling instructions and allocating registers.
Though compilers are now typically better than humans at register allocation,
the C programming language retains the register
keyword, which is supposed to
be a hint to the compiler that it is appropriate to put a certain variable in a
register. Compilers are not required to take this hint; the only mandatory
effect of declaring a variable to be a register
variable is that you are no
longer allowed to take its address. And yet, one of the most popular attempted
optimizations for the matrix multiplication assignment in my high-performance
computing class is to add register
annotations to a bunch of the variables,
even though I tell the students that it will probably have no real impact.
Why is this so?
I think the allure of register
, along with the allure of more grotty C tricks
like Duff’s device, is that it
seems almost like a magical incantation. Wouldn’t it be nice if there was a
formula that some wizardly programmer could chant over code in order to make it
go fast? Of course, if there really is a formula, compiler writers now will
incorporate it into the optimizer. This may not be good for the mystique of
code tuning, but it certainly makes good engineering sense. After all, the
magic of the computer is that it can automate things for which you can find
a formula!
What is interesting about these tricks is not that they represent a sort of lore on how to optimize things now, but rather they are historical artifacts that show something about the joint evolution of machine architectures, compilers, and programming wisdom. They aren’t magical in any real sense, but they surely are worth enjoying as evidence that programmers in the past were just as clever as we fancy ourselves to be today.
Comments
blog comments powered by Disqus