Scrivere in C per le prestazioni? [chiuso]

32

So di aver sentito abbastanza spesso che C ha in genere un vantaggio in termini di prestazioni rispetto al C ++. Non ho davvero pensato ad altro fino a quando non ho capito che MSVC non sembra nemmeno supportare il nuovo standard di C, ma il più recente lo supporta C99 (per quanto ne so).

Stavo pensando di scrivere una libreria con del codice da renderizzare in OpenGL in modo da poterla riutilizzare. Stavo progettando di scrivere la libreria in C poiché qualsiasi aumento delle prestazioni è benvenuto quando si tratta di grafica.

Ma ne varrebbe davvero la pena? Il codice che utilizza la libreria verrebbe probabilmente scritto in C ++ e preferisco codificare in C ++ in generale.

Tuttavia, se producesse anche una piccola differenza nelle prestazioni, probabilmente andrei con C.

Si può anche notare che questa libreria sarebbe qualcosa che avrei fatto funzionare su Windows / OS X / Linux, e probabilmente compilerei tutto in modo nativo (MSVC per Windows, Clang o GCC per OS X e GCC per Linux ... o forse i compilatori di Intel per tutto).

Mi sono guardato attorno e ho trovato alcuni benchmark e simili, ma tutto ciò che ho visto si è occupato di GCC piuttosto che di MSVC e Clang. Inoltre, i parametri di riferimento non menzionano gli standard delle lingue utilizzate. Qualcuno ha qualche idea su questo?

EDIT: volevo solo condividere il mio punto di vista su questa domanda dopo un paio d'anni di esperienza in più. Ho finito per scrivere il progetto per cui stavo facendo questa domanda in C ++. Ho iniziato un altro progetto nello stesso periodo in C perché stavamo cercando di ottenere una piccola quantità di prestazioni che potevamo e avevamo bisogno che il progetto fosse collegabile in C. Un paio di mesi fa, ho raggiunto il punto in cui avevo davvero bisogno di mappe e avanzato manipolazione delle stringhe. Conoscevo le capacità di questo nella libreria standard del C ++ e alla fine giunsi alla conclusione che quelle strutture nella libreria standard avrebbero sovraperformato e sarebbero state più stabili delle mappe e delle stringhe che avrei potuto implementare in C in un ragionevole lasso di tempo. Il requisito di essere collegabili in C è stato facilmente soddisfatto scrivendo un'interfaccia C sul codice C ++, che è stata eseguita rapidamente con tipi opachi. Riscrivere la libreria in C ++ sembrava andare molto più veloce rispetto a quando lo scriveva in C ed era meno incline a bug, soprattutto perdite di memoria. Sono stato anche in grado di utilizzare la libreria di threading della libreria standard, che è stata molto più semplice rispetto all'utilizzo di implementazioni specifiche della piattaforma. Alla fine, credo che scrivere la libreria in C ++ abbia portato grandi benefici con possibilmente un piccolo costo di prestazioni. Non ho ancora analizzato la versione C ++, ma credo che potrebbe anche essere possibile ottenere delle prestazioni utilizzando le strutture di dati della libreria standard rispetto a quelle che ho scritto.

    
posta danielunderwood 07.05.2014 - 01:52
fonte

7 risposte

88

Suppongo che le persone affermino spesso che C è più veloce del C ++ perché è più facile per motivo sulle prestazioni in C. C ++ non è intrinsecamente più lento o più veloce, ma un certo codice C ++ potrebbe oscurare le penalizzazioni delle prestazioni nascoste. Ad esempio, ci possono essere copie e conversioni implicite che non sono immediatamente visibili quando si guarda un pezzo di codice C ++.

Prendiamo la seguente dichiarazione:

foo->doSomething(a + 5, *c);

Supponiamo inoltre che doSomething abbia la seguente firma:

void doSomething(int a, long b);

Ora proviamo ad analizzare il possibile impatto sulle prestazioni di questa particolare affermazione.

In C, le implicazioni sono abbastanza chiare. foo può essere solo un puntatore a una struttura e doSomething deve essere un puntatore a una funzione. *c dereferences a long e a + 5 è l'aggiunta di interi. L'unica incertezza deriva dal tipo di a : se non è un int, ci sarà qualche conversione. ma a parte questo, è facile quantificare l'impatto sulle prestazioni di questa singola affermazione.

Ora passiamo a C ++. La stessa affermazione ora può avere caratteristiche prestazionali molto diverse:

  1. doSomething potrebbe essere una funzione membro non virtuale (a buon mercato), funzione membro virtuale (un po 'più costosa), std::function , lambda ... ecc. Cosa c'è di peggio, foo potrebbe essere un tipo di classe che sovraccarica operator-> con qualche operazione di complessità sconosciuta. Pertanto, per quantificare il costo della chiamata di doSomething , è ora necessario conoscere la natura esatta di foo e doSomething .
  2. a potrebbe essere un numero intero o un riferimento a un numero intero (indiretto aggiuntivo) o un tipo di classe che implementa operator+(int) . L'operatore potrebbe anche restituire un altro tipo di classe che è implicitamente convertibile in int . Ancora una volta, il costo delle prestazioni non è evidente dalla sola affermazione.
  3. c potrebbe essere un tipo di classe che implementa operator*() . Potrebbe anche essere un riferimento a un long* ecc.

Ottieni l'immagine. A causa delle caratteristiche linguistiche del linguaggio C ++, è molto più difficile quantificare i costi delle prestazioni di una singola istruzione rispetto a C. Ora inoltre, le astrazioni come std::vector , std::string sono comunemente usate in C ++, che hanno caratteristiche di prestazione proprie, e nascondere le allocazioni di memoria dinamica (vedi anche la risposta di @ Ian).

Quindi, la linea di fondo è: In generale, non c'è differenza nelle possibili prestazioni ottenibili utilizzando C o C ++. Ma per un codice realmente critico per le prestazioni, le persone preferiscono spesso usare C perché ci sono meno sanzioni possibili per le prestazioni nascoste .

    
risposta data 07.05.2014 - 13:18
fonte
30

Il codice scritto in C ++ può essere più veloce che in C, per determinati tipi di compiti.

Se preferisci il C ++, usa C ++. Qualsiasi problema di prestazioni sarà insignificante rispetto alle decisioni algoritmiche del tuo software.

    
risposta data 07.05.2014 - 02:01
fonte
23

Uno dei principi di progettazione di C ++ è che non si paga per le funzionalità che non si utilizzano. Quindi, se scrivi codice in C ++ ed eviti funzionalità che non esistono in C, il codice compilato risultante dovrebbe essere equivalente in termini di prestazioni (anche se dovresti misurare questo).

C'è un costo trascurabile nell'uso delle classi, ad esempio, rispetto alle strutture e un mucchio di funzioni associate. Le funzioni virtuali costeranno un po 'di più e dovrai misurare le prestazioni per vedere se è importante per la tua applicazione. Lo stesso vale per qualsiasi altra caratteristica del linguaggio C ++.

    
risposta data 07.05.2014 - 02:06
fonte
14

Una delle ragioni per cui i linguaggi di livello superiore sono a volte più lenti è che possono nascondere dietro le quinte una gestione della memoria molto maggiore rispetto ai linguaggi di livello inferiore.

Qualsiasi linguaggio (o libreria, API, ecc.) che astrae dettagli di basso livello può potenzialmente nascondere attività costose. Ad esempio, in alcune lingue semplicemente ritagliare spazi bianchi finali da una stringa risulta in un'allocazione di memoria e una copia della stringa. L'allocazione della memoria e la copia, in particolare, possono diventare costose se si verificano ripetutamente in un ciclo limitato.

Se scrivessi questo tipo di codice in C sarebbe palesemente ovvio. In C ++ forse meno, perché le allocazioni e la copia potrebbero essere astratte in una classe da qualche parte. Potrebbero persino essere nascosti dietro un operatore o un costruttore di copie dall'aspetto innocente.

Quindi usa C ++ se vuoi. Ma non lasciarti ingannare dall'apparente comodità delle astrazioni quando non sai cosa c'è sotto di loro.

Ovviamente, usa un profiler per scoprire cosa rallenta veramente il codice.

    
risposta data 07.05.2014 - 11:35
fonte
5

Per quel che vale, tendo a scrivere le mie librerie in C ++ 11 per il set di funzionalità avanzate. Mi piace essere in grado di sfruttare le cose come i puntatori condivisi, le eccezioni, la programmazione generica e altre caratteristiche solo del C ++. Mi piace il C ++ 11 perché ho scoperto che un bel po 'di esso è supportato su tutte le piattaforme a cui tengo. Visual Studio 2013 ha un sacco delle funzionalità linguistiche di base e delle implementazioni di libreria pronte per l'uso e si suppone stia lavorando per aggiungere il resto. Come ben sai, Clang e GCC supportano anche l'intero set di funzionalità.

Detto ciò, di recente ho letto di una strategia davvero grande per quanto riguarda lo sviluppo delle biblioteche che penso sia direttamente pertinente alla tua domanda. L'articolo è intitolato "AC che gestisce lo stile degli errori con le eccezioni C ++" Stefanu Du Toit si riferisce a questa strategia come a un modello a "clessidra". Il primo paragrafo dell'articolo:

I've written a lot of library code using what I call an "hourglass" pattern: I implement a library (in my case, typically, using C++), wrap it in a C API which becomes the only entry point to the library, then wrap that C API in C++ or some other language(s) to provide a rich abstraction and convenient syntax. When it comes to native cross-platform code, C APIs provide unparalleled ABI stability, and portability to other languages via FFIs. I even restrict the API to a subset of C that I know is portable to a wide variety of FFIs and insulates the library from leaking changes in internal data structures — expect more on that in future blog posts.

Ora per rispondere alla tua preoccupazione principale: le prestazioni.

Suggerirei, come molte altre risposte qui, che scrivere codice in entrambe le lingue funzionerebbe altrettanto bene sul piano delle prestazioni. Da un punto di vista personale, trovo che scrivere codice corretto in C ++ sia più semplice a causa delle caratteristiche del linguaggio, ma penso che sia una preferenza personale. In entrambi i casi, i compilatori sono davvero intelligenti e tendono a scrivere un codice migliore di te comunque. Ciò significa che il compilatore probabilmente ottimizzerà il tuo codice meglio di quanto potresti.

So che molti programmatori dicono questo, ma la prima cosa che dovresti fare è scrivere il tuo codice, quindi tracciarlo e fare ottimizzazioni laddove il tuo profiler ti suggerisce di farlo. Il tuo tempo sarà speso molto meglio nella produzione di funzionalità e quindi nell'ottimizzazione una volta che potrai vedere dove sono i tuoi colli di bottiglia.

Ora ci sono alcune letture divertenti su come le funzionalità e le ottimizzazioni della lingua possono davvero funzionare a tuo favore:

std :: unique_ptr ha zero overhead

constexp consente il calcolo in fase di compilazione

spostare la semantica previene gli oggetti temporanei non necessari

    
risposta data 07.05.2014 - 19:54
fonte
4

La differenza di prestazioni tra C ++ e C non è dovuta a nulla nella lingua, in senso stretto, ma in ciò che ti spinge a fare. È come una carta di credito contro denaro. Non ti fa spendere di più, ma lo fai comunque, a meno che tu non sia molto disciplinato.

Ecco un esempio di un programma scritto in C ++, che è stato poi aggressivamente ottimizzato per le prestazioni . Devi sapere come eseguire l'ottimizzazione aggressiva delle prestazioni, indipendentemente dalla lingua. Il metodo che uso è una pausa casuale, come mostrato in questo video .

I tipi di cose costose che il C ++ ti spinge a fare sono gestione eccessiva della memoria, programmazione in stile notifica, affidamento al contatore del programma su librerie di astrazione a più livelli (come dice @Ian), nascondimento della lentezza, ecc.

    
risposta data 07.05.2014 - 13:28
fonte
2

C non ha alcun vantaggio in termini di prestazioni rispetto a C ++ se si eseguono le stesse operazioni in entrambe le lingue. Puoi prendere qualsiasi vecchio codice C scritto da qualsiasi programmatore C decente e trasformarlo in un codice C ++ valido e equivalente, che funzionerà altrettanto velocemente (a meno che tu e il tuo compilatore non sappiate cosa fa la parola chiave "restrict" e la usate in modo efficace, ma la maggior parte della gente non lo fa).

C ++ può avere prestazioni enormemente diverse, sia più lente sia più veloci, se (1) usi la libreria standard C ++ per fare cose che possono essere fatte molto più velocemente e più facilmente senza usare la libreria, o (2) se usi libreria standard di C ++ per fare le cose molto più facile e più veloce di reimplementare la libreria in cattiva C.

    
risposta data 07.05.2014 - 18:29
fonte

Leggi altre domande sui tag