O paradigma funcional não é muito divergente com o hardware subjacente para ser geralmente eficiente?

14

Inspirado por uma pergunta da SO: /programming/6623391/how-to-gain-control-of-a-5gb-heap-in-haskell

Pode ser um longo debate sobre as inúmeras vantagens e desvantagens do FP, mas, por enquanto, eu gostaria de limitar o escopo à eficiência principal do FP no hardware moderno.

Tese:

O paradigma funcional implica imutabilidade e apatridia (?), Mas o hardware em que executamos os programas funcionais são autômatos finitos com estado. A tradução do programa 'puro funcional' para uma representação de 'hardware com estado' deixa pouco controle para o programador, gera sobrecarga (?) E limita o uso dos recursos de hardware (?).

Estou certo ou errado nas declarações questionadas?

Pode-se provar que o FP implica / não implica as principais penalidades de desempenho na moderna arquitetura de computadores de uso geral?

EDIT: Como já afirmei em resposta a alguns comentários, a questão não é sobre desempenho e detalhes da implementação. Trata-se da presença ou ausência de sobrecarga principal , que a execução de FP em autômatos com estado pode trazer.

videiras
fonte
3
Você já olhou realmente como o hardware moderno funciona em um nível baixo? Se você se preocupa com eficiência, também não se assemelha à programação imperativa do dia-a-dia.
CA McCann
Acredite ou não, mas os cientistas da computação que criaram linguagens de programação e compiladores funcionais também sabem um pouco sobre como otimizar o desempenho. Esse não é o objetivo de todo produto de linguagem funcional, mas é para as plataformas de produção sérias.
Jeremy
@camccann, @Jeremy: C # e Java, por exemplo, usam máquinas virtuais. Não importa o quão ótima ela é, não importa o quão eficiente C programas Java # e são para a produção, não é um princípio fonte de ineficiência, e é a VM. A questão não é sobre desempenho de implementação, mas running FP on stateful automata.
21711 vines
1
veja a minha pergunta aqui- programmers.stackexchange.com/q/71391/963
Gulshan
2
@ videiras: Você percebe que VMs modernas com JITing sofisticado podem realmente superar o código nativo em alguns casos, certo? E que todo o objetivo de um compilador é converter um programa em uma representação correspondente à arquitetura subjacente, diferente de qualquer linguagem moderna? Sua pergunta não faz sentido.
CA McCann

Respostas:

7

Há um enorme mal-entendido na imutabilidade.

A imutabilidade é uma característica da semântica, mas não implica imutabilidade na implementação.

Um exemplo simples é a implementação da preguiça.

Quando os cálculos são preguiçosos, o resultado de uma expressão é conceitualmente um valor, mas a implementação subjacente é uma conversão que contém os argumentos a serem avaliados e uma função para criar o valor, além de um slot para armazenar o valor.

Na primeira vez em que você solicitar (no idioma) o valor, o cálculo será realmente realizado, o resultado avaliado e o valor devolvido a você (ou a um identificador).

Isso é transparente na semântica da linguagem, e tudo que você sabe é que essa variável foi vinculada a um valor (ou um valor futuro) e que, uma vez feito, você não pode alterar o valor que será retornado. A representação da memória subjacente será alterada, mas você não saberá.

A mesma diferença semântica / implementação existe em qualquer idioma e está de fato no coração da otimização . Qualquer que seja o idioma, a semântica garante algumas coisas, mas deixa outras não especificadas para deixar espaço para otimização.

Agora, é verdade que linguagens praticamente funcionais não são tão rápidas quanto C ++, por exemplo. No entanto, Go(que ainda é o hype) é mais lento que o Haskell ou o Lisp, e também o C # Mono ( fonte ).

Quando você perceber como o C ++ ou C não é confiável para obter essas performances, convém deixar um pouco de lado.

Quando você perceber que Haskell está crescendo rapidamente hoje, e ainda há muito espaço para otimização em seu compilador / tempo de execução (o GHC acabou de mudar recentemente para o LLVM, por exemplo, a Microsoft Research está financiando ativamente as melhorias de tempo de execução), você pode apostar que vai melhorar em breve.

Diversão: uma brincadeira com expressões regulares ou como uma equipe da Haskell criou um comparador de expressões regulares que supera re2a biblioteca C do Google em vários cenários.

Matthieu M.
fonte
Soa otimista :)
vines
3

O paradigma funcional é útil para dividir as coisas em um escopo estreito. Isso é realmente bom, considerando como o computador evolui.

A CPU multicore tem grandes problemas ao lidar com recursos compartilhados e o custo de sincronização é realmente exagerado. O paradigma funcional permite uma maneira natural de expressar programas que não têm esses problemas. Isso é realmente bom para o paralelismo.

Além disso, estamos usando farms de servidores cada vez mais com SaaS e computação em nuvem. Portanto, o mesmo aplicativo deve ser executado em várias máquinas. Nesta posição, os custos de sincronização são ainda mais caros. O Google fez algum trabalho e publicou alguns trabalhos de pesquisa sobre programação funcional e algoritmo nos quais você pode escrever. Isso é fundamental para eles, porque eles têm um problema de escabilidade.

Além disso, você pode facilmente fazer uma pilha na pilha do computador e até mesmo uma pilha não contínua usando listas vinculadas. Isso já é feito para gerar rastreamento de pilha em muitas linguagens de programação. Portanto, isso não é um problema.

OK, a programação funcional implica algumas limitações. Mas também traz uma maneira natural de expressar problemas que temos na informática moderna, que são extremamente difíceis de lidar em paradigmas com os quais estamos acostumados. A escalabilidade é uma delas e está se tornando um negócio real.

Todo mundo que já lida com um complexo sistema paralelo sabe do que estou falando.

Então, eu matiz a resposta. Sim, o funcional tem problemas com o hardware moderno, mas a programação antiga simples também tem alguns. Como sempre, você encontrará vantagens e desvantagens. O ponto é saber o que são, para que você possa fazer a escolha apropriada quando precisar.

deadalnix
fonte
0

Eu realmente não tenho uma resposta, pois não sei o estado atual ou mesmo o quão difícil seria, mas apenas porque o compilador garantiria essas coisas a partir da entrada, não significa necessariamente que a saída as teria . Em teoria, um compilador suficientemente inteligente poderia passar por todos esses problemas, mas, na prática, provavelmente sempre existirá.

No entanto, outra maneira de ver isso é ver a história da máquina Lisp. Se bem me lembro, eles foram originalmente projetados para superar os mesmos problemas que Lisp teve com a diferença das máquinas da época. O desenvolvimento dessas máquinas acabou sendo interrompido, pois a área de trabalho se tornou rápida o suficiente para tornar as ineficiências mais baratas de se viver do que suportar outra máquina.

Geralmente, exceto para a aplicação mais crítica em termos de desempenho, as linguagens FP ainda são rápidas o suficiente. Se escolher qualquer idioma de nível superior, você estará disposto a diminuir a prioridade no controle e no desempenho da sintonia fina para obter uma segurança mais fácil, mais fácil, mais sustentável ou outra prioridade.

No final, a programação tem tudo a ver com trade-offs; portanto, basta escolher o que importa mais para o projeto em questão.

tylermac
fonte
0

É verdade que o paradigma funcional implica imutabilidade e apatridia, mas não temos nenhuma linguagem de programação completamente pura. Até o mais puro, Haskell, permite efeitos colaterais.

Dito isso, para responder sua pergunta sobre eficiência, usei Haskell e Clojure e também não notei nenhum problema de desempenho.

Larry Coleman
fonte
1
Os problemas são relativos aos requisitos ... E as áreas críticas de desempenho? Alto paralelismo é valioso lá, mas qual é a pontuação geral?
videiras
1
@ videiras: Eu não usei nenhum idioma para um aplicativo crítico de desempenho, por isso não posso falar sobre isso.
Larry Coleman
1
Não é muito divertido, sem efeitos colaterais, pois você não seria capaz de salvar o resultado em nenhum lugar.
@ Thorbjørn Ravn Andersen: ... de uma maneira diferente de devolvê-lo ao chamador, o que é permitido.
videiras