2013-03-07 22 views
10

Czy istnieje sposób na powiedzenie clang, aby rozwinąć określoną pętlę?clang: Rozwijanie pętli siły dla określonej pętli


Wyszukiwanie w Google daje mi dostęp do opcji wiersza poleceń, które będą miały wpływ na całą kompilację, a nie na pojedynczą pętlę.


Jest podobne pytanie dla GCC --- Tell gcc to specifically unroll a loop --- ale odpowiedź pod warunkiem, że nie działa z brzękiem.

Wariant 1 sugerowane tam:

#pragma GCC optimize ("unroll-loops") 

wydaje się być zignorowane. W rzeczywistości

#pragma GCC akjhdfkjahsdkjfhskdfhd 

jest również cicho ignorowana.

Opcja 2:

__attribute__((optimize("unroll-loops"))) 

skutkuje ostrzeżeniem:

warning: unknown attribute 'optimize' ignored [-Wattributes] 

Aktualizacja

joshuanapoli zapewnia miły rozwiązanie jak iteracyjne za pośrednictwem szablonu metaprogramowanie i C + +11 bez tworzenia pętli. Konstrukt zostanie rozwiązany podczas kompilacji, w wyniku czego pojawi się wielokrotnie podkreślona bryła. Chociaż nie jest to dokładnie odpowiedź na to pytanie, zasadniczo osiąga to samo.

Dlatego właśnie akceptuję odpowiedź. Jeśli jednak wiesz, jak używać standardowej pętli C (for, while) i wymusić rozwinięcie - proszę podziel się z nami wiedzą!

+1

Zwykle kompilator ma bardzo dobre pojęcie o tym, kiedy można rozwinąć pętlę i kiedy nie jest to dobry pomysł.Jaki jest specjalny przypadek, który próbujesz rozwiązać, jeśli nie ma to zastosowania? –

+0

Nie może * wymuszać * rozwijania, ale '__attribute__ ((hot)) może być warte wypróbowania. –

+1

@MatsPetersson Chcę wyraźnie zmierzyć korzyść z rozwijania pętli. Napisany ręcznie napis faktycznie przyspiesza kod trzykrotnie, ale kompilator go nie wykrywa. – CygnusX1

Odpowiedz

8

Dla programu C++ można rozwinąć pętle w obrębie języka. Nie będziesz musiał wymyślać opcji specyficznych dla kompilatora. Na przykład,

#include <cstddef> 
#include <iostream> 

template<std::size_t N, typename FunctionType, std::size_t I> 
class repeat_t 
{ 
public: 
    repeat_t(FunctionType function) : function_(function) {} 
    FunctionType operator()() 
    { 
    function_(I); 
    return repeat_t<N,FunctionType,I+1>(function_)(); 
    } 
private: 
    FunctionType function_; 
}; 

template<std::size_t N, typename FunctionType> 
class repeat_t<N,FunctionType,N> 
{ 
public: 
    repeat_t(FunctionType function) : function_(function) {} 
    FunctionType operator()() { return function_; } 
private: 
    FunctionType function_; 
}; 

template<std::size_t N, typename FunctionType> 
repeat_t<N,FunctionType,0> repeat(FunctionType function) 
{ 
    return repeat_t<N,FunctionType,0>(function); 
} 

void loop_function(std::size_t index) 
{ 
    std::cout << index << std::endl; 
} 

int main(int argc, char** argv) 
{ 
    repeat<10>(loop_function)(); 
    return 0; 
} 

Przykład funkcją skomplikowane pętli

template<typename T, T V1> 
struct sum_t 
{ 
    sum_t(T v2) : v2_(v2) {} 
    void operator()(std::size_t) { v2_ += V1; } 
    T result() const { return v2_; } 
private: 
    T v2_; 
}; 

int main(int argc, char* argv[]) 
{ 
    typedef sum_t<int,2> add_two; 
    std::cout << repeat<4>(add_two(3))().result() << std::endl; 
    return 0; 
} 
// output is 11 (3+2+2+2+2) 

Stosując zamknięcie zamiast bezpośredniej funkcji przedmiotu

int main(int argc, char* argv[]) 
{ 
    int accumulator{3}; 
    repeat<4>([&](std::size_t) 
    { 
    accumulator += 2; 
    })(); 
    std::cout << accumulator << std::endl; 
} 
+0

Tak, to jest mój domyślny sposób robienia tego. Ale ponieważ jestem już w szablonie z parametrami, które muszą dostać się do 'loop_function' robi się naprawdę brzydka ... i dlatego szukam jeszcze jednego" przyjemnego dla oka "rozwiązania :) – CygnusX1

+0

Jeśli możesz użyć C + +11, możesz użyć funkcji constexpr, aby zmniejszyć szum składni szablonu. – joshuanapoli

+0

Nie, jeśli tylko niektóre parametry to constexpr/template, a niektóre są zwykłymi parametrami dynamicznymi ... lub? – CygnusX1