CodeBoost is part of the Sophus[1] project, which explores the use of high-level abstractions for numerical applications. This has great advantages in terms of easier programming and maintenance, but poor performance has hindered the adoption of these techniques in HPC. Current compilers have proven unable to optimise sufficiently, partly due to low demand for such optimisations, and partly because some of the most effective optimisations are in conflict with the C++ standard. For CodeBoost, three optimisations are on the way, and more are planned for the future.
The first optimisation is motivated by the use of operator overloading in C++, which greatly improve the readability of complex expressions involving user defined types. For instance, we can write A = A + B * c, instead of something like mul(B, c, t); add(A, t, A); (possibly with the function bodies hand-inlined). Unfortunately, this programmer-friendly style is bad for performance; the result must be copied, and each operator call involves the creation of a new temporary. This might be fine with only a few bytes of data, but unacceptable when working with many megabytes. If the optimiser knows that A += B means the same as A = A + B, it can rewrite the expression to use only one temporary, and eliminate copying of the result. This is what the C++ compiler does for built-in types, but it can't do it for user-defined types, because the standard forbids assuming any relation between + and +=. If we demand that this relation holds, or allow the user to specify it for each case, we can perform the optimisation.
But even if we do this optimisation, we are left with another performance problem; the operators are typically defined in terms of loops, thus the computation is done in several passes over the data. This causes unnecessary cache misses and index computations. A smart optimiser can inline the operators, and use loop fusion to fold consecutive loops into a single loop. Your compiler might actually do loop fusion in some cases, but most likely it won't look for this case, and miss the opportunity.
Inlining a function eliminates the function-call overhead, and allows for further optimisations--such as loop fusion. C++ provides the inline keyword as a hint to the compiler that a function can be inlined, but this is merely a hint; the compiler is free to ignore it. Depending on the compiler, seemingly easy-to-inline code may run a lot slower than hand-inlined code. With proper inlining, we can use functions actively, and get better readability, maintainability and flexibility.
The CodeBoost framework is limited to processing a simplified version of the C++ language. Many irrelevant features, such as namespaces, pointers to functions, and inheritance, have been ignored to keep the implementation concise and managable. New features are added as the need arises. The restrictions are motivated not only by implementation concerns, but also by good coding practice and assumptions made by the CodeBoost optimiser.
The implementation is based on standard compiler design, with clearly seprarate parts for each step in the process. A modified version of OpenCpp is used for parsing, everything else is written in Stratego. Stratego is a language for specifying program transformations; the transformations are described by a combination of concise rewrite rules, and strategies allowing precise application of the rules based on context.
Intermediate output from CodeBoost is in the ATerm format, and is primarily useful for Stratego programs, but is also accessible from C, C++ and Java, and is easily parsable. The final output is readable C++ code.
See also