Ha ancora senso pensare a un codice efficace su micro scala in C ++?

3

All'inizio della mia carriera di programmatore ero innamorato del puntatore che girava, codice snello, che faceva tutto con il minor numero di astrazioni possibili e così via. Il codice era molto simile a C, direi vicino al metal e intelligente.

Il tempo è passato, ho molta più esperienza e sto notando che il mio atteggiamento nei confronti del codice è cambiato.

E con il cambiamento, voglio dire, non voglio più preoccuparmi delle cose di tutti i giorni, a meno che non sia super facile da fare.

Se esiste una concatenazione di stringhe, non sceglierò deliberatamente i puntatori grezzi. Se ho bisogno di concatenare cose, potrei aggiungere una riserva di congettura rapida per un container STL, ma non voglio preoccuparmi di buffer preallocati, C come API, cache, evitare di colpire il disco o cestinare. So che realloc potrebbe accadere di tanto in tanto, compresi tutti i blocchi dell'heap, la copia extra e così via, ma non mi preoccupo più.

Forse, è perché ho trascorso un po 'di tempo all'inizio della mia carriera in cui ho pensato a schemi puliti e belli con thread di lavoro che elaborano una grande quantità di dati banali, solo per scoprire in seguito che l'intero non ottimizzato realloc + copy + realloc + copy + realloc + copy + 5 strati di wrapper non si registrano nemmeno nel profiler.

Forse è perché ho visto come i compilatori a volte fanno magie.

Tuttavia, cose così banali si sommano. Quando tutta la tua base di codice utilizza costrutti di ordine superiore, è probabile che ci saranno alcuni realloc ovunque, o colpi di disco freddo, che possono causare una percezione generale di un'applicazione lenta.

Ordinamento di WTL vs MFC. O come sai immediatamente che l'applicazione è scritta in Java quando la lanci.

Ma è davvero? Esiste un confronto tra software che utilizza solo codice molto snello e intelligente rispetto a software che utilizza contenitori generici dappertutto?

Sentiresti mai la differenza se l'allocazione delle stringhe nel programma usasse prerequisiti e mosse intelligenti o pigramente chiamando string.append in ogni posto dove c'è bisogno di tale funzionalità?

Cerchi di implementare soluzioni di mitigazione per cose così semplici e ben note che sono economiche da eseguire comunque?

Il software può trasformarsi in bloatware solo perché non viene applicata ulteriore cautela su ogni riga di codice?

    
posta Coder 18.07.2012 - 02:40
fonte

4 risposte

6

No. I profiler possono dirti in modo rapido e adeguato esattamente dove si trovano i punti problematici.

Il motivo per cui alcuni framework sono problematici è perché quando il punto problematico si trova in una struttura o in una macchina virtuale, sei fregato. Se hai, realisticamente, completo controllo delle prestazioni sull'applicazione, allora impazzisci. Questo è il motivo per cui puoi dire quando un'app viene lanciata con Java - quando il rallentamento è nel codice JVM, non c'è nulla che nessun dev possa fare al riguardo. Tuttavia, questo tende a non essere un problema con lo sviluppo C ++ in generale.

Per non parlare del fatto che la potenza dei compilatori per tagliare le cazzate e rendere il tuo codice di alto livello molto più veloce cresce ogni anno.

Is there any comparisons of software that's using only very lean and smart code vs software that uses generic containers all over the place?

Odio portartelo, amico, ma i contenitori generici sono snelli e intelligenti. Uno dei loro principali vantaggi è che, poiché non è necessario riscriverli per ogni tipo che sia mai esistito, è possibile permettersi di scrivere codice ad alte prestazioni una volta e riutilizzarlo. È una semplice applicazione di DRY che migliora sia le prestazioni che l'affidabilità. Scrivendolo da solo 999999 volte non è il codice smart, questo è il codice stupido .

    
risposta data 18.07.2012 - 02:53
fonte
2

Il linguaggio non fa una grande differenza in ciò che ha senso preoccuparsi. Se stai lavorando su un progetto in cui il tuo codice è attualmente 4.2 KiB, e devi aggiungere altre due funzioni e inserire il risultato in una ROM da 4 KiB, la codifica per ridurre al minimo la dimensione probabilmente fa un lotto di senso.

D'altra parte, se si sta codificando per macchine desktop, dove 16 gigabyte di RAM e 2 terabyte di spazio su disco costa in totale circa $ 200, dedicare molto tempo ad assicurarsi che il codice sia il più piccolo e veloce potrebbe essere probabilmente lo zelo mal riposto.

Il posto ovvio in cui la lingua entra nella domanda è che nel caso del C ++, è stato fatto molto lavoro per fornire costrutti di livello superiore riducendo al minimo la penalità associata al loro utilizzo invece di adattare tutto il codice al compito esatto a mano. Non è sempre stato così: anni fa, Alexander Stepanov ha scritto un benchmark che mostra la penalità associata all'uso dei costrutti di livello superiore nella libreria di template standard. La maggior parte dei test aveva almeno due o tre "passaggi" dal codice scritto in stile C al massimo, sfruttando appieno i contenitori standard, gli algoritmi e l'iteratore.

Quando era nuovo, era quasi scontato che ogni passo che hai portato via dal codice stile C verso un uso più completo di contenitori / algoritmi / iteratori aveva una penalità, quindi per il momento in cui sei arrivato al massimo Versione STLish, era spesso ovunque da 2 a 5 volte più lento (e talvolta più vicino a 10 volte più lento).

Con gli attuali compilatori non è più il caso - in effetti, non è più così raro che il codice C-like sia effettivamente un po ' più lento del codice STL (anche se raramente da abbastanza di cui preoccuparsi molto)

Ciò ha richiesto un notevole sforzo da parte dei produttori di compilatori, ma dal momento che hanno fatto quel lavoro, di solito ha più senso trarne vantaggio. Il fatto che tu possa scrivere codice equivalente molto più rapidamente e facilmente a portata di mano - ma il fatto che nel processo di solito si riducano drasticamente gli errori è in genere molto più importante.

    
risposta data 18.07.2012 - 17:44
fonte
2

Sì, certo, nei posti giusti. Vorresti fare affidamento su librerie ottimizzate come le librerie standard C ++ se sono state scritte male e 10 volte più lente di oggi? Tutti quelli con cui hai lavorato hanno la stessa risposta alla domanda precedente?

"C like" e "clever" non sono generalmente complimenti in C ++. I contenitori generici non sono intrinsecamente lenti. In C ++, i livelli di astrazione possono essere scritti in modo tale che costano quasi nulla in fase di esecuzione (se questo è un problema).

La tua energia (supponendo che sia finita) non dovrebbe essere equamente divisa tra le linee. invece, guarda le aree che vengono maggiormente riutilizzate / utilizzate e che più comunemente servono come fondamento di altre implementazioni se la velocità, la dimensione e / o l'utilizzo delle risorse sono considerazioni. Stare vicino al metallo è facile quando stai riutilizzando e scrivendo buone implementazioni.

Man mano che le librerie, i kernel, l'hardware, i compilatori, ecc. variano e avanzano, capirai che non puoi prevedere la soluzione ottimale per ogni piattaforma / sistema. Non si può sempre vincere, né si dovrebbe tentare di vincere sempre date le grandi variazioni (si consideri una persona sempre alla base di implementazioni che utilizzano std::string per più dimensioni SSO). Tuttavia, le astrazioni inefficienti e generiche possono sommarsi rapidamente e costare molte volte di più di implementazioni ben eseguite ed efficienti.

La linea di fondo è "Sì, i programmi scritti pigramente possono essere molto più lenti e affamati di risorse rispetto ai programmi ben scritti".

Se il tuo codice di disegno (ad esempio) deve essere (o dovrebbe essere) dieci volte più veloce di quello che è oggi è un'altra domanda. Se il programma fosse un pony di piccole dimensioni, allora potrebbe non essere necessario alcun ulteriore ottimizzazione. Man mano che la complessità aumenta, queste inefficienze e il cattivo utilizzo delle risorse diventano rapidamente problemi molto importanti. Se sai che gli utenti porteranno il tuo programma al limite delle capacità dell'hardware spesso e il tempo o le prestazioni sono critici, dovresti prendere del tempo per considerare più approcci all'implementazione e scrivere programmi che siano precocemente .

Immagina quanto sarebbe migliore la tua esperienza di elaborazione se tutti i programmi che utilizzi oggi fossero 10 volte più veloci, usassero molta meno memoria, usassero buoni moduli paralleli, ecc. - la complessità del software cresce quasi alla stessa velocità dell'hardware, ma molto di quella "crescita" è anche ingigantita e implementazioni che non sono state ottimizzate bene. C'è molto spazio per migliorare.

    
risposta data 18.07.2012 - 17:34
fonte
2

I compilatori di linguaggi avanzati sono come le carte di credito - sono davvero a portata di mano, e rendono così facile acquistare cose straordinarie di cui veramente non è necessario, ma se riesci a mantenere tutta questa tendenza sotto controllo, sono la cosa migliore. Il problema è se, come la maggior parte di noi, perdi l'autocontrollo e spendi più di quanto dovresti.

Se fai solo piccoli programmi in stile accademico, non sarà mai un grosso problema, ma qui un esempio in cui un programma realisticamente complesso è stato eseguito in C ++ utilizzando classi di raccolta apparentemente ragionevoli e approccio progettuale. In quel programma, ci sono stati sei (6) miglioramenti delle prestazioni, con conseguente ( attenzione ) un fattore di accelerazione di settecentotrenta (730) volte. Uno di questi sei miglioramenti era il tipo di cosa che un compilatore di ottimizzazione avrebbe potuto produrre. Il resto erano semplicemente modifiche al design, indipendentemente da C ++ vs. C.

Quindi, se pensi semplicemente che "l'ottimizzazione del compilatore sta diventando talmente buona che posso semplicemente scatenarmi", è come supporre che se hai una carta di credito veramente buona con un basso interesse e una grande tecnologia on-line non puoi spendere troppo. Sicuro, e probabilmente lo farai, e la tecnologia non ti aiuterà.

Nel mondo delle carte di credito non posso offrirti una bacchetta magica, ma nel mondo del software posso. Uso una tecnica di profilazione manuale a bassa tecnologia che in realtà coinvolge il tuo cervello e trova cose che i profiler ordinari non trovano. Viene spiegato qui .

    
risposta data 20.07.2012 - 02:50
fonte

Leggi altre domande sui tag