Arquiteturas de Computadores, Processamento e Programação Paralela

Classificado em Computação

Escrito em em português com um tamanho de 10,33 KB

Arquiteturas de Computadores: Taxonomia de Flynn

SISD (Single Instruction, Single Data)

Corresponde aos computadores sequenciais convencionais (Arquitetura de Von Neumann).

SIMD (Single Instruction, Multiple Data)

Corresponde ao processamento de vários dados sob o comando de apenas uma instrução. Em uma arquitetura SIMD, o programa ainda segue uma organização sequencial.

SIMD - Processadores Vetoriais

Os processadores vetoriais são mais bem-sucedidos comercialmente que os matriciais. Parte do seu sucesso deve-se ao fato de que um processador vetorial é uma arquitetura de uso geral, capaz de executar todas as operações escalares normais.

SIMD - Processadores Matriciais

Já os processadores matriciais não implementam funções escalares e, geralmente, são configurados como periféricos de outras arquiteturas (mainframes e minicomputadores) para a execução da porção vetorial dos programas.

MIMD (Multiple Instruction, Multiple Data)

Envolve múltiplos processadores executando diferentes instruções em diferentes conjuntos de dados, de maneira independente. Esta classe engloba a maioria dos computadores paralelos.

MIMD - Memória Distribuída (Distributed Memory)

Cada processador é capaz de endereçar apenas a sua memória local.

Vantagens
  • Altamente escalável e permite a construção de processadores maciçamente paralelos.
  • A comunicação entre os processadores se dá através de troca de mensagens.
  • A troca de mensagens resolve tanto o problema da comunicação entre processadores quanto o da sincronização.
Desvantagens
  • Necessidade de fazer uma boa distribuição de carga entre os processadores, seja automaticamente ou manualmente.
  • É necessário evitar as situações de deadlock, tanto no nível de aplicação quanto no nível de sistema.

MIMD - Memória Compartilhada (Shared Memory)

Cada processador consegue ter acesso a todo o espaço de memória do sistema.

Vantagens
  • Não há necessidade de particionar o código ou dados, logo técnicas de programação para uniprocessadores podem ser facilmente adaptadas para ambientes multiprocessadores.
  • Não há necessidade de se movimentar fisicamente os dados quando dois ou mais processadores se comunicam. Como resultado, a comunicação entre processos é bastante eficiente.
  • Localidade memória/processador.
  • Compartilhamento de recursos.
  • Semelhante a uma arquitetura sequencial.
  • Programação mais simples.
Desvantagens
  • Há necessidade do uso de primitivas especiais de sincronização quando do acesso a regiões compartilhadas na memória, para assegurar um resultado correto para a computação.
  • Falta de escalabilidade devido ao problema de contenção de memória. Depois de um determinado número de processadores, a adição de mais processadores não aumenta o desempenho.
  • Gargalo no barramento de memória.
  • Consistência de cache.
  • Modelo de programação menos natural.

MIMD - UMA (Uniform Memory Access) / NUMA (Non-Uniform Memory Access)

UMA: Nas máquinas que possuem esse tipo de arquitetura, o tempo de acesso aos dados localizados em qualquer posição da memória é o mesmo para todos os processadores. A forma de interconexão mais comum neste tipo de máquina é o barramento, e a memória geralmente é implementada com um único módulo.

NUMA: Nos computadores que possuem arquitetura NUMA, o tempo de acesso à memória depende da posição em que a mesma se encontra em relação ao processador. Isso acontece devido ao fato de que, nesse tipo de arquitetura, existe um limite quanto ao número de processadores por barramento de memória. Dessa forma, um processador terá acesso mais rápido a uma região de memória localizada no seu barramento do que a uma região localizada em um barramento diferente.

SMP (Symmetric Multiprocessor System)

Uma máquina de arquitetura paralela MIMD com memória compartilhada, constituída por processadores que, na maioria das vezes, estão conectados à memória por meio de um barramento. Elas possuem arquitetura...

(Nota: O texto original termina abruptamente aqui, mas o conteúdo não foi cortado.)

Processamento Paralelo

Definição

É usar múltiplos (dois ou mais) processadores, simultaneamente, para resolver um mesmo problema.

Objetivos

  • Redução do tempo necessário para resolver um problema (desempenho).
  • Paralelismo de atividades diferentes que precisam ser realizadas em um tempo aceitável para a tomada de decisões corretas.

Processo - Definição

É uma entidade dinâmica que altera seu estado à medida que avança sua execução. Assim, o processo é uma abstração que representa um programa em execução.

Thread - Definição

Programa em execução com um único fluxo de execução. Em sistemas tradicionais, cada processo tem seu espaço de endereçamento individual e um fluxo de execução.

Multithreading

É a capacidade que o sistema operacional possui de executar várias threads simultaneamente sem que uma interfira na outra. Essas threads compartilham os recursos do processo, mas não são capazes de ser executadas de forma independente.

Programação Paralela

Definição

A Programação Paralela é uma estratégia que consiste na execução simultânea de partes distintas de uma mesma aplicação, minimizando o tempo na obtenção de resultados de tarefas grandes e complexas.

O paralelismo pode ocorrer:

  • Com memória compartilhada: Caracteriza-se pela presença de mais de um processador compartilhando recursos de memória e disco de um mesmo computador. Neste caso, o sistema operacional é o responsável pela maior parte da complexidade, inclusive pelo controle de concorrência.
  • Com memória distribuída: Quase não há compartilhamento de recursos entre processadores, e a aplicação é responsável por coordenar as tarefas e a coerência entre os diversos nós (computadores independentes com memória e disco próprios) do sistema.

Sincronização

Quando threads são disparadas dentro de uma mesma aplicação, é necessário sincronizá-las para evitar que dados compartilhados se tornem inconsistentes ou que essas threads atuem em momentos errados.

Formas de Sincronização

  • Sincronização de Competição: Ocorre quando duas ou mais threads competem pelo mesmo recurso compartilhado e, por isso, precisam se comunicar de alguma forma para que os dados não se tornem inconsistentes devido à concorrência das threads no acesso aos mesmos.
  • Sincronização de Cooperação: Ocorre quando o aspecto mais importante de duas ou mais threads não é a competição por um recurso, mas sim a comunicação entre elas para que uma atue num momento específico que depende de uma ação ou estado da outra.

Programação Distribuída

Definição

Programação Distribuída consiste na execução de aplicações cooperantes em computadores diferentes interligados por uma rede local, Internet, ou por outra rede pública ou privada. É uma forma de programação geralmente muito utilizada em Sistemas Multimídia e em Computação Móvel.

Sockets

Socket representa um ponto de conexão em uma rede TCP/IP. Para dois computadores trocarem informações, cada um utiliza um socket. Um computador é o Servidor, que abre o socket e escuta à espera de conexões, e o outro é o Cliente, que chama o socket do Servidor para iniciar a conexão.

Implementação de Threads em Java (Exemplos)

Há duas maneiras principais para criar uma thread:

1. Herdar a classe Thread

A primeira forma é declarar uma classe que herde a classe Thread. Quando a classe é instanciada, a thread e o objeto são criados juntos, e o objeto é limitado automaticamente à thread. Chamando o método start() do objeto, a thread é iniciada e executa imediatamente o método run() do objeto. O código a seguir demonstra esta forma de implementação:

// A classe ThreadBasica1 herda de Thread
class ThreadBasica1 extends Thread {
    // Este método(run()) é chamado quando a thread é iniciada
    public void run() {
    }
}

// Criando e iniciando a thread definida
Thread thread = new ThreadBasica1(); 
thread.start();

2. Implementar a interface Runnable

A segunda maneira é criar a thread implementando a interface Runnable e fornecer um objeto com um método run(). Este objeto será associado permanentemente à thread. O método run() do objeto será invocado quando a thread for iniciada. Este método de criação de threads é útil se você quiser muitas threads que compartilham um objeto. Este exemplo demonstra a criação de um objeto runnable e, em seguida, a criação de uma thread associada a ele:

class ThreadBasica2 implements Runnable {
    // Este método(run()) é chamado quando a thread é iniciada
    public void run() {
    }
}

// Cria o objeto que contém o método run()
Runnable runnable = new ThreadBasica2(); 

// Cria uma thread que recebe o comportamento do objeto runnable
Thread thread = new Thread(runnable);

// Inicia a thread
thread.start();

OpenMP

OpenMP (Open Multi-Processing) é uma API para programação paralela de memória compartilhada em C, C++ e Fortran.

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[]) 
{
    int i, n;
    float a[100], b[100], sum; 

    /* Some initializations */
    n = 100;
    for (i=0; i < n; i++)
        a[i] = b[i] = i * 1.0;
    sum = 0.0;

    #pragma omp parallel for reduction(+:sum)
    for (i=0; i < n; i++)
        sum = sum + (a[i] * b[i]);

    printf("   Sum = %f\n",sum);
    return 0;
}

Entradas relacionadas: