Lista 1 Resolvida

De BCC Wiki

Lista: Lista 1 PDF

Tabela de conteúdo

Exercício 1

a

Versão com Threads

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define N ? /* Define o valor de N, substituir ? */

int array[N];

int c = 0;

pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;

void soma(int x){
        /* Regi�o Cr�tica */
        pthread_mutex_lock(&mut);
        c = c + array[x];
        pthread_mutex_unlock(&mut);
}

int main(){
        int i;
        pthread_t ids[N];

        /* Inicializa o vetor para testes
        for (i = 0; i < N; i ++){
        array[i] = i;
}*/

        for (i = 0; i < N; i++){
                pthread_create(&ids[i],NULL,soma,i);
        }

        for (i = 0; i < N; i++){
                pthread_join(ids[i],NULL);
        }

        printf("Results is %d\n",c);

        return 0;
}


Versão com OpenMP

#pragma omp parallel for reduction(+:c)
for (c=i=0; i < N; i++)
{
        c = c + a[i];
}

Exercício 2

(a) O número máximo de processadores é 3, porque as linhas 3-5, 6-8 e 9-10 não têm dependências verdadeiras então podem ser paralelizadas, a sequência de execução pode ser

thread  1   2   3
1
2
3 4 5
sync 6 7 8
sync 9 10 11
sync 12

havendo sincronização antes de cada linha marcada com sync

Fiz de outra maneira, usando Ordenação Topológica

thread 1 2 3

       1        
2 4 7
8 3 5
9 6 10
11 12

(b) O tempo de execução é 6, dado pelo número de linhas da tabela anterior

(c) A aceleração é S(3) = T(1) / (ts + tp/3) => S(3) = 12 / (3 + 9/3) = 12 / 6 = 2

Exercício 3

É chamada de verdadeira porque é a única que não pode ser desfeita. A anti-depêndencia pode ser desfeita inserindo uma nova variável, por exemplo

c = a + d;
a = b;

pode virar uma dependência verdadeira inserindo a variável k

k = a;
a = b;
c = k + d;

e a dependência de saída se vier sozinha não faz sentido e pode ser desfeita facilmente
Por exemplo:

a = b;
a = c;

é uma dependência de saída que pode ser trocado por

a = c;

Se não estiver sozinha ela vem acompanhada das outras duas depêndencias
Por exemplo:

a = b;
k = a + 3;
a = c;

Que é transformado numa dependência verdadeira usando o mesmo mecanismo da anti-paralela

a = b;
d = a;
a = c;
k = d + 3;

Exercício 4

O custo correspondente na memória compartilhada é dado pelo barramento da memória, de quão rápido os dados são enviados da memória sendo compartilhada até o cache do processador que vai executar o trecho de código

Exercício 5

To-Do

Exercício 6

Os programas Embarrasing Parallel são programas que não é necessário nenhum grande empenho em segmentar o programa em um grande número de tarefas paralelizáveis e não há nenhuma dependência essencial entre estas tarefas paralelizáveis.

Exercício 7

To-Do

Exercício 8

To-Do

Exercício 9

Semáforo x Busy Waiting

Um Busy Waiting faz uma verificação repetidamente para a modificação de uma determinada variável ou recurso. Um exemplo é a captura de eventos de um teclado ou a espera por uma trava se destravar.

Um semáforo recebe um valor máximo de quantos processos podem acessar um recurso e consiste de duas operações: wait e signal. O wait decrementa o valor do semáforo, e se este valor for 0, o processo é posto para dormir. O signal incrementa o valor do semáforo. Se o valor for 0, e houver algum processo dormindo, acorda o processo adormecido. Caso contrário, incrementa o valor do semáforo.

O Busy Waiting parece gastar mais CPU, por se tratar de uma verificação "exaustiva". Porém, no caso de um BW, a atualização acontece mais rápido.

Semáforo x Regiões Críticas Condicionais
Monitores x Regiões Críticas Condicionais
Ferramentas pessoais