È utile usare l'aritmetica binaria in un codice C ++ come "C style"?

7

Mi piace il fatto che il linguaggio C ti permetta di usare l'aritmetica binaria in modo esplicito nel tuo codice, a volte l'uso dell'aritmetica binaria può anche darti un piccolo vantaggio in termini di prestazioni; ma da quando ho iniziato a studiare C ++ non posso davvero dire quanto ho visto l'uso esplicito di qualcosa di simile in un codice C ++, qualcosa come un puntatore alla struttura del puntatore o un'istruzione per saltare a uno specifico valore di indice attraverso l'aritmetica binaria .

L'aritmetica binaria è ancora importante e rilevante nel mondo C ++? Come posso ottimizzare la mia aritmetica e / o l'accesso a un indice specifico? Che dire del C ++ e del modo in cui i bit sono disposti secondo lo standard?

... o ho dato un'occhiata alle convenzioni di codifica sbagliate ...?

    
posta user827992 25.06.2012 - 13:33
fonte

9 risposte

25

In breve: No, non è consigliabile usare "aritmetica binaria" (nel senso che la domanda lo richiede) o "C style" in C ++ .

Cosa ti fa pensare che l'aritmetica bit a bit sarebbe davvero più veloce? Puoi lanciare le operazioni bit a bit su tutto il codice, ma cosa lo renderebbe più veloce?

Il fatto è che quasi qualsiasi cosa banale che stai cercando di risolvere, può essere risolta più facilmente dalle funzioni standard di alto livello (inclusi gli algoritmi standard della libreria, STL e STL). In alcuni casi specifici potresti davvero voler cambiare i singoli bit, ad esempio quando lavori con maschere di bit . Oppure memorizzare dati molto compatti, ad esempio quando si scrive un algoritmo di compressione, un formato di file denso o si lavora ad esempio con sistemi incorporati.

Se ti preoccupi delle prestazioni, sempre scrivi prima un algoritmo semplice e banale. Falla funzionare. Quindi, misura il tempo che il tuo algoritmo assume con un input tipico. Ora, se a questo punto senti che è troppo lento, solo allora puoi provare l'ottimizzazione a mano con questi trucchi "aritmetici bit a bit". E dopo aver finito, misura se il tuo codice è più veloce. È probabile che non lo sia, a meno che tu non sappia davvero cosa stai facendo in quella specifica situazione / caso.

Francamente, il modo migliore per comprendere questo tipo di costrutti di basso livello che si occupano di prestazioni è studiare il linguaggio dell'assemblaggio. Ti fa davvero capire che no, scrivere un po 'di codice di manipolazione dei bit non è più veloce che usare sort(begin(v),end(v)) . Solo perché si opera a basso livello non significa che si opera velocemente. In generale, gli algoritmi sono più importanti dei dettagli di implementazione!

Sostanzialmente qualunque sia lo " stile C " significa, per favore , stai lontano da esso quando scrivi C ++. Sono due lingue completamente diverse. Non mescolarli.

Bjarne Stroustrup ha tenuto una bella chiacchierata sullo stile C ++ nella conferenza Microsoft GoingNative 2012 a febbraio, per favore guarda: link

Specialmente le parti tra 10 e 15 minuti sono grandi, quando parla del vecchio codice in stile C rispetto al moderno stile C ++.

    
risposta data 25.06.2012 - 14:34
fonte
13

for example the shift operator << or >>, which is a quick way to calculate "something times 2" or "something divided by 2"

Che tu stia lavorando in C o C ++, scrivi cosa intendi. Scrivi foo = foo * 2; o foo *= 2; se questo è ciò che intendi, non foo = foo << 1; . Lascia che il compilatore si occupi di trovare le istruzioni più veloci da usare e non confondere le persone che devono leggere il tuo codice con l'ottimizzazione manuale non necessaria.

    
risposta data 25.06.2012 - 18:38
fonte
8

Segui questi passaggi:

  1. Scrivi il codice nel modo più semplice e chiaro possibile
  2. Attiva tutte le ottimizzazioni del compilatore.
  3. Considerare se si dispone di conoscenze sufficienti sulla CPU di destinazione specifica e sul relativo set di istruzioni (assemblatore). In caso contrario, probabilmente non riuscirai a fare ottimizzazioni manuali e probabilmente non dovresti provarlo, poiché probabilmente finirai per offuscare il codice senza alcun guadagno. Si noti inoltre che l'ottimizzazione manuale è necessaria solo se il compilatore ha uno scarso supporto per la specifica piattaforma di destinazione. In alternativa, puoi provare un altro compilatore.

  4. Identifica i colli di bottiglia delle prestazioni. Come trovarli dipende dal sistema di destinazione. Nei programmi di "alto livello" come la programmazione desktop, l'utente esegue il benchmarking del proprio codice tramite strumenti specifici progettati per tale scopo o tramite le funzioni dell'API del sistema operativo. Sui programmi "di basso livello" come i sistemi incorporati, in genere si utilizza un oscilloscopio per misurare le prestazioni in tempo reale. Su qualsiasi programma, puoi disassemblare il codice e vedere cosa il compilatore ha effettivamente trovato.

  5. Se non ci sono colli di bottiglia che influenzano le prestazioni del tuo programma, non devi fare nulla e puoi smettere di leggere qui.
  6. Se vi sono dei colli di bottiglia che hanno un impatto sul programma, potrebbe essere necessario eseguire l'ottimizzazione manuale.
  7. In che modo le ottimizzazioni manuali dipendono dalla CPU di destinazione, non esiste un trucco universale. Le cose comuni da cercare sono: aritmetica in virgola mobile, allineamento, dimensioni dei numeri interi, divisione, previsione dei rami e amp; gestione della cache delle istruzioni, uso di funzioni della libreria inutilmente complesse ... e così via.
risposta data 26.06.2012 - 09:57
fonte
4

Dipende dal tipo di codice C ++ che stai scrivendo. Più sei basso, più diventa rilevante. Il problema con questo tipo di domande è che ognuno può fare affidamento solo sulla propria esperienza e quindi se qualcuno non ha mai dovuto fare questo genere di cose non può capire perché qualcun altro potrebbe aver bisogno di farlo.

Ecco l'articolo "Cinque mondi" di Joel

    
risposta data 25.06.2012 - 17:16
fonte
2

Uso dell'aritmetica binaria praticamente TUTTE le lingue con cui ho programmato i computer. Ad esempio, prendi l'operatore di addizione + :

int sum = x + y; // compiler probably implements this as binary arithmetic!

Trovo difficile programmare in un linguaggio che non supporta l'aritmetica e troverei difficile credere che le operazioni aritmetiche non siano state implementate dal compilatore / interprete usando l'aritmetica binaria (come l'uso dell'aritmetica in base 10) .

link

link

link

TL; DR: usa la terminologia corretta (bitmap ≠ bitwise), altrimenti ottieni risposte pendates come questa.

    
risposta data 18.09.2012 - 21:19
fonte
1

L'aritmetica binaria è legata all'implementazione. Devi stare attento ai dettagli di implementazione come endianness. Pertanto, l'utilizzo di operatori binari non è automaticamente più veloce rispetto all'utilizzo di operatori elementari. Spesso il compilatore esegue ottimizzazioni più rilevanti e un codice naturale può essere migliore per le prestazioni e più facile da leggere sia per il compilatore che per il programmatore.

Naturalmente, ci sono alcuni casi (come la codifica Base64), in cui è necessario utilizzare quegli operatori. Ma l'ottimizzazione del codice con gli operatori binari dovrebbe essere l'ultima ottimizzazione, dopo aver perfezionato i tuoi algoritmi. Per la programmazione personale, alcuni trucchi ( come questo ) potrebbero essere più veloci, ma con una programmazione seria, la leggibilità dovrebbe venire prima.

E, come zxcdw detto, C e C ++ sono entrambe lingue molto diverse. C ++ ha più librerie di alto livello, quindi i trucchi binari sono meno famosi.

    
risposta data 25.06.2012 - 15:11
fonte
1

No, non c'è alcun uso dell'aritmetica binaria in C ++, eccetto un dettaglio "minuscolo": lo standard C ++ definisce la semantica del linguaggio in termini di un binario virtuale astratto macchina che deve utilizzare sia la prima parte del complemento, il 2 ° complemento o la rappresentazione dell'intero segno.

    
risposta data 25.06.2012 - 17:15
fonte
1

Come molti hanno già menzionato, sii consapevole che non ottimizza prematuramente le cose . Ma quando trovi il codice associato alla CPU che è un collo di bottiglia , uno dei modi migliori per capire quale delle tue implementazioni alternative sarebbe meglio, usando Clang C / C ++ - > LLVM IR è una grande idea. Se ti senti più a tuo agio in un browser web, prova link .

L'IR (Intermediate Representation) generato da Clang e LLVM sono istruzioni della macchina virtuale. Ad esempio, è possibile scrivere lo stesso algoritmo / funzione aritmetica in "C style" e "C ++ style" (sto cercando "STL-style"?) E confrontare l'IR generato dal compilatore. Anche se il compilatore del prodotto finale non è basato su LLVM, il codice IR sarà rappresentativo del codice effettivamente generato e compilato. Oltre l'IR ci sono solo ottimizzazioni hardware (come il modo in cui vengono implementati i landing pad da rami condizionali). LLVM può produrre assembly di computer di destinazione, se pensi che ti renderebbe più saggio (ma non consiglierei di andare oltre l'IR).

    
risposta data 26.06.2012 - 01:21
fonte
0

A volte diversi flag sono stipati in un singolo byte per risparmiare spazio. A volte è prematuro, altre volte critico.

Microsoft SQL Server memorizzerà più colonne del tipo di dati "bit" nello stesso byte. In questo caso non è una ottimizzazione prematura. Si risparmiano da 2 a 8 volte lo spazio su disco, per colonne da 2 a 8 bit (questo è un grosso problema). Ottieni anche ricerche più veloci (un grosso problema). È anche più probabile che tu possa memorizzare nella cache un set di dati in memoria. Questo è perfetto. Dal momento che non vi è alcun vantaggio nell'indicizzazione dei dati binari, è possibile anche raggruppare i bit. E la natura bit a bit non è esposta ai programmatori dei clienti, quindi tutti sono felici.

L'API di Windows contiene diverse opzioni per byte. Si manipolano le opzioni di visualizzazione con operazioni bit a bit. Direi che questo era prematuro. Ha anche reso molte persone abbandonare la programmazione di Windows. Ma i programmatori che hanno scritto l'API provenivano dai vecchi tempi in cui lo spazio era severamente limitato. Al momento potrebbe essere una buona idea progettare un'API attorno alla manipolazione bit a bit.

I videogiochi client / server amano confezionare più flag in un byte. Ad esempio, sul server il gioco calcola il tuo danno. Restituirà i dati del display al client, con diversi flag come se fosse un colpo critico, se uccidesse il nemico, ecc. Il display quindi procederebbe con operazioni bit a bit. È discutibile se sia prematuro o no. Ma mi piacerebbe dire che less is more quando spingo i dati su una rete.

    
risposta data 19.09.2012 - 03:14
fonte

Leggi altre domande sui tag