Linguagem de desenvolvimento de software de computação científica paralela?

18

Eu quero desenvolver um software de computação científica paralelo do zero. Eu quero alguns pensamentos sobre qual idioma começar. O programa envolve ler / gravar dados em arquivos txt e realizar cálculos pesados ​​em paralelo, com muitas fatorações de LU e o uso de solucionadores lineares esparsos. As soluções candidatas que eu estava pensando são Fortran 2003/2008 com OpenMP ou co-array, C ++ com openmp cilk + ou TBB, python. Quaisquer outras sugestões documentadas são bem-vindas! Eu sei muito bem C, Fortran e Java (nessa ordem). Eu fiz alguns scripts em python, mas coisas básicas.

Eu sei que o fortran é muito rápido, mas difícil de manter e paralelizar. Diz-se que C ++ é lento, a menos que você use bibliotecas externas, etc. Eu gosto de Python, mas é realista escrever um software em escala industrial em escala completa?

O software precisa ser capaz de lidar com grandes quantidades de dados e ser eficaz com cálculos científicos. O desempenho é essencial.

Como pano de fundo, eu já tenho um software de trabalho escrito em Fortran. Muitas pessoas estiveram envolvidas no desenvolvimento ao longo de muitos anos e o código está realmente sujo. Manter e paralelizar o código provou ser um pesadelo e estou pensando em alternativas.

Petros

electrique
fonte
5
Como um especialista em C ++, eu não consideraria o Fortran difícil de manter. A capacidade de manutenção está ligada às boas práticas, em grande parte, não à escolha do idioma. A lentidão do C ++ está sobrevendida. Além disso, eu recomendo que você aumente esta postagem para descrever seus requisitos de tamanho de dados e tempo de resposta. Eu já vi "grande" variar em 9 ou 10 ordens de magnitude, dependendo de com quem estou falando.
Bill Barth
@ BillBarth O problema com o código Fortran existente é que três pessoas foram envolvidas usando práticas diferentes. Eu venho de um background C, um cara do background F77 e outro do Matlab. Os dados não são alocáveis ​​e dimensionados para o sistema de maior tamanho (eu estava envolvido recentemente). O código foi capaz de simular o sistema com 72000 equações diferenciais e 74000 algébricas em um horizonte de 240s em 350s (tempo decorrido). Reduzi isso para 170s usando o OpenMP para paralelizar. Agora eu preciso executar vários casos em paralelo (para varrer para verificação de segurança).
electrique
4
@BillBarth é modesto demais em vender suas habilidades em C ++, mas também é generoso em afirmar que a "lentidão do C ++ está exagerada". Houve um número de threads C ++ vs Fortran no scicomp.stackexchange.com que discutiram essa mesma questão e a conclusão geral foi que simplesmente não é verdade, pois o C ++ é mais lento que o Fortran em quase todos os casos. Pessoalmente, acho que hoje poderia ser considerado um mito urbano. O que é verdade é que, se você levar em conta a manutenção do código, o Fortran não se sairá muito bem hoje.
Wolfgang Bangerth
2
@BillBarth e outros, se você quiser continuar discutindo os méritos gerais do Fortran, C ++ e outros idiomas, leve-o à sala de bate-papo do scicomp e a qualquer pessoa que você queira abordar especificamente.
Aron Ahmadia 11/06/12
1
@AronAhmadia: ah, vamos lá, tenho muito a dizer para Jed ;-) (Jed: outra hora. No nosso caso, não há STL para matrizes esparsas, mas muito nas estruturas de dados de malha adaptativa.)
Wolfgang Bangerth

Respostas:

19

Deixe-me tentar detalhar seus requisitos:

  • Manutenção
  • Leitura / gravação de dados de texto
  • Interfaces / capacidade fortes para fatorações de LU
  • Solucionadores lineares esparsos
  • Desempenho e escalabilidade para grandes dados

Nesta lista, eu consideraria os seguintes idiomas:

C, C ++, Fortran, Python, MATLAB, Java

Julia é um novo idioma promissor, mas a comunidade ainda está se formando em torno dele e não foi implantada em nenhum dos principais códigos novos.

Leitura / gravação de dados de texto

É fácil acertar em qualquer linguagem de programação. Verifique se você está armazenando o buffer e coalescendo adequadamente seu acesso de E / S e obterá um bom desempenho de qualquer um dos idiomas que você deve considerar. Evite os objetos de fluxo no C ++, a menos que você saiba como usá-los com desempenho.

Interfaces / capacidade fortes para fatorações de LU

Se você estiver executando fatorações densas de LU, convém usar LAPACK ou ScaLAPACK / Elemental para funcionalidade paralela. LAPACK e ScaLAPACK são escritos em Fortran, Elemental é escrito em C ++. Todas as três bibliotecas têm desempenho, são bem suportadas e documentadas. Você pode fazer interface com eles a partir de qualquer um dos idiomas que você deve considerar.

Solucionadores lineares esparsos

Os principais solucionadores lineares esparsos disponíveis gratuitamente estão quase todos disponíveis no PETSc , escrito em C, que é bem documentado e suportado. Você pode fazer interface com o PETSc a partir de qualquer um dos idiomas que você deve considerar.

Desempenho e escalabilidade para grandes dados

Os únicos paradigmas de programação paralela mencionados são baseados em memória compartilhada, o que significa que você não está considerando uma abordagem de computação de memória distribuída baseada em MPI (passagem de mensagem). De acordo com minha experiência, é muito mais fácil escrever código que vai muito além de uma dúzia de núcleos usando uma solução de memória distribuída. Quase todos os "agrupamentos" de universidades são baseados em MPI atualmente, grandes máquinas de memória compartilhada são caras e, correspondentemente, raras. Você deve considerar o MPI para sua abordagem, mas meu conselho será aplicado independentemente do paradigma de programação que você escolher.

Com relação ao desempenho no nó, se você estiver escrevendo rotinas numéricas, é mais fácil obter um bom desempenho serial no Fortran. Se você tem um pouco de experiência em C, C ++ ou Python, pode obter um desempenho muito comparável (C e C ++ são inoperantes mesmo com Fortran, Python e MATLAB dentro de uma sobrecarga de cerca de 25% do tempo sem muito esforço). O MATLAB faz isso através de um compilador JIT e muito boa expressividade em álgebra linear. Você provavelmente precisará usar kernels numéricos Cython, numpy, numexpr ou incorporar para obter o desempenho reivindicado do Python. Não posso comentar sobre o desempenho do Java, porque não conheço muito bem a linguagem, mas desconfio que ela não esteja muito longe da linguagem do Python se escrita por um especialista.

Uma nota sobre interfaces

Espero ter convencido você de que você poderá fazer tudo o que quiser em qualquer uma das linguagens de programação que estiver considerando. Se você estiver usando Java, as interfaces C serão um pouco desafiadoras. O Python possui excelente suporte à interface C e Fortran por meio de ctypes, Cython e f2py. O LAPACK já está empacotado e disponível através do scipy. O MATLAB possui toda a funcionalidade necessária em suas bibliotecas nativas, mas não é facilmente escalável ou particularmente fácil de executar em clusters. Java pode suportar interfaces C e Fortran com o JNI , mas não é comumente encontrado em clusters e em software paralelo para computação científica.

Manutenção

Muito disso vai se resumir ao gosto pessoal, mas o consenso geral sobre manutenção é que você deseja minimizar o número de linhas de código em seu software, escrever código modular com interfaces bem definidas e, para o software computacional, fornecer testes que verificam a correção e a funcionalidade da implementação.

Recomendação

Eu , pessoalmente, tive muita sorte com Python e eu recomendo para muitos projetos computacionais. Eu acho que você deve considerá-lo fortemente para o seu projeto. Python e MATLAB são provavelmente as línguas mais expressivas disponíveis para a computação científica. Você pode facilmente conectar o Python a qualquer outra linguagem de programação, pode usar o f2py para encapsular sua implementação atual do Fortran e reescrever peça por peça, independentemente das peças que você deseja no Python enquanto verifica se está mantendo a funcionalidade. No momento, eu recomendaria uma combinação da implementação oficial do Python 2.7 com o scipy . Você pode começar muito facilmente com essa pilha na distribuição gratuita do Enthought Python .

Você também pode fazer a maior parte disso em C, C ++ ou Fortran. C e C ++ são linguagens muito atraentes para desenvolvedores profissionais com muita experiência, mas frequentemente viajam para novos desenvolvedores e, nesse sentido, provavelmente não são uma ótima idéia para um código mais acadêmico. Fortran e MATLAB são populares na computação acadêmica, mas são fracos nas estruturas avançadas de dados e na expressividade que o Python oferece (pense em um objeto de ditado do Python, por exemplo).

Perguntas relacionadas:

Aron Ahmadia
fonte
1
Uma resposta muito bem documentada e com tudo incluído. No Fortran, eu uso muito o Lapack. Vou dar uma olhada no python e tentar encapsular meu código Fortran para começar e lentamente mover para o Python. A única coisa que me assusta é a sobrecarga de 25% do tempo que eu possa ter. Mas se ele vier com o benefício de um código mais expressivo e um melhor processamento da computação paralela, eu tentarei. Mencionei a memória compartilhada apenas porque o software atualmente é executado de maneira interativa (faça uma alteração nos dados e execute novamente) em computadores com memória compartilhada de 2,4,8,24,48 núcleos de pesquisadores da Uni no Windows e Linux.
electrique
3
Não sei como você pode reivindicar uma sobrecarga de 25% para kernels numéricos escritos em Python. Os kernels numéricos do Python puro costumam ser 100x mais lentos que o C. Numpy e numexpr podem fazer um trabalho decente com certas expressões, mas isso dificilmente cria novos kernels numéricos no Python. O Cython pode agilizar algumas coisas, mas geralmente não está dentro de 25% do C. O Python é uma linguagem fina de "cola", mas acho que o Aron está vendendo demais como uma solução de uso geral para tarefas sensíveis ao desempenho.
Jed Brown
E / S é o ponto fraco do Fortran, porque o Fortran requer muita estrutura em E / S. Minha experiência em segunda mão conversando com colegas do meu laboratório que trabalham com Cython corresponde ao que Jed diz sobre Cython; pelo menos um deles escreve C ajustado manualmente para substituir o Cython para tarefas com alto desempenho, e acredito que o desempenho do Python chamando o código C resultante está mais próximo da afirmação de Aron. Além disso, se você mencionar o PETSc e o Python, também poderá mencionar o petsc4py. A última vez que vi (isso foi há alguns anos), não havia boas interfaces MPI para Java. Isso mudou?
amigos estão dizendo
@ GeoffOxberry: As ligações Java MPI existem, mas não foram atualizadas em quase uma década. Considero seu status duvidoso. O Fortran possui inúmeras opções de E / S que podem ser feitas para serem executadas muito rapidamente. Eu recomendo explorar o HDF5 paralelo (e o HDF5, geralmente). Se a E / S for realmente dominante (mais de 50% do tempo de execução), medidas mais sérias podem estar em ordem; caso contrário, a qualidade e a portabilidade de uma interface semelhante ao HDF provavelmente valerão a pena.
Bill Barth
@ BillBarth: Vou ter que verificar isso. Meu comentário sobre o Fortran I / O vem do ponto de vista de alguém que recomendou que eu escrevesse um analisador de arquivo de entrada no Fortran. É possível, aplicando uma grande quantidade de estrutura, mas eu simplesmente não vi bibliotecas de analisador de regex ou analisador de XML de maneira fácil e fácil no Fortran (para dar alguns exemplos). Há uma boa razão para isso: somos as únicas pessoas que usam mais o Fortran. Talvez estejamos pensando em diferentes casos de uso.
Geoff Oxberry
2

Além da resposta muito abrangente de Aron, eu daria uma olhada nos vários tópicos do scicomp.stackexchange que tratavam da questão de qual linguagem de programação tomar - tanto em relação à velocidade dos programas quanto à questão de quão fácil ou difícil é escrever e manter software nesses idiomas.

Dito isto, além do que foi escrito lá, deixe-me fazer algumas observações:

(i) Você inclui o co-array Fortran em sua lista. Que eu saiba, o número de compiladores que realmente o suportam é muito pequeno - e, na verdade, sou zero. O compilador Fortran mais amplamente disponível é o GNU gfortran e, embora as fontes de desenvolvimento atuais analisem um subconjunto de co-matrizes, acredito que ele não suporta nada disso (ou seja, aceita a sintaxe, mas não implementa nenhuma semântica) . Obviamente, essa é uma observação geral sobre os novos padrões do Fortran: que o atraso com o qual os compiladores realmente suportam novos padrões é medido em vários anos - os compiladores implementaram o Fortran 2003 apenas completamente nos últimos dois anos e suportam apenas parcialmente o Fortran 2008. Isso não deve impedi-lo de usar nada, se você tiver um compilador que suporte o que você usa,

(ii) O mesmo certamente acontece com C ++ / Cilk +: Sim, a Intel está desenvolvendo isso em uma filial do GCC, mas não está disponível em nenhuma das versões do GCC e, provavelmente, não será por um tempo. Você pode esperar mais dois ou três anos, pelo menos, até encontrar o Cilk + com as versões do GCC instaladas em máquinas linux típicas.

(iii) C ++ / TBB é uma história diferente: o TBB existe há algum tempo, possui uma interface muito estável e é compilável com a maioria dos compiladores C ++ existentes nos últimos anos (tanto no Linux quanto no Windows) . Nós o usamos em deal.II há vários anos, com bons resultados. Há também um livro muito bom sobre isso.

(iv) Tenho minha própria opinião sobre o OpenMP, a saber, que é uma solução em busca de um problema. Funciona bem para paralelizar os loops internos, o que pode ser interessante se você tiver estruturas de dados muito regulares. Mas raramente é o que você quer fazer se precisar paralelizar algo - porque o que você realmente deseja fazer é paralelizar os loops externos . E, para isso, soluções como o TBB são soluções muito melhores porque usam os mecanismos da linguagem de programação em vez de tentar descrever o que acontece fora da linguagem (via #pragmas) e de maneira que você não tenha acesso aos identificadores de encadeamento , indicadores de status do resultado etc., de dentro do seu programa.

(v) Se você é experimental, também pode dar uma olhada nas novas linguagens de programação projetadas para programação paralela e, em particular, para tarefas como as que você descreve. Existem essencialmente dois que eu daria uma olhada: X10 e Chapel . Eu já vi bons tutoriais no Chapel, e parece bem desenhado, embora ambos, hoje em dia, sejam soluções insulares também.

Wolfgang Bangerth
fonte
Para constar, a Intel afirma ter um co-array paralelo (memória distribuída) Fortran incorporado em seus compiladores atuais. Estamos analisando o assunto no TACC, mas ainda não tenho nada a relatar. O Cray também possui uma implementação em seu compilador, mas isso está disponível apenas em um pequeno número inteiro de máquinas em todo o mundo. Eu não acho que alguém implemente o padrão completo do Fortran 2008 com relação a co-matrizes, ainda, mas há mais do que suporte nascente em alguns compiladores. É claro que o Cilk + também está disponível com os compiladores da Intel, mas ser confiável provavelmente ainda não é sensato.
Bill Barth
O padrão Fortran 2008 não foi aprovado até o final de 2010, portanto levará alguns anos para que o CAF esteja amplamente disponível. O G95 realmente teve uma implementação (não gratuita), mas não é mais desenvolvido (o desenvolvedor ingressou no PathScale).
stali
A maioria do g95 acabou no gfortran, mas pode ser que o CAF não faça parte disso.
11119 Wolfgang Bangerth
Eu acredito que o compilador Intel fornece um bom suporte de co-array. Eles o construíram usando mpiexec. Não será minha primeira escolha. O bom é que a mesma implementação pode ser executada na memória compartilhada e distribuída (executei alguns testes). Com os processadores de memória compartilhada opteron atingindo 60 núcleos a preços realmente razoáveis, quero ver minhas opções de memória compartilhada primeiro.
11138
2

Geralmente, se você é realmente sério sobre esse projeto de software, sugiro uma reescrita completa em qualquer idioma em que você se sinta mais confortável. Parece que você fará o trabalho sozinho e, portanto, obterá os melhores resultados no idioma em que se sentir mais à vontade.

Mais especificamente, porém, em relação ao paralelismo, eu o incentivaria a tentar pensar um pouco fora da caixa. O OpenMP tem seus pontos fortes, mas está preso em uma mentalidade de pegar um código seqüencial e colocar um paralelismo aqui e ali. O mesmo vale, em essência, para a Intels TBB.

Cilk é definitivamente um passo na direção certa, ou seja, força você a repensar seu problema / solução em uma configuração inerentemente paralela. O que eu não gosto sobre isso, porém, é que é outra língua . Além disso, como apenas pode inferir relações entre tarefas paralelas, o agendador pode ser bastante conservador e pode não ter boa escala para determinados problemas.

A boa notícia é que, novamente, se você é sério sobre sua implementação, pode fazer o que o Cilk faz; por exemplo, reescreva seu problema como um conjunto de tarefas interdependentes e distribua-os por vários processadores / núcleos, tudo por conta própria, usando pthreads ou mau uso do OpenMP para gerar processos. Um bom exemplo de como isso pode ser feito é o planejador QUARK usado na biblioteca PLASMA . Uma boa comparação de seu desempenho vs. Cilk é apresentada aqui .

Pedro
fonte
Vou olhar para os links sugeridos. O papel de comparação é muito bom! Obrigado! Eu estive pensando em pthreads, mas quero que o programa seja multiplataforma. Pelo que sei pthreads têm problemas no Windows (errado?).
electrique
@ p3tris: O "p" em pthreads é para POSIX, por isso é o mais portátil possível. Existem algumas implementações compatíveis com o Windows, como pthreads-win32dentro do cygwinprojeto.
Pedro
Com base em stackoverflow.com/q/2797690/801468 , vejo que há muitas coisas necessárias para resolver o uso. Dado que não sou programador, prefiro continuar com algo mais testado.
Jun12
2

Houve pouca discussão sobre o coarray fortran nos comentários acima. No momento, e para meu conhecimento limitado, o suporte a coarray nos compiladores é aproximadamente o seguinte:

  • O Cray possui um compilador que suporta pelo menos os recursos básicos da matriz. Eu o usei para escrever código que deveria ser "educacional", mas eu diria que você poderia escrever código real no coarray fortran. A sintaxe e os conceitos são, na maioria das vezes, muito mais simples que o MPI, mas, como sempre, existem muitas armadilhas e as armadilhas são diferentes da MPI.
  • O Intel fortran possui suporte a coarray construído sobre sua biblioteca MPI. Supostamente, isso limita seu desempenho teórico máximo, mas eu não vi nenhuma métrica.
  • O Gfortran suporta coarrays, mas apenas para uma única imagem (ou classificação única, na fala MPI). Portanto, nenhuma paralelização real está disponível até o gfortran 4.8 ou 4.9 estar disponível.

Geralmente, eu teria cuidado ao iniciar um código baseado em coarray. A sintaxe é simples e muito mais conveniente que o Fortran / C / C ++ com MPI, mas não é tão completa. Por exemplo, o MPI suporta muitas operações de redução, etc., o que pode ser muito conveniente para você. Isso realmente dependeria da sua necessidade de muita comunicação. Se você quiser um exemplo, entre em contato e eu posso fornecer alguns, se eu puder desenterrar os arquivos.

pletnes
fonte
Sim, mais informações sobre a prontidão da matriz Fortran para esse tipo de problema certamente seriam úteis. Bem-vindo ao scicomp!
Aron Ahmadia 01/07/12
1

Dê uma olhada no Spark, que é uma estrutura distribuída para cálculos na memória, que tira proveito da programação funcional. A estrutura de um programa no Spark é muito diferente quando comparada ao MPI. Basicamente, você escreve um código como para um único computador, que é automaticamente distribuído como funções aos dados localizados na memória. Ele suporta Scala, Java e Python.

Regressão logística (scala):

//load data to distributed memory
val points = spark.textFile(...).map(parsePoint).cache()
var w = Vector.random(D) // current separating plane
for (i <- 1 to ITERATIONS) {
  val gradient = points.map(p =>
    (1 / (1 + exp(-p.y*(w dot p.x))) - 1) * p.y * p.x
  ).reduce(_ + _)
  w -= gradient
}
println("Final separating plane: " + w)

Existe uma extensão chamada MLib (biblioteca de aprendizado de máquina) que usa uma biblioteca Fortran para alguns cálculos de baixo nível (para Python, acho que o numpy é usado). Portanto, a ideia é simples, concentre-se no seu algoritmo e deixe as otimizações em níveis mais baixos (ordem de processamento, distribuição de dados etc.).

Tombart
fonte