Il paradigma funzionale non è troppo divergente con l'hardware sottostante per essere generalmente efficiente?


14

Ispirato da una domanda di SO: /programming/6623391/how-to-gain-control-of-a-5gb-heap-in-haskell

Può essere un lungo dibattito sui numerosi vantaggi e svantaggi di FP, ma per ora, vorrei restringere l'ambito alla principale efficienza di FP su hardware moderno.

Tesi:

Il paradigma funzionale implica immutabilità e apolidia (?), Ma l'hardware su cui eseguiamo programmi funzionali è automi finiti con stato. La traduzione di un programma 'puro funzionale' in una rappresentazione 'hardware con stato' lascia poco controllo al programmatore, porta il sovraccarico (?) E limita l'uso delle capacità hardware (?).

Ho ragione o torto nelle dichiarazioni in discussione?

Si può dimostrare che FP implica / non implica le principali penalità di prestazione sulla moderna architettura informatica per uso generale?

EDIT: come ho già affermato in risposta ad alcuni commenti, la domanda non riguarda le prestazioni e i dettagli dell'implementazione. Riguarda la presenza o l'assenza del sovraccarico principale , che può portare l'esecuzione di FP su automi con stato.


3
Hai mai davvero visto come funziona l'hardware moderno a basso livello? Se ti interessa l'efficienza, non assomiglia nemmeno alla programmazione imperativa di tutti i giorni.
CA McCann,

Che ci crediate o no, ma gli informatici che hanno progettato linguaggi di programmazione funzionale e compilatori sanno anche un po 'di ottimizzazione per le prestazioni. Questo non è l'obiettivo di ogni prodotto di linguaggio funzionale, ma è per le piattaforme di produzione serie.
Jeremy,

@camccann, @Jeremy: C # e Java, ad esempio, usano macchine virtuali. Non importa quanto sia ottimale sia, non importa quanto sia efficace C # e programmi Java sono per la produzione, non v'è un principio fonte di inefficienza, ed è la VM. La domanda non riguarda le prestazioni di implementazione, ma running FP on stateful automata.
viti


2
@vines: ti rendi conto che le macchine virtuali moderne con fantasia JITing possono effettivamente superare il codice nativo in alcuni casi, giusto? E che lo scopo di un compilatore è convertire un programma in una rappresentazione che corrisponda all'architettura sottostante, che è diversa da qualsiasi linguaggio moderno? La tua domanda non ha alcun senso.
CA McCann,

Risposte:


7

C'è un grande fraintendimento nell'immutabilità.

L'immutabilità è una caratteristica della semantica, ma non implica l'immutabilità nell'attuazione.

Un semplice esempio è l'implementazione della pigrizia.

Quando i calcoli sono pigri, il risultato di un'espressione è concettualmente un valore, ma l'implementazione sottostante è un thunk che contiene gli argomenti da valutare e una funzione per creare il valore, nonché uno slot in cui archiviare il valore.

La prima volta che chiederai (nella lingua) il valore, il calcolo verrà effettivamente eseguito, il suo risultato sarà valutato e il valore che ti verrà restituito (o un handle).

Questo è trasparente nella semantica del linguaggio e tutto ciò che sai è che questa variabile è stata associata a un valore (o un valore futuro) e che una volta fatto non puoi cambiare il valore che verrà restituito. La rappresentazione della memoria sottostante cambierà, ma non lo saprai.

La stessa differenza semantica / di implementazione esiste in qualsiasi lingua ed è in effetti al centro dell'ottimizzazione . Qualunque sia la lingua, la semantica garantisce alcune cose, ma lascia altri non specificati per lasciare spazio all'ottimizzazione.

Ora, è vero che i linguaggi praticamente funzionali non sono veloci come il C ++, per esempio. Tuttavia, Go(che è ancora abbastanza il clamore) è più lento di Haskell o Lisp, e così è C # Mono ( fonte ).

Quando vedi quanto C ++ o C possano essere inaffidabili per ottenere quelle esibizioni, potresti voler lasciar perdere un po '.

Quando ti rendi conto che Haskell sta crescendo rapidamente oggi e c'è ancora molto spazio per l'ottimizzazione nel suo compilatore / runtime (GHC è passato di recente a LLVM, ad esempio, Microsoft Research sta finanziando attivamente i miglioramenti del runtime), potresti essere disposto a scommettere che migliorerà presto.

Divertimento: A Play on Regular Expressions o in che modo un team Haskell ha creato un matcher di espressioni regolari che supera re2la libreria C di Google in diversi scenari.


Sembra ottimista :)
viti

3

Il paradigma funzionale è utile per dividere le cose in un ambito ristretto. Questa è davvero una buona cosa considerando l'evoluzione del computer.

Le CPU multicore hanno grossi problemi nella gestione delle risorse condivise e i costi di sincronizzazione sono davvero onerosi. Il paradigma funzionale consente un modo naturale di esprimere programmi che non presentano questi problemi. Questo è davvero buono per il parallelismo.

Inoltre, stiamo utilizzando sempre più server farm con SaaS e cloud computing. Pertanto, la stessa applicazione deve essere eseguita su più macchine. In questa posizione, i costi di sincronizzazione sono ancora più costosi. Google ha svolto alcuni lavori e pubblicato alcuni articoli di ricerca sulla programmazione funzionale e sugli algoritmi in cui puoi scrivere. Questa è una cosa fondamentale per loro perché hanno un problema di scallability.

Inoltre, puoi facilmente fare uno stack nell'heap del computer e persino uno non continuo usando gli elenchi collegati. Questo è già fatto per generare la traccia dello stack in molti linguaggi di programmazione. Quindi questo non è un problema.

OK, la programmazione funzionale implica alcune limitazioni. Ma offre anche un modo naturale per esprimere le problematiche che abbiamo nell'informatica moderna, che sono estremamente difficili da gestire nei paradigmi a cui sono abituati. La scalabilità è una di queste e sta diventando un vero affare.

Tutti quelli che hanno già a che fare con un sistema parallelo complesso sanno di cosa sto parlando.

Quindi vorrei sfumare la risposta. Sì, funzionale ha problemi con l'hardware moderno, ma anche la semplice vecchia programmazione ne ha. Come sempre, troverai vantaggi e svantaggi. Il punto è sapere quali sono in modo da poter fare la scelta appropriata quando è necessario.


0

Non ho davvero una risposta, poiché non conosco lo stato attuale o nemmeno quanto sia difficile, ma solo perché il compilatore garantirebbe tali elementi dall'input, non significa necessariamente che l'output li avrebbe . In teoria, un compilatore sufficientemente intelligente potrebbe superare tutti questi problemi, ma in pratica probabilmente esisterà sempre.

Tuttavia, un altro modo di vederlo è quello di guardare alla storia della macchina Lisp. Se ricordo bene, erano stati originariamente progettati per superare gli stessi problemi che Lisp aveva con la sua differenza rispetto alle macchine in quel momento. Lo sviluppo di queste macchine alla fine si interruppe, poiché il desktop divenne abbastanza veloce da rendere le inefficienze più economiche con cui convivere che supportare un'altra macchina.

In generale, ad eccezione dell'applicazione più critica in termini di prestazioni, i linguaggi FP sono ancora abbastanza veloci. Scegliendo qualsiasi lingua di livello superiore, sarai disposto a ridurre la priorità sul controllo e sulle prestazioni della messa a punto per una più sicura, più facile, più gestibile o un'altra priorità.

Alla fine, la programmazione è incentrata sui compromessi, quindi è sufficiente scegliere ciò che conta di più per il progetto in corso.


0

È vero che il paradigma funzionale implica immutabilità e apolidia, ma non abbiamo linguaggi di programmazione completamente puri. Anche il più puro, Haskell, consente effetti collaterali.

Detto questo, per rispondere alla tua domanda sull'efficienza, ho usato sia Haskell che Clojure e non ho notato alcun problema di prestazioni con entrambi.


1
I problemi sono relativi ai requisiti ... E le aree critiche per le prestazioni? Un alto parallelismo è prezioso lì, ma qual è il punteggio complessivo?
viti

1
@vines: non ho usato nessuno dei due linguaggi per un'applicazione critica per le prestazioni, quindi non posso davvero parlarne.
Larry Coleman,

1
Non molto divertente senza effetti collaterali, in quanto non si sarebbe in grado di salvare il risultato da nessuna parte.

@ Thorbjørn Ravn Andersen: ... in un modo diverso da restituirlo al chiamante, che è permesso.
viti
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.