2016-06-09 8 views
11

Gibt es eine Möglichkeit für C-Code zu sagen, ob es in einer Architektur kompiliert wird, wo die Multiplikation schnell ist? Gibt es ein Makro __FAST_MULT__ oder etwas, das auf diesen Architekturen definiert ist?Gibt es eine Möglichkeit in C, zur Kompilierzeit zu überprüfen, ob Sie sich in einer Architektur befinden, in der die Multiplikation schnell ist?

Angenommen, Sie implementieren eine Funktion zum Ermitteln der Hamming-Gewichtung einer 64-Bit-Ganzzahl über die Shift-and-Add-Methode *. Es gibt two optimal algorithms for that: man benötigt 17 Rechenoperationen, während die andere nur 12 benötigt, aber eine davon ist eine Multiplikationsoperation. Der zweite Algorithmus ist also 30% schneller, wenn Sie auf Hardware laufen, wo Multiplikation die gleiche Zeit wie Addition benötigt - aber viel, viel langsamer auf einem System, wo die Multiplikation als wiederholte Addition implementiert wird.
Wenn also eine solche Funktion zu schreiben, wäre es sinnvoll sein, um bei der Kompilierung zu überprüfen, ob dies der Fall ist, und wechseln Sie zwischen den beiden Algorithmen entsprechend:

unsigned int popcount_64(uint64_t x) { 
    x -= (x >> 1) & 0x5555555555555555;        // put count of each 2 bits into those 2 bits 
    x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); // put count of each 4 bits into those 4 bits 
    x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;      // put count of each 8 bits into those 8 bits 
#ifdef __FAST_MULT__ 
    return (x * 0x0101010101010101)>>56;       // returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ... 
#else // __FAST_MULT__ 
    x += x >> 8;             // put count of each 16 bits into their lowest 8 bits 
    x += x >> 16;             // put count of each 32 bits into their lowest 8 bits 
    x += x >> 32;             // put count of each 64 bits into their lowest 8 bits 
    return x & 0x7f; 
#endif // __FAST_MULT__ 
} 

Gibt es eine Möglichkeit zu tun Dies?

* Ja, mir sind die __builtin_popcount() Funktionen bekannt; Dies ist nur ein Beispiel.

+0

ich die meisten Pakete glaube, die so etwas tun, entweder Verwendung Konfigurationsflags vor dem Kompilieren oder irgendeine Art von automatisierten Performance-Tests durchführen richtig diese Flags zu setzen. –

+0

Genau deshalb gibt es Compiler-Built-Ins. – Olaf

Antwort

7

Gibt es eine Möglichkeit für C-Code zu sagen, ob es auf einer Architektur kompiliert wird, wo die Multiplikation schnell ist? Gibt es ein Makro __FAST_MULT__ oder etwas, das auf diesen Architekturen definiert ist?

Nein, Standard C bietet keine solche Möglichkeit. Es ist möglich, dass bestimmte Compiler so etwas wie eine Erweiterung bieten, aber ich bin mir dessen nicht bewusst.

Dies kann während der Buildkonfiguration getestet werden, zum Beispiel über Autoconf oder CMake. In diesem Fall können Sie das Symbol gegebenenfalls selbst angeben.

Alternativ bieten einige C-Compiler definitiv Makros, die die Architektur angeben, für die der Code kompiliert wird. Sie können dies in Verbindung mit der Kenntnis der Details verschiedener Maschinenarchitekturen verwenden, um zwischen den beiden Algorithmen zu wählen - dafür sind solche Makros bestimmt.

Oder Sie können sich darauf verlassen, dass die Person, die das Programm erstellt, eine Konfigurationsoption auswählt, indem sie ein Makro oder was auch immer definiert.

+2

+1 für Autoconf/Cmake - das ist normalerweise die beste Wahl, wenn Sie wirklich das letzte bisschen Leistung aus Ihrer App herauspressen möchten - dynamische, vollautomatische Kompilierung beim ersten Start, über vorkompilierte Helfer-Binärdateien. .. diese müssen nicht "schnell" sein, sie müssen nur einen Build auslösen :-) – specializt

2

Ich glaube nicht, dass es ein vordefiniertes Makro gibt, das speziell die schnelle Multiplikationsfunktion adressiert.

Es gibt jedoch viele predefined compiler macros for different architectures so , wenn Sie wissen schon im Voraus welche Architekturen oder CPUs die schnelle Multiplikationsbefehl unterstützen, können Sie diese Makros verwenden Sie Ihre eigenen anwendungsspezifischen ein definieren, die eine schnelle Multiplikation bedeutet .

Z. B .:

#if (defined __GNUC__ && defined __arm__ && defined __ARM_ARCH_'7'__) || 
    (defined __CC_ARM && (__TARGET_ARCH_ARM == 7)) 
#define FAST_MULT 
#endif