Interface de passagem de mensagens - Message Passing Interface

Message Passing Interface ( MPI ) é um padrão de transmissão de mensagens padronizado e portátil projetado para funcionar em arquiteturas de computação paralela . O padrão MPI define a sintaxe e a semântica das rotinas de biblioteca que são úteis para uma ampla gama de usuários que escrevem programas portáteis de passagem de mensagens em C , C ++ e Fortran . Existem várias implementações de MPI de código aberto , que fomentaram o desenvolvimento de uma indústria de software paralela e encorajaram o desenvolvimento de aplicativos paralelos portáteis e escaláveis ​​em grande escala.

História

O esforço de interface de passagem de mensagens começou no verão de 1991, quando um pequeno grupo de pesquisadores iniciou as discussões em um retiro nas montanhas da Áustria. Dessa discussão surgiu um Workshop sobre Padrões para Passagem de Mensagens em um Ambiente de Memória Distribuída, realizado de 29 a 30 de abril de 1992 em Williamsburg, Virgínia . Os participantes de Williamsburg discutiram os recursos básicos essenciais para uma interface de troca de mensagens padrão e estabeleceram um grupo de trabalho para continuar o processo de padronização. Jack Dongarra , Tony Hey e David W. Walker apresentaram um projeto de proposta preliminar, "MPI1", em novembro de 1992. Em novembro de 1992, uma reunião do grupo de trabalho do MPI ocorreu em Minneapolis e decidiu colocar o processo de padronização em mais base formal. O grupo de trabalho MPI se reuniu a cada 6 semanas durante os primeiros 9 meses de 1993. O esboço do padrão MPI foi apresentado na conferência Supercomputing '93 em novembro de 1993. Após um período de comentários públicos, que resultou em algumas mudanças no MPI, versão 1.0 do O MPI foi lançado em junho de 1994. Essas reuniões e a discussão por e-mail juntas constituíram o Fórum MPI, cuja associação foi aberta a todos os membros da comunidade de computação de alto desempenho .

O esforço do MPI envolveu cerca de 80 pessoas de 40 organizações, principalmente nos Estados Unidos e na Europa. A maioria dos principais fornecedores de computadores concorrentes estava envolvida no esforço do MPI, colaborando com pesquisadores de universidades, laboratórios governamentais e da indústria .

A MPI fornece aos fornecedores de hardware paralelo um conjunto básico de rotinas claramente definido que pode ser implementado com eficiência. Como resultado, os fornecedores de hardware podem se basear nessa coleção de rotinas padrão de baixo nível para criar rotinas de alto nível para o ambiente de comunicação de memória distribuída fornecido com suas máquinas paralelas . MPI fornece uma interface portátil simples de usar para o usuário básico, mas poderosa o suficiente para permitir que os programadores usem as operações de transmissão de mensagens de alto desempenho disponíveis em máquinas avançadas.

Em um esforço para criar um padrão universal para a passagem de mensagens, os pesquisadores não o basearam em um único sistema, mas incorporou os recursos mais úteis de vários sistemas, incluindo aqueles projetados pela IBM, Intel , nCUBE , PVM, Express, P4 e PARMACS . O paradigma de transmissão de mensagens é atraente devido à ampla portabilidade e pode ser usado na comunicação para multiprocessadores de memória distribuída e compartilhada, redes de estações de trabalho e uma combinação desses elementos. O paradigma pode ser aplicado em várias configurações, independentemente da velocidade da rede ou da arquitetura de memória.

O apoio para as reuniões do MPI veio em parte da DARPA e da Fundação Nacional de Ciências dos EUA (NSF) sob a concessão ASC-9310330, acordo de cooperação do Centro de Ciência e Tecnologia NSF número CCR-8809615 e da Comissão Europeia através do Projeto Esprit P6643. A Universidade do Tennessee também fez contribuições financeiras para o Fórum MPI.

Visão geral

MPI é um protocolo de comunicação para programação de computadores paralelos . Tanto a comunicação ponto a ponto quanto a coletiva são suportadas. MPI "é uma interface de programador de aplicativo de passagem de mensagens, junto com especificações de protocolo e semânticas de como seus recursos devem se comportar em qualquer implementação." Os objetivos da MPI são alto desempenho, escalabilidade e portabilidade. O MPI continua sendo o modelo dominante usado na computação de alto desempenho hoje.

O MPI não é sancionado por nenhum órgão de padronização importante; no entanto, tornou-se um padrão de fato para comunicação entre processos que modelam um programa paralelo rodando em um sistema de memória distribuída . Os supercomputadores reais de memória distribuída, como clusters de computadores, geralmente executam esses programas.

O modelo MPI-1 principal não tem conceito de memória compartilhada e o MPI-2 tem apenas um conceito limitado de memória compartilhada distribuída . No entanto, programas MPI são regularmente executado em computadores de memória compartilhada, e ambos MPICH e Abrir MPI pode usar memória compartilhada para a transferência de mensagem se ele estiver disponível. Projetar programas em torno do modelo MPI (ao contrário dos modelos explícitos de memória compartilhada ) tem vantagens sobre as arquiteturas NUMA , uma vez que o MPI incentiva a localidade da memória . A programação explícita de memória compartilhada foi introduzida no MPI-3.

Embora MPI pertença às camadas 5 e superiores do Modelo de Referência OSI , as implementações podem cobrir a maioria das camadas, com soquetes e Protocolo de Controle de Transmissão (TCP) usados ​​na camada de transporte.

A maioria das implementações MPI consiste em um conjunto específico de rotinas diretamente chamadas de C , C ++ , Fortran (ou seja, uma API) e qualquer linguagem capaz de fazer interface com tais bibliotecas, incluindo C # , Java ou Python . As vantagens do MPI em relação às bibliotecas de transmissão de mensagens mais antigas são a portabilidade (porque o MPI foi implementado para quase todas as arquiteturas de memória distribuída) e a velocidade (porque cada implementação é, em princípio, otimizada para o hardware em que é executada).

MPI usa especificações independentes de linguagem (LIS) para chamadas e ligações de linguagem. O primeiro padrão MPI especificava ligações ANSI C e Fortran-77 junto com o LIS. O projeto foi apresentado na Supercomputing 1994 (novembro de 1994) e finalizado logo depois. Cerca de 128 funções constituem o padrão MPI-1.3, que foi lançado como o fim da série MPI-1 em 2008.

Atualmente, o padrão tem várias versões: versão 1.3 (comumente abreviada como MPI-1 ), que enfatiza a passagem de mensagens e tem um ambiente de tempo de execução estático, MPI-2.2 (MPI-2), que inclui novos recursos, como E / S paralela, gerenciamento de processos dinâmicos e operações de memória remota e MPI-3.1 (MPI-3), que inclui extensões para as operações coletivas com versões não bloqueadoras e extensões para as operações unilaterais. O LIS do MPI-2 especifica mais de 500 funções e fornece ligações de linguagem para ISO C , ISO C ++ e Fortran 90 . A interoperabilidade de objetos também foi adicionada para permitir uma programação mais fácil de passagem de mensagens em idiomas mistos. Um efeito colateral da padronização do MPI-2, concluída em 1996, foi o esclarecimento do padrão MPI-1, criando o MPI-1.2.

MPI-2 é principalmente um superconjunto do MPI-1, embora algumas funções estejam obsoletas. Os programas MPI-1.3 ainda funcionam em implementações MPI compatíveis com o padrão MPI-2.

MPI-3 inclui novas associações Fortran 2008, enquanto remove associações C ++ obsoletas, bem como muitas rotinas obsoletas e objetos MPI.

MPI é freqüentemente comparado com Parallel Virtual Machine (PVM), que é um ambiente distribuído popular e sistema de passagem de mensagem desenvolvido em 1989, e que foi um dos sistemas que motivou a necessidade de passagem de mensagem paralela padrão. Modelos de programação de memória compartilhada encadeada (como Pthreads e OpenMP ) e programação de passagem de mensagem (MPI / PVM) podem ser considerados complementares e têm sido usados ​​juntos ocasionalmente em, por exemplo, servidores com vários nós grandes de memória compartilhada.

Funcionalidade

A interface MPI se destina a fornecer topologia virtual essencial, sincronização e funcionalidade de comunicação entre um conjunto de processos (que foram mapeados para nós / servidores / instâncias de computador) de uma forma independente de linguagem, com sintaxe específica de linguagem (ligações), além de alguns recursos específicos do idioma. Os programas MPI sempre funcionam com processos, mas os programadores geralmente se referem aos processos como processadores. Normalmente, para desempenho máximo, cada CPU (ou núcleo em uma máquina com vários núcleos) será atribuído a apenas um único processo. Essa atribuição ocorre em tempo de execução por meio do agente que inicia o programa MPI, normalmente denominado mpirun ou mpiexec.

As funções da biblioteca MPI incluem, mas não estão limitadas a, operações de envio / recebimento do tipo encontro ponto a ponto, escolhendo entre uma topologia de processo lógico cartesiana ou semelhante a um gráfico , troca de dados entre pares de processos (operações de envio / recebimento), combinação parcial resultados de cálculos (operações de coleta e redução), nós de sincronização (operação de barreira), bem como a obtenção de informações relacionadas à rede, como o número de processos na sessão de computação, identidade do processador atual para o qual um processo é mapeado, processos vizinhos acessíveis em um topologia lógica e assim por diante. As operações ponto a ponto vêm em formas síncronas , assíncronas , em buffer e prontas , para permitir uma semântica relativamente mais forte e mais fraca para os aspectos de sincronização de um envio de rendezvous. Muitas operações pendentes são possíveis no modo assíncrono, na maioria das implementações.

O MPI-1 e o MPI-2 permitem implementações que se sobrepõem à comunicação e à computação, mas a prática e a teoria são diferentes. O MPI também especifica interfaces thread-safe , que possuem estratégias de coesão e acoplamento que ajudam a evitar o estado oculto na interface. É relativamente fácil escrever código MPI ponto a ponto multithread e algumas implementações suportam tal código. A comunicação coletiva multithread é melhor realizada com várias cópias de Communicators, conforme descrito abaixo.

Conceitos

MPI oferece vários recursos. Os conceitos a seguir fornecem contexto para todas essas habilidades e ajudam o programador a decidir qual funcionalidade usar em seus programas aplicativos. Quatro dos oito conceitos básicos do MPI são exclusivos do MPI-2.

Comunicador

Os objetos do Communicator conectam grupos de processos na sessão MPI. Cada comunicador fornece a cada processo contido um identificador independente e organiza seus processos contidos em uma topologia ordenada . MPI também tem grupos explícitos, mas estes são principalmente bons para organizar e reorganizar grupos de processos antes que outro comunicador seja feito. MPI compreende operações intracomunicadoras de grupo único e comunicação intercomunicador bilateral. No MPI-1, as operações de grupo único são mais prevalentes. As operações bilaterais aparecem principalmente no MPI-2, onde incluem comunicação coletiva e gerenciamento dinâmico em processo.

Os comunicadores podem ser particionados usando vários comandos MPI. Esses comandos incluem MPI_COMM_SPLIT, onde cada processo se junta a um dos vários subcomunicadores coloridos, declarando ter essa cor.

Noções básicas ponto a ponto

Uma série de funções MPI importantes envolvem a comunicação entre dois processos específicos. Um exemplo popular é MPI_Send, que permite que um processo especificado envie uma mensagem a um segundo processo especificado. As operações ponto a ponto, como são chamadas, são particularmente úteis na comunicação padronizada ou irregular, por exemplo, uma arquitetura paralela de dados em que cada processador troca rotineiramente regiões de dados com outros processadores específicos entre as etapas de cálculo, ou um mestre arquitetura escrava na qual o mestre envia novos dados de tarefa a um escravo sempre que a tarefa anterior é concluída.

O MPI-1 especifica mecanismos para mecanismos de comunicação ponto a ponto bloqueadores e não bloqueadores, bem como o mecanismo denominado 'pronto-envio', pelo qual uma solicitação de envio pode ser feita apenas quando a solicitação de recebimento correspondente já tiver sido feita .

Noções básicas coletivas

As funções coletivas envolvem a comunicação entre todos os processos em um grupo de processos (o que pode significar todo o pool de processos ou um subconjunto definido pelo programa). Uma função típica é a MPI_Bcastchamada (abreviação de " transmissão "). Esta função obtém dados de um nó e os envia a todos os processos no grupo de processos. Uma operação reversa é a MPI_Reducechamada, que obtém dados de todos os processos em um grupo, realiza uma operação (como soma) e armazena os resultados em um nó. MPI_Reducegeralmente é útil no início ou no final de um grande cálculo distribuído, em que cada processador opera em uma parte dos dados e os combina em um resultado.

Outras operações executar tarefas mais sofisticados, tais como MPI_Alltoallque reorganiza n itens de dados de tal forma que o n º nó recebe o n º ponto de dados de cada um.

Tipos de dados derivados

Muitas funções MPI requerem que você especifique o tipo de dados que são enviados entre os processos. Isso ocorre porque o MPI tem como objetivo oferecer suporte a ambientes heterogêneos onde os tipos podem ser representados de maneira diferente nos diferentes nós (por exemplo, eles podem estar executando diferentes arquiteturas de CPU que têm endianness diferente ), caso em que as implementações de MPI podem realizar a conversão de dados . Desde a linguagem C não permite que um tipo próprio para ser passado como um parâmetro, MPI predefine as constantes MPI_INT, MPI_CHAR, MPI_DOUBLEpara corresponder com int, char, double, etc.

Aqui está um exemplo em C que passa matrizes de ints de todos os processos para um. O único processo de recebimento é chamado de processo "raiz" e pode ser qualquer processo designado, mas normalmente será o processo 0. Todos os processos pedem para enviar seus arrays para a raiz com MPI_Gather, o que é equivalente a ter cada processo (incluindo o a própria raiz) MPI_Sende a raiz faz o número correspondente de MPI_Recvchamadas ordenadas para montar todas essas matrizes em uma maior:

int send_array[100];
int root = 0; /* or whatever */
int num_procs, *recv_array;
MPI_Comm_size(comm, &num_procs);
recv_array = malloc(num_procs * sizeof(send_array));
MPI_Gather(send_array, sizeof(send_array) / sizeof(*send_array), MPI_INT,
           recv_array, sizeof(send_array) / sizeof(*send_array), MPI_INT,
           root, comm);

No entanto, você pode desejar enviar dados como um bloco em vez de 100 ints. Para fazer isso, defina um tipo de dados derivado de "bloco contíguo":

MPI_Datatype newtype;
MPI_Type_contiguous(100, MPI_INT, &newtype);
MPI_Type_commit(&newtype);
MPI_Gather(array, 1, newtype, receive_array, 1, newtype, root, comm);

Para passar uma classe ou estrutura de dados, MPI_Type_create_structcria um tipo de MPI_predefineddados derivado de MPI a partir de tipos de dados, da seguinte maneira:

int MPI_Type_create_struct(int count,
                           int *blocklen,
                           MPI_Aint *disp,
                           MPI_Datatype *type,
                           MPI_Datatype *newtype)

Onde:

  • counté um número de blocos, e especifica o comprimento (em elementos) das matrizes blocklen, dispe type.
  • blocklen contém vários elementos em cada bloco,
  • disp contém deslocamentos de byte de cada bloco,
  • type contém tipos de elemento em cada bloco.
  • newtype (uma saída) contém o novo tipo derivado criado por esta função

O disparray (deslocamentos) é necessário para o alinhamento da estrutura de dados , uma vez que o compilador pode preencher as variáveis ​​em uma classe ou estrutura de dados. A maneira mais segura de descobrir a distância entre campos diferentes é obtendo seus endereços na memória. Isso é feito com MPI_Get_address, que normalmente é o mesmo que o &operador de C, mas pode não ser verdade ao lidar com segmentação de memória .

Passar uma estrutura de dados como um bloco é significativamente mais rápido do que passar um item por vez, especialmente se a operação for repetida. Isso ocorre porque os blocos de tamanho fixo não requerem serialização durante a transferência.

Dadas as seguintes estruturas de dados:

struct A {
    int f;
    short p;
};

struct B {
    struct A a;
    int pp, vp;
};

Aqui está o código C para construir um tipo de dados derivado de MPI:

static const int blocklen[] = {1, 1, 1, 1};
static const MPI_Aint disp[] = {
    offsetof(struct B, a) + offsetof(struct A, f),
    offsetof(struct B, a) + offsetof(struct A, p),
    offsetof(struct B, pp),
    offsetof(struct B, vp)
};
static MPI_Datatype type[] = {MPI_INT, MPI_SHORT, MPI_INT, MPI_INT};
MPI_Datatype newtype;
MPI_Type_create_struct(sizeof(type) / sizeof(*type), blocklen, disp, type, &newtype);
MPI_Type_commit(&newtype);

Conceitos MPI-2

Comunicação unilateral

MPI-2 define três operações de comunicação unilateral, MPI_Put, MPI_Get, e MPI_Accumulate, sendo uma gravação para memória remota, uma leitura da memória remota, e uma operação de redução no mesmo memória através de uma série de tarefas, respectivamente. Também estão definidos três métodos diferentes para sincronizar essa comunicação (bloqueios globais, de pares e remotos), pois a especificação não garante que essas operações ocorreram até um ponto de sincronização.

Esses tipos de chamada podem frequentemente ser úteis para algoritmos nos quais a sincronização seria inconveniente (por exemplo , multiplicação de matriz distribuída ) ou onde é desejável que as tarefas sejam capazes de equilibrar sua carga enquanto outros processadores estão operando nos dados.

Gestão dinâmica de processos

O aspecto chave é "a capacidade de um processo MPI de participar na criação de novos processos MPI ou de estabelecer comunicação com processos MPI iniciados separadamente." A especificação MPI-2 descreve três interfaces principais pelas quais os processos MPI podem estabelecer comunicações dinamicamente MPI_Comm_spawn, MPI_Comm_accept/ MPI_Comm_connecte MPI_Comm_join. A MPI_Comm_spawninterface permite que um processo MPI gere várias instâncias do processo MPI nomeado. O conjunto de processos MPI recém-gerado forma um novo MPI_COMM_WORLDintracomunicador, mas pode se comunicar com o pai e o intercomunicador que a função retorna. MPI_Comm_spawn_multipleé uma interface alternativa que permite que as diferentes instâncias geradas sejam binários diferentes com argumentos diferentes.

I / O

O recurso de E / S paralela às vezes é chamado de MPI-IO e se refere a um conjunto de funções projetadas para abstrair o gerenciamento de E / S em sistemas distribuídos para MPI e permitir que os arquivos sejam facilmente acessados ​​de forma padronizada usando a funcionalidade de tipo de dados derivada existente .

A pouca pesquisa que foi feita sobre esse recurso indica que pode não ser trivial obter altos ganhos de desempenho usando MPI-IO. Por exemplo, uma implementação de multiplicações esparsas de matriz-vetor usando a biblioteca MPI I / O mostra um comportamento geral de ganho de desempenho menor, mas esses resultados são inconclusivos. Não foi até a ideia de E / S coletiva implementada no MPI-IO que o MPI-IO começou a alcançar uma adoção generalizada. A E / S coletiva aumenta substancialmente a largura de banda de E / S dos aplicativos ao fazer com que os processos transformem coletivamente as operações de E / S pequenas e não contíguas em grandes e contíguas, reduzindo assim o bloqueio e a sobrecarga de busca de disco. Devido aos seus vastos benefícios de desempenho, o MPI-IO também se tornou a camada de I / O subjacente para muitas bibliotecas de I / O de última geração, como HDF5 e Parallel NetCDF . Sua popularidade também desencadeou pesquisas sobre otimizações de E / S coletivas, como E / S com reconhecimento de layout e agregação de arquivo cruzado.

Implementações oficiais

Muitos outros esforços são derivados de MPICH, LAM e outros trabalhos, incluindo, mas não se limitando a, implementações comerciais da HP , Intel , Microsoft e NEC .

Embora as especificações exijam uma interface C e Fortran, a linguagem usada para implementar MPI não está restrita a corresponder à linguagem ou às linguagens que ela busca oferecer suporte em tempo de execução. A maioria das implementações combina C, C ++ e linguagem assembly, e programadores de C, C ++ e Fortran de destino. Bindings estão disponíveis para muitas outras linguagens, incluindo Perl, Python, R, Ruby, Java e CL (consulte #Language bindings ).

A ABI das implementações MPI são aproximadamente divididas entre os derivados MPICH e OpenMP, de modo que uma biblioteca de uma família funciona como uma substituição imediata de outra da mesma família, mas a substituição direta entre as famílias é impossível. O CEA francês mantém uma interface de invólucro para facilitar essas opções.

Hardware

A pesquisa de hardware MPI concentra-se na implementação de MPI diretamente no hardware, por exemplo, por meio do processador na memória , incorporando operações MPI no microcircuito dos chips de RAM em cada nó. Por implicação, essa abordagem é independente de linguagem, sistema operacional e CPU, mas não pode ser prontamente atualizada ou removida.

Outra abordagem foi adicionar aceleração de hardware a uma ou mais partes da operação, incluindo processamento de hardware de filas MPI e uso de RDMA para transferir dados diretamente entre a memória e a interface de rede sem intervenção da CPU ou kernel do sistema operacional.

Wrappers do compilador

mpicc (e da mesma forma mpic ++ , mpif90 , etc.) é um programa que envolve um compilador existente para definir os sinalizadores de linha de comando necessários ao compilar o código que usa MPI. Normalmente, ele adiciona alguns sinalizadores que permitem que o código seja compilado e vinculado à biblioteca MPI.

Ligações de linguagem

Bindings são bibliotecas que estendem o suporte MPI a outras linguagens, envolvendo uma implementação MPI existente, como MPICH ou Open MPI.

Infraestrutura de linguagem comum

As duas implementações gerenciadas do Common Language Infrastructure .NET são Pure Mpi.NET e MPI.NET, um esforço de pesquisa da Indiana University licenciado sob uma licença do estilo BSD . É compatível com Mono e pode fazer uso total de malhas de rede MPI de baixa latência subjacentes.

Java

Embora o Java não tenha uma vinculação MPI oficial, vários grupos tentam fazer a ponte entre as duas, com diferentes graus de sucesso e compatibilidade. Uma das primeiras tentativas foi o mpiJava de Bryan Carpenter, essencialmente um conjunto de wrappers Java Native Interface (JNI) para uma biblioteca C MPI local, resultando em uma implementação híbrida com portabilidade limitada, que também deve ser compilada em relação à biblioteca MPI específica que está sendo usada .

No entanto, este projeto original também definiu a API mpiJava (uma API MPI de fato para Java que seguia de perto as ligações C ++ equivalentes) que outros projetos MPI Java subsequentes adotaram. Uma API menos usada é a MPJ API, que foi projetada para ser mais orientada a objetos e mais próxima das convenções de codificação da Sun Microsystems . Além da API, as bibliotecas Java MPI podem ser dependentes de uma biblioteca MPI local ou implementar as funções de passagem de mensagens em Java, enquanto algumas como P2P-MPI também fornecem funcionalidade ponto a ponto e permitem operação em plataforma mista.

Algumas das partes mais desafiadoras de Java / MPI surgem de características Java, como a falta de ponteiros explícitos e o espaço de endereço de memória linear para seus objetos, o que torna a transferência de matrizes multidimensionais e objetos complexos ineficiente. As soluções alternativas geralmente envolvem a transferência de uma linha de cada vez e / ou execução de desserialização e conversão explícitas nas extremidades de envio e recebimento, simulando matrizes C ou Fortran pelo uso de uma matriz unidimensional e ponteiros para tipos primitivos por o uso de matrizes de elemento único, resultando em estilos de programação muito distantes das convenções Java.

Outro sistema de passagem de mensagens Java é o MPJ Express. As versões recentes podem ser executadas em configurações de cluster e multicore. Na configuração do cluster, ele pode executar aplicativos Java paralelos em clusters e nuvens. Aqui, soquetes Java ou interconexões de E / S especializadas como Myrinet podem suportar mensagens entre processos MPJ Express. Ele também pode utilizar a implementação nativa de C de MPI usando seu dispositivo nativo. Na configuração multicore, um aplicativo Java paralelo é executado em processadores multicore. Nesse modo, os processos MPJ Express são representados por encadeamentos Java.

Julia

O wrapper de linguagem Julia para MPI foi usado e considerado mais rápido do que para C ou Fortran.

MATLAB

Existem algumas implementações acadêmicas de MPI usando MATLAB . O MATLAB tem sua própria biblioteca de extensão paralela implementada usando MPI e PVM .

OCaml

O módulo OCamlMPI implementa um grande subconjunto de funções MPI e está em uso ativo na computação científica. Um programa OCaml de 11.000 linhas foi "MPI-ified" usando o módulo, com 500 linhas adicionais de código e uma pequena reestruturação, e foi executado com excelentes resultados em até 170 nós em um supercomputador.

Pitão

As implementações MPI em Python incluem: pyMPI , mpi4py, pypar, MYMPI e o submódulo MPI em ScientificPython . pyMPI é notável porque é um interpretador python variante, enquanto pypar, MYMPI e o módulo ScientificPython são módulos de importação. Eles tornam o trabalho do codificador decidir a quem MPI_Initpertence a chamada .

Recentemente, as Bibliotecas Boost C ++ adquiriram o Boost: MPI que incluía os Bindings MPI Python. Isso é de ajuda especial para misturar C ++ e Python. Em outubro de 2016 Boost: os vínculos Python da MPI ainda têm bugs de empacotamento não corrigidos no CentOS .

R

As ligações R de MPI incluem Rmpi e pbdMPI , em que Rmpi ​​se concentra no paralelismo dos trabalhadores-gerente, enquanto o pbdMPI se concentra no paralelismo SPMD . Ambas as implementações são totalmente compatíveis com Open MPI ou MPICH2 .

Programa de exemplo

Aqui está um "Olá, mundo!" programa em MPI escrito em C. Neste exemplo, enviamos uma mensagem "hello" para cada processador, o manipulamos trivialmente, retornamos os resultados ao processo principal e imprimimos as mensagens.

/*
  "Hello World" MPI Test Program
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <mpi.h>

int main(int argc, char **argv)
{
    char buf[256];
    int my_rank, num_procs;

    /* Initialize the infrastructure necessary for communication */
    MPI_Init(&argc, &argv);

    /* Identify this process */
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

    /* Find out how many total processes are active */
    MPI_Comm_size(MPI_COMM_WORLD, &num_procs);

    /* Until this point, all programs have been doing exactly the same.
       Here, we check the rank to distinguish the roles of the programs */
    if (my_rank == 0) {
        int other_rank;
        printf("We have %i processes.\n", num_procs);

        /* Send messages to all other processes */
        for (other_rank = 1; other_rank < num_procs; other_rank++)
        {
            sprintf(buf, "Hello %i!", other_rank);
            MPI_Send(buf, sizeof(buf), MPI_CHAR, other_rank,
                     0, MPI_COMM_WORLD);
        }

        /* Receive messages from all other process */
        for (other_rank = 1; other_rank < num_procs; other_rank++)
        {
            MPI_Recv(buf, sizeof(buf), MPI_CHAR, other_rank,
                     0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            printf("%s\n", buf);
        }

    } else {

        /* Receive message from process #0 */
        MPI_Recv(buf, sizeof(buf), MPI_CHAR, 0,
                 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        assert(memcmp(buf, "Hello ", 6) == 0);

        /* Send message to process #0 */
        sprintf(buf, "Process %i reporting for duty.", my_rank);
        MPI_Send(buf, sizeof(buf), MPI_CHAR, 0,
                 0, MPI_COMM_WORLD);

    }

    /* Tear down the communication infrastructure */
    MPI_Finalize();
    return 0;
}

Quando executado com 4 processos, deve produzir a seguinte saída:

$ mpicc example.c && mpiexec -n 4 ./a.out
We have 4 processes.
Process 1 reporting for duty.
Process 2 reporting for duty.
Process 3 reporting for duty.

Aqui, mpiexecestá um comando usado para executar o programa de exemplo com 4 processos , cada um dos quais é uma instância independente do programa em tempo de execução e classificações atribuídas (ou seja, IDs numéricos) 0, 1, 2 e 3. O nome mpiexecé recomendado por o padrão MPI, embora algumas implementações forneçam um comando semelhante sob o nome mpirun. O MPI_COMM_WORLDé o comunicador que consiste em todos os processos.

Um modelo de programação de programa único, dados múltiplos ( SPMD ) é facilitado, mas não obrigatório; muitas implementações de MPI permitem que vários executáveis ​​diferentes sejam iniciados no mesmo trabalho de MPI. Cada processo tem sua própria classificação, o número total de processos no mundo e a capacidade de se comunicar entre eles por comunicação ponto a ponto (enviar / receber) ou por comunicação coletiva entre o grupo. É o suficiente para o MPI fornecer um programa no estilo SPMD com MPI_COMM_WORLDsua própria classificação e o tamanho do mundo para permitir que os algoritmos decidam o que fazer. Em situações mais realistas, a E / S é gerenciada com mais cuidado do que neste exemplo. MPI não estipula como I / O padrão (stdin, stdout, stderr) deve funcionar em um determinado sistema. Geralmente funciona conforme o esperado no processo de classificação 0, e algumas implementações também capturam e canalizam a saída de outros processos.

MPI usa a noção de processo em vez de processador. As cópias do programa são mapeadas para processadores pelo tempo de execução MPI . Nesse sentido, a máquina paralela pode mapear para um processador físico, ou para N processadores, onde N é o número de processadores disponíveis, ou mesmo algo entre eles. Para a máxima aceleração paralela, mais processadores físicos são usados. Este exemplo ajusta seu comportamento ao tamanho do mundo N , portanto, ele também busca escalar para a configuração de tempo de execução sem compilação para cada variação de tamanho, embora as decisões de tempo de execução possam variar dependendo da quantidade absoluta de simultaneidade disponível.

Adoção MPI-2

A adoção do MPI-1.2 foi universal, particularmente na computação em cluster, mas a aceitação do MPI-2.1 foi mais limitada. Os problemas incluem:

  1. As implementações de MPI-2 incluem E / S e gerenciamento de processo dinâmico, e o tamanho do middleware é substancialmente maior. A maioria dos sites que usam sistemas de agendamento em lote não oferece suporte ao gerenciamento dinâmico de processos. A E / S paralela do MPI-2 é bem aceita.
  2. Muitos programas MPI-1.2 foram desenvolvidos antes do MPI-2. As preocupações com a portabilidade inicialmente retardaram a adoção, embora o suporte mais amplo tenha diminuído isso.
  3. Muitos aplicativos MPI-1.2 usam apenas um subconjunto desse padrão (16-25 funções) sem necessidade real da funcionalidade MPI-2.

Futuro

Alguns aspectos do futuro do MPI parecem sólidos; outros nem tanto. O MPI Forum se reuniu novamente em 2007 para esclarecer algumas questões do MPI-2 e explorar desenvolvimentos para um possível MPI-3, que resultou nas versões MPI-3.0 (setembro de 2012) e MPI-3.1 (junho de 2015).

As arquiteturas estão mudando, com maior simultaneidade interna ( multi-core ), melhor controle de simultaneidade refinado (threading, afinidade) e mais níveis de hierarquia de memória . Os programas multithread podem tirar vantagem desses desenvolvimentos mais facilmente do que os aplicativos single-threaded. Isso já resultou em padrões complementares separados para multiprocessamento simétrico , a saber, OpenMP . MPI-2 define como as implementações em conformidade com o padrão devem lidar com problemas multithread, mas não exige que as implementações sejam multithread ou mesmo thread-safe. MPI-3 adiciona a capacidade de usar paralelismo de memória compartilhada dentro de um nó. Implementações de MPI como Adaptive MPI, Hybrid MPI, Fine-Grained MPI, MPC e outros oferecem extensões para o padrão MPI que abordam diferentes desafios em MPI.

O astrofísico Jonathan Dursi escreveu um artigo de opinião chamando MPI obsoleto, apontando para tecnologias mais recentes como a linguagem Chapel , Unified Parallel C , Hadoop , Spark e Flink .

Veja também

Referências

Leitura adicional

links externos