Im Linux-Kernel-Code vorbei gibt es ein Makro zu Test-Bit verwendet (Linux Version 2.6.2): Differenz zwischen der Performance-Funktion, wenn Parameter wie der Kompilierung konstante oder variable
#define test_bit(nr, addr) \
(__builtin_constant_p((nr)) \
? constant_test_bit((nr), (addr)) \
: variable_test_bit((nr), (addr)))
wo constant_test_bit
und variable_test_bit
definiert wie:
static inline int constant_test_bit(int nr, const volatile unsigned long *addr )
{
return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
}
static __inline__ int variable_test_bit(int nr, const volatile unsigned long *addr)
{
int oldbit;
__asm__ __volatile__(
"btl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit)
:"m" (ADDR),"Ir" (nr));
return oldbit;
}
ich verstehe, dass __builtin_constant_p
, ob eine Variable kompilieren Zeitkonstante oder unbekannt ist zu erkennen, verwendet wird. Meine Frage ist: Gibt es einen Leistungsunterschied zwischen diesen beiden Funktionen, wenn das Argument eine Kompilierzeitkonstante ist oder nicht? Warum sollte man die C-Version verwenden und die Assembly-Version verwenden, wenn dies nicht der Fall ist?
UPDATE: Die folgende Hauptfunktion verwendet wird, um die Leistung zu testen:
konstant, Call constant_test_bit:
int main(void) {
unsigned long i, j = 21;
unsigned long cnt = 0;
srand(111)
//j = rand() % 31;
for (i = 1; i < (1 << 30); i++) {
j = (j + 1) % 28;
if (constant_test_bit(j, &i))
cnt++;
}
if (__builtin_constant_p(j))
printf("j is a compile time constant\n");
return 0;
}
Dies korrekt gibt den Satz j a ...
Für die anderen Situationen entfernen Sie einfach die Zeile, die eine "zufällige" Nummer zu j
zuweist und den Funktionsnamen entsprechend ändert ly. Wenn diese Zeile unkommentiert ist, ist die Ausgabe leer und dies wird erwartet.
ich gcc test.c -O1
verwenden zu kompilieren, und hier ist das Ergebnis:
konstant, constant_test_bit:
$ time ./a.out
j is compile time constant
real 0m0.454s
user 0m0.450s
sys 0m0.000s
konstant, variable_test_bit (weglassen time ./a.out
, gleiche gilt für die folgenden):
j is compile time constant
real 0m0.885s
user 0m0.883s
sys 0m0.000s
variabel, konstant_test_bit:
real 0m0.485s
user 0m0.477s
sys 0m0.007s
Variable, variable_test_bit:
real 0m3.471s
user 0m3.467s
sys 0m0.000s
Ich habe jede Version mehrmals ausgeführt wird, und die obigen Ergebnisse sind die typischen Werte von ihnen. Es scheint, dass die constant_test_bit
Funktion immer schneller ist als die variable_test_bit
Funktion, egal ob der Parameter eine Kompilierzeitkonstante ist oder nicht ... Für die letzten beiden Ergebnisse (wenn nicht konstant ist) ist die variable Version sogar dramatisch langsamer als die Konstante ein. Fehle ich hier etwas?
Könnte sein, aber der einzige Weg, um herauszufinden, ist zu messen. – deviantfan
Offensichtlich dachte jemand, dass es einen Unterschied in perf macht, oder es würde nicht 2 Versionen geben. Für die Details müssen Sie 4 Fälle berücksichtigen (eine Konstante/nicht konstant an eine der beiden Funktionen übergeben). Was denkst du passiert in jedem Fall? Haben Sie sich die erzeugte Baugruppe angesehen? –
@deviantfan Ich habe die Leistungsergebnisse hinzugefügt. –