20% di penalità sulle prestazioni per un piacevole design del software


17

Sto scrivendo una piccola libreria per calcoli con matrici sparse come un modo per insegnarmi a sfruttare al meglio la programmazione orientata agli oggetti. Ho lavorato molto duramente per avere un bel modello a oggetti, in cui le parti (matrici sparse e grafici che descrivono la loro struttura di connettività) sono accoppiati in modo molto approssimativo. A mio avviso, il codice è molto più estensibile e gestibile per questo.

Tuttavia, è anche un po 'più lento di se avessi usato un approccio schietto. Al fine di testare i compromessi di avere questo modello a oggetti, ho scritto un nuovo tipo di matrice sparsa che ha rotto l'incapsulamento del grafico sottostante per vedere quanto più veloce sarebbe eseguito.

All'inizio sembrava piuttosto desolante; il codice di cui ero orgoglioso una volta era più lento del 60% rispetto a una versione senza un elegante design del software. Ma sono stato in grado di apportare alcune ottimizzazioni di basso livello - incorporando una funzione e modificando un loop un po '- senza modificare l'API. Con questi cambiamenti, ora è solo il 20% più lento rispetto alla concorrenza.

Il che mi porta alla mia domanda: quanta perdita di prestazione dovrei accettare se ciò significa che ho un bel modello a oggetti?


Quale operazione di matrice sparsa stavi misurando?
Bill Barth,

Moltiplicazione matrice-vettore. Le matrici variava nel formato da . Li ho resi il grafico Laplaciani per i grafici casuali Erdos-Renyi con grado medio d = log 2 n . Inoltre, la cifra del 20% peggiora su alcune macchine, quindi ora sono più propenso a buttare via tutto. Sospiro profondon=1024,...,16384d=log2n
Daniel Shapero,

3
Quale linguaggio di programmazione stai usando? In genere qualcosa come C ++ ti permetterà di cavartela con design eleganti (ish) a un costo basso (o inesistente). In altre lingue senza meta-programmazione (Java, Fortran, ecc.) Un costo del 20% sembra ragionevole.
LKlevin,

Puoi mostrarci il tuo codice? Che lingua hai usato? Quali flag di compilatore e compilation? Hai trovato esattamente da dove proviene il successo? Come ti sei assicurato di aver trovato il motivo giusto? Quale profiler hai usato e come l'hai usato? Sei sicuro che il simpatico modello a oggetti non sia implementato in modo inefficiente? Il 20% è abbastanza piccolo da dover raccogliere molti dati e avere un'analisi dettagliata prima di dire che è sicuramente dovuto alla progettazione, piuttosto che, per esempio, all'implementazione inferiore o ad altri problemi di codifica.
Kirill,

Breve nota a margine: tutti sembrano lodare pubblicamente il buon design per le prestazioni pure (con motivi molto validi, ovviamente). Ma allora, perché così tanto codice del mondo reale è davvero, davvero irraggiungibile? Tutti gli slogan del codice si sentono in colpa e quindi silenziosamente pubblici?
AlexE,

Risposte:


9

Pochissimi sviluppatori di software scientifici comprendono buoni principi di progettazione, quindi mi scuso se questa risposta è un po 'prolissa. Dal punto di vista dell'ingegneria del software, l'obiettivo dello sviluppatore di software scientifico è progettare una soluzione che soddisfi una serie di vincoli che sono spesso in conflitto .

Ecco alcuni esempi tipici di questi vincoli, che potrebbero essere applicati al design della tua libreria di matrici sparse:

  • Completato in un mese
  • Funziona correttamente sul tuo laptop e su diverse workstation
  • Funziona in modo efficiente

Gli scienziati stanno gradualmente prestando maggiore attenzione ad alcuni altri requisiti comuni dell'ingegneria del software:

  • Documentazione (guida per l'utente, tutorial, commenti sul codice)
  • Manutenibilità (controllo versione, test, design modulare)
  • Riutilizzabilità (design modulare, "flessibilità")

Potrebbe essere necessario più o meno uno di questi requisiti. Se stai cercando di vincere un premio Gordon Bell per la performance, anche le frazioni di un percento sono rilevanti e pochi giudici valuteranno la qualità del tuo codice (purché tu possa convincerli che è giusto). Se stai cercando di giustificare l'esecuzione di questo codice su una risorsa condivisa come un cluster o un supercomputer, spesso devi difendere le affermazioni sulle prestazioni del tuo codice, ma raramente sono molto stringenti. Se stai cercando di pubblicare un articolo su un giornale che descrive i miglioramenti delle prestazioni del tuo approccio, allora devi essere legittimamente più veloce dei tuoi concorrenti e il 20% delle prestazioni è un compromesso che farei volentieri per una migliore manutenibilità e riusabilità.

Tornando alla tua domanda, il "buon design", concesso abbastanza tempo di sviluppo, non dovrebbe mai sacrificare le prestazioni. Se l'obiettivo è rendere il codice più veloce possibile, allora il codice dovrebbe essere progettato attorno a tali vincoli. È possibile utilizzare tecniche come la generazione di codice, l'assemblaggio in linea o trarre vantaggio da librerie altamente ottimizzate per la risoluzione del problema.

E se non avessi abbastanza tempo di sviluppo? Cosa c'è di abbastanza buono? Bene, dipende, e nessuno sarà in grado di darti una buona risposta a questa domanda senza più contesto.

FWIW: Se sei veramente interessato a scrivere kernel a matrice sparsa ad alte prestazioni, dovresti confrontarti con un'installazione PETSc ottimizzata e lavorare con il loro team se li stai battendo, sarebbero felici di incorporare i kernel sintonizzati nella libreria.


Sono curioso dei generatori di codice - penso che potrebbero essermi utili, ma temo che saranno difficili da mantenere. So che i programmatori Java li usano molto, ma sono spesso personalizzati per generare codice per applicazioni specifiche. Conosci qualche codice scientifico che li utilizza?
Daniel Shapero,

ATLAS, FFTW, Spiral, OSKI, Ignition, stencil_codegen, per citarne alcuni. Non è pubblicizzato pubblicamente, ma non sarei sorpreso se molti dei kernel importanti in MKL ed ESSL vengono generati in questo modo. Scrivere un codice di generazione del kernel gestibile sarebbe un'interessante domanda di follow-up. Ho esperienza in questo, ma non mi considero un'autorità.
Aron Ahmadia,

12

È una domanda su cosa passi il tuo tempo. Per la maggior parte di noi, impieghiamo 3/4 del tempo a programmare e 1/4 del tempo in attesa di risultati. (I tuoi numeri possono variare, ma penso che il numero non sia completamente privo di merito.) Quindi, se hai un design che ti ha permesso di programmare due volte più velocemente (3/4 di un'unità di tempo anziché 1,5 unità di tempo), allora tu può subire un colpo del 300% in termini di prestazioni (da 1/4 a 1 unità di tempo) e si ottiene comunque un vantaggio in termini di tempo reale impiegato per risolvere il problema.

D'altra parte, se stai eseguendo calcoli pesanti, i tuoi calcoli potrebbero apparire in modo diverso e potresti voler dedicare più tempo a ottimizzare il tuo codice.

Per me, il 20% sembra un compromesso abbastanza buono se finisci per essere più produttivo.


Buona risposta, aggiungerei anche l'importanza per le prestazioni. Un dato codice scientifico non sta facendo solo la moltiplicazione di matrici; se il 20% del tuo tempo di esecuzione è in moltiplicazione di matrici, un aumento delle prestazioni del 20% vi è solo una differenza del 4% nel complesso, e lo prenderei volentieri in cambio di una libreria più facile da usare.
Aurelio l'

1
E una libreria scritta migliore significa meno bug, in modo da perdere meno tempo in attesa di risultati errati.
Davidmh,

4

IMHO una penalità fino al 50% (per qualsiasi motivo) non è poi così male.

In effetti ho visto una differenza dello 0-30% nelle prestazioni solo in base al tipo di compilatore. Questo è per la rara routine MatMult di PETSc sulle matrici derivanti da discretizzazioni FE di basso ordine.


1

Il design del software non migliorerà automagicamente nel tempo. Lo spettacolo lo farà. Otterrai il 20% di sconto con la tua prossima CPU. Inoltre, una buona progettazione del software renderà più semplice estendere o migliorare la libreria in futuro.


Non credo che questo risponda alla domanda.
Nicoguaro

0

Un principio generale è quello di cercare prima un buon design e poi ottimizzare le prestazioni solo se necessario . I casi d'uso in cui è realmente necessario un aumento delle prestazioni del 20% sono probabilmente rari, se si presentano affatto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.