Rozbalování smyček
Následující výraz
for (i = 0; i < n; i++) { data[i] = a[i]; }
lze zaměnit za
for (i = 0; i < n; i += k) { data[i] = a[i]; data[i+1] = a[i+1]; data[i+2] = a[i+2]; ... data[i+k-1] = a[i+k-1]; }
a tak umožnit lepší využití pipeline procesoru.
Specializace šablon
Zde vidíme použití specializace na výpočet fibonacciho čísla v době překladu. Prvně je definována obecná šablona, která obsahuje rekurzivní vzorec a následně jsou definovány specializace pro počáteční podmínky. Všechny propočty jsou realizovány v době kompilace a ve výsledném programu už najdeme jen číslo, které se vypisuje.
template<int N> struct fib { static const int result = fib<N-1>::result + fib<N-2>::result; }; template<> struct fib<0> { static const int result = 0; }; template<> struct fib<1> { static const int result = 1; };
#include <iostream> int main(int ac, char *av[]) { std::cout << "Fib(10) = " << fib<10>::result << std::endl; return 0; }
Specializace šablon s více parametry
template<arg(0), arg(1), ... arg(n)> class sablona { //defaultní chování }; template<arg(i0), arg(i1), ... arg(im)> class sablona< /* dosazení za parametry obecné šablony */ > { //specializace };
Obecná šablona má n parametrů. Častečná specializace šablony má pro parametry s indexy {1..n} \ (i)1..m určené typy nebo přímo číselné hodnoty. Ostatní nespecifikované parametry šablony (i)1..m je třeba uvést jako parametry specializace za klíčové slovo template. Častečná specializace šablony tedy má méně parametrů než obecná šablona a za názvem třídy se uvádí nespecifikované parametry a hodnoty parametrů, pro kterou šablonu specializujeme.
Šablona pro rozbalení smyčky
Tato šablona má dva parametry: počet řádek, které je potřeba rozbalit a výraz, na kterém se provádí. Rekurzivně se volá tak dlouho, až dojde k rozbalení posledního výrazu. Celý cyklus je ukončen specializací šablony.
template <int loops, class A> class loop_unroll { public: static const int n = loops; inline static void do_loops(double data[], const A &a, int i) { //tato řádka se rozbalí data[i] = a[i]; //využití šablony o 1 menší loop_unroll<n-1, A>::do_loops(data, a, i+1); } }; /* specializace šablony pro 0 opakování */ template <class A> class loop_unroll<0, A> { public: inline static void do_loops(double data[], const A a, int i) {} }; //--------------------------použití------------------------------------------- template <class A> void operator = (const Expr<A>& a_) { const A& a(a_); int i; #ifdef unroll_loops for (i = 0; i<n; i += unroll) { // rozbalení smyčky na "unroll" výrazů za sebou loop_unroll<unroll, A>::do_loops(data, a, i); } // prochazíme zbytek výrazu for (;i<n; i++) { data[i] = a[i]; } #else for (i=0;i<n; i++) { data[i] = a[i]; } #endif }
Rozbalování smyček v gcc
Rozbalení smyček lze dosáhnout i pomocí přepínače gcc -funroll-loops. Což samozřejmě vede ke zvětšení spustitelného souboru a tím pádem větší spotřebě paměti, ale umožní zredukovat vyhodnocení podmínky smyčky, a tak lépe využít pipeline.