it-swarm.it

Big-O è davvero così rilevante quando si lavora nell'industria?

In ogni intervista in cui sono stato, sono stato interrogato sull'analisi matematica della complessità, inclusa la notazione big-O.

Quanto è importante l'analisi big-O per lo sviluppo nell'industria? Quanto spesso lo usi davvero e quanto è necessario avere una mentalità raffinata per il problema?

66
MM01

La mia domanda è: quanto è importante questo test per lo sviluppo nell'industria?

Una solida conoscenza della teoria della complessità computazionale (ad es. Notazione O grande) è essenziale per progettare algoritmi, applicazioni e sistemi scalabili. Poiché la scalabilità è estremamente rilevante per l'informatica nell'industria, lo è anche la grande notazione O.

Con quale frequenza lo usi in modo veritiero e quanto è necessario avere una mentalità raffinata per il problema?

Dipende da cosa intendi per "usalo davvero". Da un lato, non faccio mai prove formali della complessità computazionale per il software che scrivo. D'altra parte, quasi tutti i giorni ho a che fare con applicazioni in cui la scalabilità è una potenziale preoccupazione e le decisioni di progettazione includono la selezione (ad esempio) di tipi di raccolta appropriati in base alle loro caratteristiche di complessità.

(Non so se sia possibile implementare coerentemente sistemi scalabili senza una solida comprensione della teoria della complessità. Sarei propenso a pensare che non lo sia.)

76
Stephen C

Il motivo è dovuto al fatto che indica la scalabilità .

Un processo che è O (n ^ 2) scalerà peggio di uno che è O (n log n), ma migliore di uno in O (n ^ 3) o addirittura O (n!).

Se non si conoscono le differenze e quando si applicano, si è meno adatti a scegliere le giuste implementazioni di funzionalità, nonché a estrapolare le prestazioni dei test in prestazioni di produzione.


EDIT: un confronto di 48n con n ^ 3 da http://www.codinghorror.com/blog/2007/09/everything-is-fast-for-small-n.html (che in il turno è da Programmare Perle)

enter image description here

36
user1249

Dipende da cosa stai facendo.

Per gli sviluppatori web (come me) questo di solito conta molto. Volete ridimensionare le app Web. Se la tua app ha un collo di bottiglia che si ridimensiona con O (n ^ 2) e pensi che vada bene, poiché il tuo server può gestire 1000 utenti simultanei, sembra che non ti interessi. Il fatto è che per gestirne solo il doppio (il che è ragionevolmente probabile che accada poco dopo la notte), avrai bisogno di 4 volte la potenza computazionale. Idealmente, le app Web devono essere ridimensionate su O (n), poiché l'hardware è economico con un rapporto utente/server costante ragionevole.

Generalmente nelle app, dove hai 100000 oggetti, il grande O verrà a mangiarti. Sei incredibilmente vulnerabile alle cime. Ad esempio, sto attualmente lavorando a un gioco 3D, che è un'app che gestisce un sacco di dati. Oltre al rendering, hai il controllo delle collisioni, la navigazione ecc. Non puoi permetterti di andare nel modo ovvio. Hai bisogno di algoritmi efficaci, hai bisogno di molta cache per ammortizzare quelli meno efficienti. E così via.

Naturalmente se quello che fai è qualcosa come creare un'app mobile mettendo insieme una GUI in un designer di interfacce, collegalo con alcuni servizi web e basta, allora non avrai mai problemi con la complessità. Perché i servizi web che chiami già si occupano di esso.

32
back2dos

In realtà non ho mai applicato formalmente la regola nella mia vita lavorativa.

Tuttavia, devi conoscere questo concetto e applicarlo in modo intuitivo ogni volta che progetti un algoritmo.

La regola è:

Dovresti avere abbastanza familiarità con la notazione O per poter determinare, per un determinato compito, se è necessario calcolarlo formalmente, oppure è sufficiente per valutarlo in modo intuitivo o se puoi semplicemente saltarlo completamente. Proprio come molti altri concetti matematici di base.

22
Wizard79

Bene, forse una piccola storia ti illumina perché DEFINITAMENTE IS necessario:

In un progetto a cui ho lavorato, c'era un programma responsabile della stampa di tutti i tipi di documenti (etichette, liste di prelievo ecc.). Questo programma consisteva in due parti, una che leggeva tutti i dati necessari dal database e li scriveva in un File .ini-style e un'altra parte che legge quei file e li ha riempiti nei template. Questo ha funzionato abbastanza bene per etichette e piccoli elenchi (con solo pochi campi) ma ha funzionato per quasi 10 minuti quando ha dovuto stampare un elenco "grande" di ~ 20 pagine. Poiché l'accesso a questi file ini ha comportato tempi di accesso O (n²), essendo n il numero di campi da stampare.

Se i programmatori originali di questo programma avessero capito la notazione O, non l'avrebbero mai fatto in quel modo. Sostituire quella stupidità con un hashtable lo ha reso molto più veloce.

10
user281377

Le prestazioni della Big-O sono importanti, ma sono state ampiamente interiorizzate.

Le prestazioni Big-O di ordinamento e ricerca non contano, perché le persone generalmente usano quelle fornite dal sistema e quelle saranno le migliori possibili (dato che devono essere generalmente utili). Esistono strutture di dati che sono più efficienti per cose diverse, ma di solito possono essere selezionate in base a principi generali (e sono generalmente integrate in linguaggi moderni). C'è un certo senso di algoritmi che si adattano o non si adattano.

Il risultato è che le questioni formali raramente emergono nella pratica, ma la pratica si basa sugli stessi principi.

8
David Thornley

IMHO molti programmi di informatica lasciano molti studenti che vagano laggiù tra le erbacce. Questi programmi non comunicano mai del tutto il quadro di cosa sia la scienza del calcolo. Gli studenti entrano nel settore, alle prese con come applicare i concetti che hanno imparato, con poca comprensione di come si relazionano con il mondo reale.

Direi che il cuore della scienza del calcolo è la capacità di ragionare sul calcolo. E impari vari metodi e tecniche per farlo e li applichi a problemi astratti, che sono primitivi prototipici trovati in molti problemi del mondo reale. Il trucco è individuare questi primitivi prototipici nel mondo reale, e quindi ragionare su cose come correttezza, complessità, tempo ecc., Che, potresti essere d'accordo, sono problemi reali di cui devi preoccuparti. Comprensione di come si comportano le parti, spesso ti dà un'idea di come si comporta l'intero. E gli stessi metodi e tecniche generali possono anche essere applicati al tutto, ma non con la stessa rigorosità che viene offerta a parti più piccole, ben astratte e ben definite. Ma alla fine, la scienza del calcolo, ti dà la possibilità di prendere ragionevoli decisioni su come organizzare il tuo calcolo, con una visione reale di come si comporterà in varie condizioni.

7
Ziffusion

Promemoria per sé !:

Io e molti altri ci poniamo questa domanda regolarmente.

Penso che il vero motivo per cui lo chiediamo sia perché siamo diventati pigri.

Questa conoscenza non uscirà mai o diventerà obsoleta. Potresti non applicarlo direttamente su base giornaliera ma lo utilizzerai inconsciamente e avrà un effetto positivo sulle tue decisioni di progettazione. Un giorno potrebbe salvare te o altri ore e giorni di programmazione.

Poiché più problemi sono incapsulati da librerie e strumenti di terze parti e sono disponibili per un numero sempre maggiore di sviluppatori, sarà necessario conoscere queste conoscenze per distinguersi dagli altri e aiutare a risolvere nuovi problemi.

5
Conor

Non proprio. Fondamentalmente l'unica volta che ci abbia mai pensato è quando accedo al database. Di solito guardo il codice e dico "Sta facendo n + 1 query, dovresti cambiarlo per fare solo 1 o 2"

Poiché tutti i miei dati vengono letti da un database e mostrati all'utente, cerco di ridurre al minimo la quantità di dati con cui sto lavorando al punto in cui la differenza tra un algoritmo lineare e uno O (n ^ 2) è piuttosto trascurabile.

Se c'è un problema, lo profileremo e lo ripareremo in seguito.

5
Greg

Tre domande che poni e penso che risposte in forma abbreviata possano aiutare gli argomenti più lunghi forniti finora.

Quanto è importante questo test per lo sviluppo nel settore?

Dipende dall'industria.

Ovunque in cui la velocità del codice o lo spazio del codice sia un problema, è del tutto rilevante per il settore interessato. Spesso devi sapere quanto tempo richiederà una routine o quanta memoria (on/offline) richiederà.

Con quale frequenza lo usi in modo reale?

Dipende dall'industria.

Se le prestazioni e il ridimensionamento sono di scarsa preoccupazione per il lavoro da svolgere, raramente, solo in presenza di un grave calo delle prestazioni. Se sei un ingegnere per un sistema critico altamente utilizzato, probabilmente ogni giorno.

Quanto è necessario avere una mentalità raffinata per il problema?

Completamente necessario.

Potrebbe essere necessario utilizzarlo ogni giorno o solo in circostanze terribili; ma a volte sarà necessario. Preferibilmente durante la progettazione prima che arrivi un problema, piuttosto che profilare disperatamente un sistema di soffocamento.

3
Orbling

Direi che è molto frequente. Generalmente non proviamo che qualcosa ha un grande O-particolare, ma abbiamo interiorizzato l'idea e memorizzato/familiarizzato con le garanzie del grande-O per particolari strutture di dati e algoritmi e scegliamo quelli più veloci per un uso particolare. Aiuta ad avere una libreria piena di tutte le opzioni, come la libreria Java delle raccolte, o la C++ STL. Implicitamente e naturalmente usi big-O tutti i giorni = quando scegli di usare un Java.util.HashMap (O(1) ricerca) invece di un Java.util.TreeMap (O(lg n) ricerca) e sicuramente scegliendo di non eseguire un lineare cerca in Java.util.LinkedList (O(n) ricerca) qualcosa in cui non hai bisogno di un accesso ordinato.

Quando qualcuno sceglie un'implementazione non ottimale e qualcuno che conosce meglio arriva e vede il proprio codice, fa parte del nostro vocabolario correggerli "l'implementazione richiede un tempo quadratico, ma possiamo farlo scendere a n-log-n facendolo in questo modo invece "naturalmente e automaticamente come useremmo la lingua inglese per ordinare una pizza.

3
Ken Bloom

Si

Potrebbe non essere necessario eseguire analisi formali, ma almeno una comprensione dell'intestino della complessità dell'algoritmo - e di come confrontare due algoritmi attorno a ciò - è fondamentale se si desidera svolgere un lavoro non banale e farlo funzionare bene.

Ho lavorato su due diversi sistemi che sembravano a posto nei primi sviluppi, ma ho messo in ginocchio l'hardware nei test di produzione, perché qualcuno ha usato un algoritmo O (n ^ 2). E in entrambi i casi, la correzione è stata una banale modifica in un algoritmo O(n).

3
Bob Murphy

Probabilmente viene utilizzato in luoghi in cui stanno sviluppando API per il consumo. Il C++ STL è una delle poche API a cui sono stati imposti limiti di complessità sui suoi algoritmi. Ma per il programmatore di lavoro quotidiano/programmatore senior/designer/architetto non passa molto per la testa.

1
sashang

Non l'ho trovato così importante se non per comunicare idee, e lavoro in settori critici per le prestazioni (raytracing, elaborazione di immagini e mesh, sistemi di particelle, motori fisici, ecc.) E ho dovuto ideare molti algoritmi e strutture dati proprietari quando si lavora in R&S. In queste aree, spesso una manciata di strutture dati e algoritmi molto efficienti possono produrre prodotti completamente nuovi e all'avanguardia mentre gli algoritmi di ieri rendono obsoleti i prodotti esistenti, quindi c'è sempre la ricerca di fare le cose in modo più efficiente. Come avvertimento, non ho mai pubblicato articoli sugli algoritmi che ho ideato. Erano tutti proprietari. Se lo facessi, avrei bisogno dell'aiuto di un matematico per formulare prove e così via.

Tuttavia, a mio avviso, la quantità di lavoro computazionale per iterazione è spesso di interesse più immediato della scalabilità dell'algoritmo, a meno che l'algoritmo non si ridimensioni davvero male. Se qualcuno presenta una tecnica all'avanguardia per il raytracing, sono più interessato alle tecniche computazionali come il modo in cui rappresentano e accedono ai dati piuttosto che alla complessità algoritmica perché in questo scenario competitivo e innovativo è già data una ragionevole scalabilità. Non puoi essere competitivo inventando algoritmi che non si adattano.

Naturalmente, se stai confrontando la complessità quadratica con linearitmica, questa è una differenza enorme. Ma la maggior parte delle persone nel mio campo sono abbastanza competenti da evitare di applicare un algoritmo di complessità quadratica su un input epico. Quindi la scalabilità è spesso profondamente implicita e le domande più significative e interessanti diventano simili, "Hai usato GPGPU? SIMD? Funziona in parallelo? Come hai rappresentato i dati? Hai riorganizzato per la cache-friendly schemi di accesso? Quanta memoria è necessaria? Può gestire in modo efficace questo caso? Stai rinviando determinati processi o esegui tutto in una volta? "

Anche un algoritmo linearitmico può sovraperformare un algoritmo a tempo lineare se il primo accede alla memoria in un modello più ottimale, ad esempio, o è più adatto per il multithreading e/o SIMD. A volte anche un algoritmo lineare può sovraperformare un algoritmo logaritmico per questi motivi, e gli algoritmi a tempo lineare naturalmente superano quelli logaritmici per gli input di adolescenti.

Quindi per me ciò che conta di più sono quelle che alcune persone potrebbero chiamare "microottimizzazioni", come rappresentazioni di dati (layout di memoria, schemi di accesso con suddivisione del campo caldo/freddo, ecc.), Multithreading, SIMD e occasionalmente GPGPU. In un campo in cui tutti sono già abbastanza competenti da utilizzare algoritmi decenti e all'avanguardia per tutto, con nuovi articoli pubblicati continuamente, il tuo vantaggio competitivo nel battere i maghi algoritmici non proviene da miglioramenti della complessità algoritmica tanto quanto più diretto efficienza computazionale.

Il mio campo è dominato da matematici brillanti, ma non sempre quelli che conoscono il costo computazionale di ciò che stanno facendo o molti trucchi di livello inferiore per accelerare il codice. Di solito è il mio vantaggio su di loro nell'elaborare algoritmi e strutture dati più veloci e più stretti, nonostante il mio sia molto meno sofisticato. Sto giocando a ciò che piace all'hardware, verso bit e byte e rendendo ogni iterazione di lavoro molto più economica anche se sto facendo alcune iterazioni di lavoro in più rispetto all'algoritmo davvero sofisticato - il lavoro nel mio caso è drasticamente più economico. Anche il codice che scrivo tende ad essere molto più semplice. Se le persone pensano che le versioni micro-ottimizzate di algoritmi e strutture di dati semplici siano difficili da capire e mantenere, prova a capire e mantenere una raccolta di algoritmi e strutture di dati esotici correlati a mesh mai visti prima nel settore con articoli di 20 pagine che descrivono matematicamente i loro passi .

Come esempio di base, ho trovato una semplice struttura a griglia che ha finito per sovraperformare un albero KD presso la nostra azienda per il rilevamento delle collisioni e la rimozione di punti ridondanti. La mia stupida griglia grezza era molto meno sofisticata da un punto di vista algoritmico e sono molto più stupida dal punto di vista matematico e algoritmico rispetto al ragazzo che ha implementato l'albero KD con il suo nuovo modo di trovare il punto mediano, ma ho appena sintonizzato l'utilizzo della memoria della griglia e i modelli di accesso e è bastato a superare qualcosa di molto più sofisticato.

Un altro vantaggio che ho che mi permette di sopravvivere in un campo dominato da persone molto più intelligenti di me è capire davvero come funziona l'utente, dal momento che utilizzo il software che sviluppo allo stesso modo. Questo mi dà idee per algoritmi che si allineano immediatamente con gli interessi degli utenti. Come esempio di base, la maggior parte delle persone cerca di accelerare cose come il rilevamento delle collisioni usando l'indicizzazione spaziale. Ho fatto una semplice osservazione di orientamento alla carriera quasi un paio di decenni fa per modelli organici che, ad esempio, se un personaggio si mette le mani sul viso, una struttura di indicizzazione spaziale vorrebbe dover dividere i nodi e fare costosi aggiornamenti se il personaggio poi si tolse la mano dalla faccia. Se, invece, esegui la partizione in base ai dati di connettività anziché alle posizioni dei vertici, puoi ottenere una struttura gerarchica stabile che si aggiorna molto rapidamente e non ha mai bisogno di dividere o riequilibrare l'albero (deve solo aggiornare i riquadri di delimitazione di ogni fotogramma di animazione). .. cose del genere - algoritmi che un bambino senza un pesante background matematico potrebbe inventare se solo comprendessero il concetto di base, ma quelli che sfuggivano ai matematici poiché non pensavano alle cose in un modo così vicino a come gli utenti funzionava e pensava troppo alle proprietà della geometria e non al modo in cui la geometria veniva comunemente usata. Vado abbastanza d'accordo appoggiandomi più alla conoscenza computazionale generale e alla conoscenza dell'utente finale che alla magia algoritmica. Quindi, comunque, non ho trovato così importante concentrarmi sulla complessità algoritmica.

1
user204677

Non penso mai alla grande O in una prospettiva matematica, non penso mai alla grande O, a meno che non mi venga chiesto. Vedo solo un algoritmo nella mia testa e posso dire se è male perché fa più cicli attraverso la memoria per ogni N, o se si divide e conquista o qualcosa del genere. Se necessario, posso tradurlo in grande notazione O in pochi secondi, ma è più facile per me sapere come funziona l'algoritmo/contenitore con la memoria, piuttosto che pensare alla prospettiva matematica.

0
Coder

Sì, la complessità è importante nel settore. Se finisci per progettare qualcosa in cui un percorso critico si ridimensiona come N-quadrato (raddoppiando il numero di qualcosa rende il sistema quattro volte più carico), colpirai il collo di bottiglia del ridimensionamento molto più velocemente che se avessi qualcosa che si ridimensiona su N.

Tuttavia, di solito non viene fatto come una prova adeguata, formale, che qualcosa si trova in una data complessità, quindi avere una buona intuizione per quale complessità ha un modello di operazioni è un buon inizio.

0
Vatine