2013-03-07 3 views
10

Gibt es eine Möglichkeit zu sagen, Clang eine bestimmte Schleife ausrollen?clang: Force loop für spezifische Schleife ausrollen

Googeln für eine Antwort gibt mir Befehlszeilenoptionen, die die gesamte Kompilente und nicht eine einzige Schleife betreffen wird.


Es gibt eine ähnliche Frage für GCC --- Tell gcc to specifically unroll a loop --- aber die Antwort vorausgesetzt, es nicht mit Klirren funktioniert.

Option 1 vorgeschlagen dort:

#pragma GCC optimize ("unroll-loops") 

scheint stillschweigend ignoriert zu werden. Tatsächlich

#pragma GCC akjhdfkjahsdkjfhskdfhd 

wird auch still ignoriert.

Option 2:

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

führt zu einer Warnung:

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

aktualisieren

joshuanapoli bietet eine schöne Lösung, wie über Metaprogrammierung und C iterieren + +11 ohne eine Schleife zu erstellen. Das Konstrukt wird zur Kompilierungszeit aufgelöst, was zu einem wiederholt inlinierten Körper führt. Es ist zwar nicht genau eine Antwort auf die Frage, aber im Wesentlichen wird dasselbe erreicht.

Deshalb akzeptiere ich die Antwort. Wenn Sie jedoch wissen, wie Sie eine Standard-C-Schleife verwenden (for, while) und erzwingen Sie es ausrollen - bitte teilen Sie das Wissen mit uns!

+1

Normalerweise hat der Compiler eine sehr gute Vorstellung davon, wann es geeignet ist, eine Schleife aufzurollen, und wenn es keine gute Idee ist.Was ist der Spezialfall, den Sie zu lösen versuchen, wo dies nicht zutrifft? –

+0

Es kann nicht * zwingen * entrolling, aber '__attribute__ ((heiß))' könnte einen Versuch wert sein. –

+1

@MatsPetersson Ich möchte explizit den Vorteil der Schleife Abrollung zu messen. Handgeschriebenes Unroll beschleunigt den Code 3 Mal, aber der Compiler erkennt es nicht. – CygnusX1

Antwort

8

Für ein C++ - Programm können Sie Loops innerhalb der Sprache abwickeln. Sie müssen keine Compiler-spezifischen Optionen herausfinden. Zum Beispiel

#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; 
} 

Beispiel mit komplizierten Loop-Funktion

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) 

Mit einem Verschluss statt eine explizite Funktion Objekt

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

Ja, das ist meine Standardmethode. Aber da ich bereits in einer Vorlage mit Parametern bin, die in die 'loop_function' kommen müssen, wird es wirklich hässlich ... deshalb suche ich nach einer etwas" ansprechenderen "Lösung :) – CygnusX1

+0

Wenn du C + benutzen kannst +11, dann können Sie mit constexpr-Funktionen das Rauschen der Vorlagensyntax reduzieren. – joshuanapoli

+0

Nicht, wenn nur einige Parameter conexpr/template sind und einige sind dynamische Parameter ... oder? – CygnusX1