In Java, perché usare bit hack quando la tecnica non bit a bit è più leggibile?

6

Esiste un uso legittimo di hack di manipolazione dei bit in linguaggi di livello superiore come Java?

Riesco a vederle utili in programmi a bassa intensità e ad uso intensivo di calcolo sensibili alla velocità, ad es. elaborazione grafica o funzioni crittografiche. Immagino sia per questo che tutte le loro raccolte sono in C. Tuttavia, arrivando a pensarle in termini di design di livello superiore non riesco a pensare a nessun punto in cui vorrei scrivere, ad esempio, quanto segue in un programma Java:

r = y ^ ((x ^ y) & -(x < y));

anziché:

r = (x < y) ? x : y;

La prima linea sembra più un'offuscamento che un miglioramento. E la maggior parte delle applicazioni ha diversi tipi di colli di bottiglia - più comunemente reti o accesso al disco, tanto che qualsiasi potenziale miglioramento ottenuto usando un hack bit a bit è talmente piccolo che è completamente ignorabile.

Questa linea di pensiero è stata provocata da una recente domanda SO in cui a qualcuno è stato chiesto di un hack bit a bit durante intervista.

Sono d'accordo tanto quanto chiunque che è sempre meglio scrivere codice più veloce, ma considerando che diventa molto meno leggibile, specialmente da qualcuno che non ha familiarità con i bit hack, c'è qualche tipo di applicazione in cui è legittimo che valga la pena?

Questa domanda non riguarda in generale gli operatori bit a bit, ma in particolare gli hack bit a bit e, ancora più specificamente, gli hack bit a bit in Java .

Per hack bit a bit intendo una manipolazione che ha un'implementazione banale e / o ovvia, ma che può essere eseguita leggermente più veloce / migliore con qualche intelligente manipolazione bit a bit - che nella maggior parte dei casi lo rende < em> near-illeggibile a qualcuno che non è abituato agli hack bit a bit.

Esistono domande simili: Importanza del pensiero bit a bit e A cosa servono gli operatori di bit? Le risposte a queste domande parlano di manipolazioni di bit in generale , che sì, hanno molte applicazioni chiare e utili; specialmente in altri linguaggi come C. Anche se questo può sembrare simile, la mia domanda era di averli contro usando la tecnica non bit a bit in Java. Nelle altre domande questo non è affatto affrontato.

    
posta blgt 29.06.2014 - 19:52
fonte

1 risposta

8

A volte, le specifiche di un algoritmo si basano su operazioni di bit. Questo è particolarmente vero nel lavoro di crittografia.

Crypto ha un altro attributo che è importante - che l'operazione richiede esattamente lo stesso tempo indipendentemente da quali siano i parametri. Questo per cercare di evitare la perdita di dati con attacchi di temporizzazione (ci sono persino attacchi basati su fa sembrare il computer mentre fa la crittografia ).

Quindi, per la crittografia, è di fondamentale importanza che il codice impieghi esattamente lo stesso tempo e faccia le stesse cose. Le operazioni bit a bit possono svolgere un ruolo significativo in quell'area in quanto non vengono spesso o facilmente ottimizzate dal compilatore. Con le cose, si può mettere in corto circuito l'espressione o decidere di seguire una branca o un'altra che ha un tempismo diverso, queste sono strade di attacchi temporali.

Il codice

if(x < y) {
  r = x;
} else {
  r = y;
}

Può richiedere diverse quantità di tempo in base alla previsione del ramo e alla ramificazione stessa. Mentre

r = y ^ ((x ^ y) & -(x < y));

prende esattamente la stessa quantità di tempo ogni volta attraverso il codice. La previsione del ramo non ha alcun ruolo perché non ci sono rami lì dentro.

Con la grafica funziona, ci sono aree di preoccupazione simili. Alcuni sistemi (specialmente quelli più vecchi) avevano il refresh del CRT legato al ciclo di clock (ad esempio l'Amiga ha avuto 4 cicli di clock per linea di aggiornamento). Ciò significava che quando scrivevi un codice che era specificamente adattato alla grafica del sistema, sapevi esattamente dove l'aggiornamento dello schermo era e poteva migliorare l'aspetto del sistema. Questo non è più un problema ora (la GForce GTX 780 può fare 40.0000 operazioni per pixel per aggiornamento del frame), ma è qualcosa da considerare.

In secondo luogo, c'è anche una profonda magia nel sistemare le cose in vari cache su vari sistemi. Fare il più possibile con la cache può migliorarlo. Ciò significa spesso eseguire operazioni bit a bit anziché cercare di caricare e archiviare oggetti o inviarli alla ALU .

In Java, questo può essere difficile da sapere con certezza, ma ancora una volta, mantenere una frequenza fotogrammi coerente basata sulla scena è qualcosa che spesso è molto importante con la grafica.

    
risposta data 29.06.2014 - 20:24
fonte