2012-01-31 20 views
7

Sto pensando di convertire un'applicazione C# in Haskell come il mio primo progetto "reale" Haskell. Tuttavia, voglio assicurarmi che sia un progetto sensato. L'app raccoglie pacchetti di dati da ~ 15 flussi seriali che arrivano a circa 1 kHz, carica quei valori nei corrispondenti buffer circolari sul mio oggetto "contesto", ognuno con ~ 25000 elementi, quindi a 60 Hz invia tali array a OpenGL per visualizzazione della forma d'onda. (Pertanto, ha da archiviare come array, o almeno convertito in un array ogni 16 ms). Ci sono anche circa 70 campi sul mio oggetto di contesto che mantengo solo il valore corrente (più recente), non la forma d'onda del flusso.È possibile creare velocemente grandi array di buffer circolari per la registrazione in streaming in Haskell?

Ci sono diversi aspetti di questo progetto che si adattano bene ad Haskell, ma la cosa di cui mi preoccupo è la performance. Se per ogni nuovo punto di dati in uno qualsiasi dei flussi, devo clonare l'intero oggetto di contesto con 70 campi e 15 matrici di 25000 elementi, ovviamente ci saranno problemi di prestazioni.

Vorrei aggirare questo mettendo tutto nell'IO-monade? Ma quello sembra in qualche modo sconfiggere lo scopo di usare Haskell, giusto? Anche tutto il mio codice in C# è guidato dagli eventi; c'è un idioma per questo in Haskell? Sembra che aggiungere un ascoltatore crei un "effetto collaterale" e non sono sicuro di come esattamente ciò sarebbe stato fatto.

risposta

5

Sì, probabilmente si desidera utilizzare il monad IO per dati mutabili. Non credo che il monad ST sia adatto per questo spazio problema perché gli aggiornamenti dei dati sono intercalati con azioni IO effettive (lettura flussi di input). Poiché è necessario eseguire l'IO in ST utilizzando unsafeIOToST, trovo preferibile utilizzare solo IO direttamente.L'altro approccio con ST è quello di scongelare e congelare continuamente un array; questo è disordinato perché è necessario garantire che le vecchie copie dei dati non vengano mai utilizzate.

Anche se evidence shows una soluzione pura (nel formato Data.Sequence.Seq) è spesso più veloce rispetto all'utilizzo di dati mutabili, dato il requisito che i dati vengano trasferiti a OpenGL, è possibile ottenere prestazioni migliori lavorando direttamente con l'array. Vorrei utilizzare le funzioni da Data.Vector.Storable.Mutable (dal pacchetto vettoriale), poiché in questo caso è possibile accedere allo ForeignPtr per l'esportazione.

È possibile osservare le frecce (Yampa) per un approccio molto comune al codice basato sugli eventi. Un'altra area è Functional Reactivity (FRP). Stanno iniziando ad essere alcune biblioteche ragionevolmente mature in questo dominio, come Netwire o banana reattiva. Non so se fornirebbero prestazioni adeguate alle tue esigenze; Li ho usati principalmente per la programmazione di tipo gui.

7

un'occhiata a questo link, nella sezione "La monade ST":

http://book.realworldhaskell.org/read/advanced-library-design-building-a-bloom-filter.html

Torna nella sezione “Modifica di elementi di array”, di cui abbiamo parlato che modifica una serie immutabile è proibitivo costoso, dato che lo richiede la copia dell'intero array. L'utilizzo di un UArray non cambia , quindi cosa possiamo fare per ridurre il costo a livelli accettabili?

In un linguaggio imperativo, dovremmo semplicemente modificare gli elementi dell'array in posizione; questo sarà il nostro approccio anche in Haskell.

Haskell fornisce una monade speciale, denominata ST, che ci consente di lavorare in modo sicuro con lo stato mutabile . Rispetto alla monade di stato, dispone di alcune potenti funzionalità aggiuntive .

Possiamo scongelare una matrice immutabile per fornire una matrice mutevole; modificare l'array mutabile in posizione; e congelare un nuovo array immutabile quando siamo fatti .

...

La monade IO fornisce anche queste capacità. La principale differenza tra i due è che la monade ST è intenzionalmente progettata in modo che possiamo fuggire da essa in puro codice Haskell.

Dunque dovrebbe essere possibile modificare sul posto, e non vanificare lo scopo di utilizzare Haskell dopo tutto.

Problemi correlati