Devo pensare al codice macchina compilato quando scrivo il mio codice?

20

Ad esempio, ho il seguente codice:

auto z = [](int x) -> int {
    if (x > 0) {
        switch (x) {
            case 2: return 5;
            case 3: return 6;
            default: return 1;
            }
        }
    return 0;
    };

E più tardi lo chiamo più volte. Nel codice asm vedo le chiamate esterne con lambda .... qualcosa ... Sta diventando non facile da leggere e penso che possa anche causare prestazioni. Quindi, forse vinco nella meta-programmazione, ma perdo il debugging e le prestazioni di asm? Dovrei evitare le funzionalità del linguaggio moderno, le macro e altri aspetti della meta-programmazione per essere sicuro della semplicità delle prestazioni e del debug?

    
posta Cynede 08.07.2013 - 07:12
fonte

3 risposte

59

Must I think about compiled machine code when I write my code?

No , non quando scrivi il tuo codice per la prima volta e non soffri di problemi di prestazioni reali e misurabili. Per la maggior parte dei compiti, questo è il caso standard. Pensare troppo presto all'ottimizzazione si chiama "ottimizzazione prematura", e ci sono buone ragioni per cui D. Knuth ha chiamato questo "la radice di tutti male ".

, quando si misura un collo di bottiglia delle prestazioni reale e dimostrabile e si identifica il costrutto lambda specifico come causa principale. In questo caso, potrebbe essere una buona idea ricordare la "legge delle leaky astrations" di Joel Spolsky e pensare a cosa potrebbe capita al livello ASM. Ma attenzione, potresti rimanere stupito di quanto piccolo sarà l'aumento delle prestazioni quando sostituirai un costrutto lambda con un costrutto linguistico "non così moderno" (almeno, quando usi un compilatore C ++ decente).

    
risposta data 08.07.2013 - 07:58
fonte
8

La scelta tra lambda e functor-class è un compromesso.

Il guadagno di lambda è per lo più sintattico, riducendo al minimo la quantità di piastre e permettendo che il codice concettualmente correlato sia scritto in linea, all'interno della funzione che lo utilizzerà (immediatamente o successivamente).

Per quanto riguarda le prestazioni, questa non è peggio di una classe functor , che è una struct o classe C ++ che contiene un unico "metodo". In effetti, i compilatori trattano Lambda non diversamente da una classe di functor generata dal compilatore dietro la scena.

// define the functor method somewhere
struct some_computer_generated_gibberish_0123456789
{
    int operator() (int x) const
    {
        if (x == 2) return 5;
        if (x == 3) return 6;
        return 0;
    }
};

// make a call
some_computer_generated_gibberish_0123456789 an_instance_of_0123456789;
int outputValue = an_instance_of_0123456789(inputValue);

Nel tuo esempio di codice, per quanto riguarda le prestazioni non è diverso da una chiamata di funzione, perché quella classe di functor non ha uno stato (perché ha una clausola di acquisizione vuota), quindi non richiede allocazione, costruttore o distruzione.

int some_computer_generated_gibberish_0123456789_method_more_gibberish(int x)
{
    if (...) return ...;
    return ...;
}

Il debug di qualsiasi codice C ++ non banale mediante un disassemblatore è sempre stato un compito difficile. Questo è vero con o senza l'uso di lambda. Questo è causato dalla sofisticata ottimizzazione del codice da parte del compilatore C ++ che ha comportato il riordino, l'interleaving e l'eliminazione del codice morto.

L'aspetto di maneggevolezza dei nomi è alquanto sgradevole e il supporto del debugger per lambda è ancora in la sua infanzia . Si può solo sperare che il supporto del debugger migliorerà nel tempo.

Attualmente, il modo migliore per eseguire il debug del codice lambda è utilizzare un debugger che supporti l'impostazione dei breakpoint a livello di codice sorgente, ad esempio specificando il nome del file di origine e il numero di riga.

    
risposta data 08.07.2013 - 07:40
fonte
3

Per aggiungere alla risposta di @DocBrown, ricorda che oggigiorno le CPU sono economiche ma il lavoro è costoso.

Nel costo complessivo di un programma, l'hardware è solitamente banale rispetto al costo della manutenzione, che è di gran lunga la parte più costosa di un progetto tipico (anche più del suo sviluppo).

Pertanto, il tuo codice deve ottimizzare manutenzione sopra ogni altra cosa, tranne quando le prestazioni sono critiche (e anche allora la manutenzione deve essere presa in considerazione).

    
risposta data 08.07.2013 - 16:02
fonte