2015-08-07 12 views
7

Zum Beispiel, hier ist ein oder Ausdruck:Warum kompilieren Cython Logik oder `` Expression?

c = f1 == 0 or f1 - f0 > th 

Hier ist die kompilierte C-Code:

__pyx_t_24 = (__pyx_v_f1 == 0); 
if (!__pyx_t_24) { 
} else { 
    __pyx_t_23 = __pyx_t_24; 
    goto __pyx_L5_bool_binop_done; 
} 
__pyx_t_24 = ((__pyx_v_f1 - __pyx_v_f0) > __pyx_v_th); 
__pyx_t_23 = __pyx_t_24; 
__pyx_L5_bool_binop_done:; 
__pyx_v_c = __pyx_t_23; 

Warum dies nicht ausgegeben?

__pyx_v_c = (__pyx_v_f1 == 0) || ((__pyx_v_f1 - __pyx_v_f0) > __pyx_v_th) 

ist die goto-version schneller als ||?

+0

Sieht aus wie der 'goto' ist Teil des Kurzschließen' or'. – hpaulj

Antwort

5

unter Verwendung der folgenden zwei Dateien:

test.c:

int main(int argc, char** argv) { 
    int c, f0, f1, th; 
    int hold, hold1; 
    f0 = (int) argv[1]; 
    f1 = (int) argv[2]; 
    th = (int) argv[3]; 
    hold1 = (f0 == 0); 
    if (!hold1) { 

    } else { 
     hold = hold1; 
     goto done; 
    } 
    hold1 = (f1 - f0 > th); 
    hold = hold1; 
    done: c = hold; 
    return c; 
} 

test2.c:

int main(int argc, char** argv) { 
    int c, f0, f1, th; 
    f0 = (int) argv[1]; 
    f1 = (int) argv[2]; 
    th = (int) argv[3]; 
    c = (f1 == 0) || (f1 - f0 > th); 
    return c; 
} 

hatte ich f0, f1 und th etwas zuweisen, damit der Compiler würde nicht nur return 1 wie die C-Spezifikation besagt, dass int s initialisiert zu 0 und f1 == 0 würde true ergeben und damit die ganze boolean Aussage ergäbe true und die Anordnung wäre:

main: 
.LFB0: 
    .cfi_startproc 
.L2: 
    movl $1, %eax 
    ret 
    .cfi_endproc 

Kompilieren GCC mit -S -O2 Fahnen mit (Optimierung aktiviert), die beide test.s und test2.s werden :

main: 
.LFB0: 
    .cfi_startproc 
    movl 8(%rsi), %edx 
    movq 16(%rsi), %rdi 
    movl $1, %eax 
    movq 24(%rsi), %rcx 
    testl %edx, %edx 
    je .L2 
    subl %edx, %edi 
    xorl %eax, %eax 
    cmpl %ecx, %edi 
    setg %al 
.L2: 
    rep 
    ret 
    .cfi_endproc 

So ist es, wenn Sie Optimierungen zu deaktivieren, die mit goto würde etwa 50% mehr Anweisungen haben die resul, in dem, Das wäre das Gleiche.

Der Grund, warum die Ausgabe C Code hässlich ist, ist wegen der Art, wie der Interpreter die Knoten im AST besucht. Wenn ein Knoten or besucht wird, wertet der Interpreter zuerst den ersten Parameter und dann den zweiten aus. Wenn der boolesche Ausdruck viel komplexer wäre, wäre es viel einfacher zu parsen. Stellen Sie sich vor, Sie rufen eine Lambda-Funktion auf, die einen booleschen Wert zurückgibt (ich bin mir nicht sicher, ob Cython dies unterstützt). der Dolmetscher würde die Struktur folgen:

hold = ... evaluate the lambda expression... 
if (hold) { 
    result = hold; 
    goto done; // short circuit 
} 
hold = ... evaluate the second boolean expression... 
done: 
... 

Es wäre eine schwierige Aufgabe bei der Interpretation Phase zu optimieren und somit Cython nicht einmal die Mühe.

2

Wenn mein Verständnis von C richtig ist (und ich C zuletzt vor vielen Jahren benutzt habe, also kann es rostig sein), ist das '||' (OR) -Operator in C gibt nur boolesche Werte zurück (das ist 0 für False oder 1 für True). Wenn das richtig ist, dann geht es nicht darum, ob GOTO schneller oder langsamer ist.

Die || würde andere Ergebnisse geben als der Goto-Code.Dies liegt daran, wie ‚oder‘ in Python funktioniert, lassen Sie sich ein Beispiel nehmen -

c = a or b 

In der obigen Aussage erster a s Wert ausgewertet wird, wenn es ein wahre wie Wert ist dieser Wert von der oder Ausdruck zurückgegeben (nicht wahr oder 1, aber a s Wert), wenn der Wert falsch ist (false wie Werte in Python sind 0, leere Zeichenfolge, leere Listen, False, usw.), dann wird der Wert von b ausgewertet und es wird zurückgegeben. Bitte beachten Sie 'oder' gibt den letzten ausgewerteten Wert zurück und nicht True (1) oder False (0).

Dies ist im Grunde sinnvoll, wenn Sie wie die Standardwerte gesetzt werden sollen -

s = d or 'default value' 
+0

Ja ich denke das ist der Grund, ich vergesse was oder Operator in Python macht. Der Ausgabecode von Cython kann Python-Stil oder Operation ohne Verlangsamung ausführen. – HYRY