Linguagem de programação em que cada chamada / bloco de função é feita em um thread separado? [fechadas]


26

Atualmente, estou criando uma linguagem de programação por diversão, onde a ideia é que cada chamada de função / novo bloco (se cláusulas, loops etc.) funcionem em um thread separado. Em vez de criar novos Threads, o padrão deve ser o de fazer isso automaticamente e, se você quiser que ele seja executado no thread principal, precisará especificar isso.

Não sou tão informado sobre programação paralela multithread, mas sei o básico (Futuros, objetos seguros para threads). Portanto, eu estou querendo saber como essa linguagem poderia parecer sintaxe sábia e se é mesmo possível começar? O objetivo não é torná-lo "útil", é mais pela diversão e por uma experiência de aprendizado.

(Desculpe se este é o lugar errado para postar. Se assim for, eu ficaria feliz em me indicar o lugar certo onde uma pergunta como a minha é permitida.)


17
Criar threads é simples. O truque do multi-threading é quando eles precisam conversar entre si ou trabalhar com os mesmos recursos. Em outras palavras, não é o garfo que é difícil, são as uniões. O principal problema que você precisa resolver é como você controla isso.
JimmyJames 28/02

20
Na IMO, você não pode fazer isso sem esticar seriamente a definição usual da palavra "função" ou da palavra "segmento". Você pode querer ler sobre os atores se ainda não os conhece: en.wikipedia.org/wiki/Actor_model
Solomon Slow

9
Tenha uma granulação suficiente e você verá que as CPUs já paralelizam as instruções automaticamente, sem sobrecarregar o desenvolvedor de software. Consulte Execução fora de ordem e processador superescalar .
8bittree

8
Isso realmente soa meio horrível. Eu ia explicar o porquê, mas Karl Bielefeldt já sabia.
Mason Wheeler

1
Que tipo de paradigma você deseja apoiar no seu idioma? Deveria ser imperativo ou funcional? Você está dizendo que todas as instruções seriam executadas ao mesmo tempo - os blocos then / else e o que vem depois deles?
Bergi

Respostas:


39

toda chamada de função / novo bloco (se cláusulas, loops etc.) funcionará em um thread separado.

Leia muito mais sobre continuações e estilo de passagem de continuação (e sua relação com threads ou corotinas). Sugiro ler SICP & Lisp In Small Pieces . Além disso, a Pragmática da Linguagem de Programação fornece uma visão geral útil de várias linguagens e ajudaria você a criar sua própria.

Portanto, eu estou querendo saber como essa linguagem poderia parecer sintaxe sábia

A sintaxe não importa muito para explorar idéias . A semântica importa muito mais. Sugiro que você adote alguma sintaxe do tipo S-expr (para que você possa criar um protótipo usando o Scheme e sua chamada / cc ) primeiro.

Depois que suas idéias ficarem mais claras (após algumas experiências), você poderá discuti-las sobre lambda-the-ultimate , definir uma sintaxe mais sexy (o que realmente importa se você deseja que as pessoas adotem seu idioma, e o que também importa é a qualidade de implementação, uma amostra de software livre, a documentação, a biblioteca padrão, a interface de função externa etc.)


25
+1 para mencionar por que a sintaxe é irrelevante. Outro +1 se eu pudesse explicar por que a sintaxe é altamente importante.
Jörg W Mittag 28/02

Boa sugestão, mas para discutir coisas no LtU, você deseja uma conta e não é trivial obter uma da minha experiência.
Mael

1
Você deve usar um conjunto de encadeamentos para reduzir a sobrecarga. en.wikipedia.org/wiki/Thread_pool
shawnhcorey

37

Você pode estar interessado em ler sobre a pesquisa em dados paralelos Haskell . Se você pesquisar no youtube, Simon Peyton Jones também deu algumas palestras interessantes sobre o assunto.

Se bem me lembro de suas palestras, em pura programação funcional, é quase trivial encontrar oportunidades para criar threads. Seu principal problema em sua pesquisa é ter muitos que têm vida curta, de modo que a sobrecarga de criar threads e comunicar seus resultados supera essencialmente os benefícios do paralelismo. Por exemplo, é fácil ensinar um compilador a girar 100 threads para calcular sum $ fmap (+1) <100 length vector>, mas será que a sobrecarga fará valer a pena?

O truque é consolidar threads em tamanhos benéficos, sem impor um ônus ao programador para denotar isso manualmente. É um problema difícil que precisa ser resolvido para usar efetivamente futuros PCs com milhares de núcleos.


8
Eu já ficaria feliz em trabalhar com um PC à moda antiga, com apenas centenas de núcleos ...
Hagen von Eitzen

8
Eu gostaria de destacar que, para projetos com paralelo de dados, já realizamos muita paralelização com muita eficiência: as GPUs são essencialmente máquinas de núcleo 200-1000 (elas têm sua própria hierarquia de memória).
Delioth 28/02

4
@HagenvonEitzen: O JCA Azul Vega (Java Compute Appliance) tinha 16 CPUs com 54 núcleos cada, totalizando 864 núcleos, e não era uma máquina de protótipo ou nível de pesquisa, mas um produto real. Também não preencheu um edifício inteiro ou mesmo uma sala inteira, era um aparelho do tamanho de uma mesa. E estava disponível há 9 anos. As GPUs já foram mencionadas, porém, essa era uma máquina com 864 núcleos de CPU de uso geral .
Jörg W Mittag 28/02

3
Claro, há uma razão pela qual nós não temos hoje os maciça da GPU dados em paralelo, mas não aqueles maciça CPU multi-core é para desktops. Os primeiros são comercialmente viáveis, os últimos não, e isso é porque você não pode programá-los com eficiência.
#

@MSalters talvez precisemos apenas de um número infinito de macacos? Ou, programas Quantum que simplesmente executam todas as operações possíveis a cada etapa?

15

É exatamente isso que Erlang faz. Ele lida com a junção dos threads principalmente usando filas. É um conceito brilhante, mas um pouco difícil de entender inicialmente, se o seu plano de fundo for uma linguagem de tipo mais processual. Eu recomendo olhar para ele.


4

Primeiro, recomendo que você analise o PROMELA , uma linguagem usada para descrever um algoritmo simultâneo, para que um verificador de modelos possa fazer força bruta para forçar todas as execuções possíveis para verificar se é incapaz de comportamento incorreto. (A programação simultânea é notoriamente difícil de acertar, e é por isso que essas técnicas de verificação são importantes.) Ela não executa todas as construções em threads separados, mas possui sintaxe e semântica bastante estranhas, porque seu foco é o não determinismo de programas concorrentes.

Tornando-se mais abstrato, o π-cálculo é uma bela abordagem para modelar a computação paralela. É difícil entender o assunto, a menos que você compre o livro Sistemas móveis e de comunicação: o cálculo de Pi , de Robin Milner. Isso me ajudou a pensar em computação paralela em um sentido mais amplo que "vários threads acessando uma memória compartilhada". É bastante interessante como declarações condicionais, "gotos" e assim por diante podem ser construídas a partir de primitivas mais simples e naturalmente paralelas.

Com relação à sintaxe ... a melhor maneira de resolver isso é escrever alguns programas de amostra. Escreva um programa para classificar uma matriz ou, simultaneamente, faça ping em vários servidores e relate qual deles responde mais rapidamente, ou tente resolver um labirinto em paralelo, ou algo assim. Enquanto você faz isso, as coisas que estão faltando na sintaxe se tornam aparentes e você pode adicioná-las. Depois de adicionar várias coisas, pergunte-se se elas têm algo em comum e, se houver, talvez você encontre uma abordagem mais simples que possa servir a vários propósitos.


4

Projetos semelhantes foram tentados no passado. Sugiro ler os clássicos para saquear idéias. (Todos os links vão para Wikipedia)

  • Unidade Esta linguagem foi / é usada para ensinar programação paralela. Eu não acho que foi realmente implementado. A sintaxe é um pouco enigmática, mas basicamente você tem uma coleção de instruções executadas em ordem desconhecida e repetidamente até que não haja mais nada a ser feito. É o mais próximo do que você pede.

  • Occam Este idioma foi projetado para ser usado de verdade, mas nunca foi realmente utilizado. Aqui existe uma palavra-chave PAR, o que significa que uma lista de instruções deve ser executada em paralelo.

  • Erlang Outra língua do mundo real. Este é usado pela empresa de telecomunicações Ericsson e tem muitos seguidores. Eles trabalharam muito para tornar o paralelismo prático e utilizável.

  • Google GO Este é o meu favorito do grupo. Conceitualmente, da mesma forma que Erlang, mas com melhor sintaxe e o peso do Google por trás disso. O que possivelmente poderia dar errado?

Gostaria de encerrar com um aviso: é muito difícil acertar o paralelismo. A maioria dos erros nos programas modernos é o resultado de erros . Tem certeza de que deseja ir para lá?


Nenhuma ofensa destinada a qualquer idioma que não esteja na minha lista. É só que meu conhecimento é limitado.
Stig Hemmer #

3

É possível, mas não seria útil para mais de 99% de todos os aplicativos possíveis. A lógica é tipicamente associada à sequência, é um fluxo. Passo a passo, você chega a uma solução para um problema e a ordem das etapas é importante, principalmente porque a saída de uma etapa será inserida na próxima.

Nos poucos casos, você tem muitas tarefas que podem ser executadas independentemente uma da outra; geralmente é barato configurá-las sequencialmente antes de deixá-las executar em paralelo.

Então, acho que seria melhor gastar seu tempo aprendendo a usar os recursos de vários threads na sua linguagem de programação favorita.


5
Esta é uma excelente resposta para uma pergunta diferente; O OP não está perguntando sobre a sabedoria de tal esquema, mas apenas se isso pode ser feito e como seria a "sintaxe".
DepressedDaniel

9
Aqueles que não pedem precisam mais da minha sabedoria. Se alguém perguntar se é possível descer uma colina em um carrinho de compras, a melhor resposta não seria "Você pode apostar! Certifique-se de lubrificar as rodas!". Seria mais como "Bem, sim, mas ...".
Martin Maat

Lembra-me da antiga instrução de linguagem de montagem do EIAO - Executar em qualquer ordem . (E onde é que qualquer de qualquer maneira Key?)

@MartinMaat ninguém vai matar-se por escrito uma linguagem de programação para se divertir
user253751

2

Clojure pode valer a pena dar uma olhada em algumas idéias.

http://clojure-doc.org/articles/language/concurrency_and_parallelism.html

Aqui estão algumas considerações: Se chamarmos uma unidade de computação que pode ser executada independentemente, uma tarefa: 1. As tarefas são independentes, portanto, podem ser executadas simultaneamente 2. Tarefas diferentes requerem recursos diferentes e demoram tempos para serem executadas 3. Portanto, as tarefas devem ser agendadas para rendimento máximo 4. O único programa em posição de atuar como agendador é o sistema operacional

Coisas como o envio central de maçãs são uma tentativa de fornecer um agendador desse tipo.

O acima exposto significa que a responsabilidade de executar tarefas não é necessariamente a da linguagem de programação.

Um segundo pensamento é reduzir o peso da programação de sistemas paralelos, tanto quanto possível. A única maneira de fazer isso é remover qualquer especificação de como algo deve ser feito do programa. Um programa deve especificar apenas o que deve ser feito e o resto deve acontecer automaticamente.

O exposto acima provavelmente significa que linguagens dinâmicas e compilação just in time são o caminho a percorrer.


2

O que você procura é chamado paralelismo implícito, e há linguagens que exploraram esse conceito, como o Sun / Oracle's Fortress . Entre outras coisas, (potencialmente) executa loops em paralelo.

Infelizmente, foi descontinuado e há muitos links inativos por aí, mas você ainda pode encontrar alguns PDFs flutuando por aí, se pesquisar no Google o suficiente:

https://www.eecis.udel.edu/~cavazos/cisc879-spring2008/papers/fortress.pdf (a especificação do idioma)

http://stephane.ducasse.free.fr/Teaching/CoursAnnecy/0506-Master/ForPresentations/Fortress-PLDITutorialSlides9Jun2006.pdf

http://www.oracle.com/technetwork/systems/ts-5206-159453.pdf

http://dl.acm.org/citation.cfm?id=1122972 (paywalled)

É importante notar que você normalmente não deseja iniciar um encadeamento real para cada declaração / expressão, pois criar e iniciar encadeamentos costuma ser caro - em vez disso, você teria um conjunto de encadeamentos nos quais publica alguns trabalhos que precisam ser executados . Mas isso é um detalhe de implementação.


1
+1 por mencionar Fortress ... Gostei muito da ideia do idioma. Fiquei muito triste quando eles anunciaram que o desenvolvimento foi interrompido ...
Roland Tepp

2

Embora não seja uma linguagem de programação, você deve dar uma olhada no VHDL . É usado para descrever circuitos digitais, que naturalmente fazem tudo em paralelo, a menos que você diga especificamente para fazê-lo em série. Isso pode lhe dar algumas idéias sobre como projetar sua linguagem e para que tipo de lógica ela pode ser adequada.


0

Isso pode ser simulado facilmente em C ++. Apenas certifique-se de que "toda" chamada de função * seja implementada por a std::future. A manipulação do valor de retorno é feita simplesmente chamando .get()o futuro.

Portanto, você pode criar um protótipo de sua linguagem compilando em C ++. Isso também nos diz como seria a sintaxe: a principal diferença é que você separa o ponto de chamada (onde os argumentos de entrada são fornecidos) do ponto de retorno (onde a saída da função é usada).

(*) Eu digo "todas as funções", mas cabe a você o que conta como uma função. É memsetuma função intrínseca ou? A atribuição de números inteiros ou de tipos definidos pelo usuário é uma chamada de função?


E, se você adiar a resposta a uma pergunta por tempo suficiente, geralmente a necessidade de uma resposta desaparece. Eu acho que isso é chamado de "Lazy Existing".
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.