Introdução ao processamento paralelo com o Grand Central Dispatch
-
Upload
flisolmaringa -
Category
Technology
-
view
922 -
download
0
Transcript of Introdução ao processamento paralelo com o Grand Central Dispatch
Introdução ao Grand Central Dispatch
Programação paralela
● O que é programação paralela?● Por que se preocupar com programação
paralela?● Melhor aproveitamento dos recursos de hardware;● Aumento do desempenho das aplicações (nem
sempre).
Processos e threads
● Processos: são programas em execução que ocupam uma região própria na memória e podem ser distribuídos para processadores pelo sistema operacional;
● Threads: são fluxos de execução de um mesmo processo que compartilham a região de memória do processo.
Processos e threads
● Criar um novo processo a partir de um processo existente consiste em alocar uma região nova de memória contendo uma cópia do processo criador;
● Criar uma thread consiste em alocar uma pequena região de memória contendo as informações da thread, o resto é compartilhado com o processo criador.
A libdispatch
A libdispatch
● Biblioteca criada pela Apple para facilitar a utilização de multiprocessamento nas aplicações;
● Abstrai o processo de criação e manutenção de threads;
● “Escreva menos código e faça mais”;
Blocks
● Extensão da linguagem C criada pela Apple e usada pelo GCD para encapsular tarefas.
typedef void (^UmBlocoVoid)();
UmBlocoVoid bloco = ^{
printf("Dentro de um Block\n");
int i;
for(i=0;i<100;i++){
printf("Exemplo %d\n", i);
}
};
Dispatch Queues
● São filas para onde as tarefas serão enviadas e, uma a uma, retiradas e processadas;
● O GCD disponibiliza 3 tipos de filas;● Main Queue (Serial);● Private Queue (Serial);● Global Queue (Concorrente);
Dispatch Queues (exemplo)
#include <dispatch/dispatch.h>
.
.
.
dispatch_queue_t fila1;
dispatch_queue_t fila2;
dispatch_queue_t fila3;
fila1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0);
fila2 = dispatch_queue_create(“queue label”, 0);
fila3 = dispatch_get_main_queue();
Executando tarefas
● Tarefas podem ser enviadas para as filas com as seguintes funcões:● dispatch_sync();● dispatch_async();● dispatch_apply();● dispatch_sync_f();● dispatch_async_f();● dispatch_apply_f().
Executando tarefas (exemplo)
dispatch_sync(queue, ^{
// Tarefa para ser processada de maneira síncrona
});
dispatch_async(queue, ^{
// Tarefa para ser processada de maneira assíncrona
});
Paralelizando loops
● Iterações de um loop podem ser paralelizadas com a função dispatch_apply():
dispatch_apply(ITERACOES, queue, ^(size_t i){
// loop
});
Grupos
● Permitem bloquear a execução do programa para esperar que uma ou mais threads terminem (join);
dispatch_group_t grupo = dispatch_group_create();
dispatch_queue_t fila = dispatch_get_global_queue(0, 0);
dispatch_group_async(grupo, fila, ^{
// bloco de execução
});
dispatch_group_wait(grupo, DISPATCH_TIME_FOREVER);
Semáforos
● Mecanismo de sincronização que possibilita a exclusão mútua e o controle do uso de recursos limitados;
dispatch_semaphore_t sema = dispatch_semaphore_create(1);
…
dispatch_async(fila, ^{
…
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
// Região crítica
dispatch_semaphore_signal(sema);
});
Dispatch Sources
● Mecanismo criado para detectar e processar eventos do sistema;
● Um dispatch source pode substituir os recursos nativos de tratamento assíncrono de eventos (poll, epoll, kqueue e etc);
● Um dispatch source permite:● Criar timers;● Monitorar sinais enviados pelo sistema;● Monitorar descritores de arquivos;● Monitorar processos (exit, fork, exec e etc).
Dispatch Sources (exemplo)
● Criando um timer:dispatch_queue_t queue = dispatch_get_global_queue(0, 0); dispatch_source_t timer = dispatch_source_create(
DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(timer, 0ull, 1ull * NSEC_PER_SEC,
1ull * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{ printf("Evento\n"); });
dispatch_resume(timer);
Dispatch Sources (exemplo)
● Criando um leitor de arquivo:int f = open("/etc/services", O_RDONLY|O_NONBLOCK);
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, f, 0, queue);
dispatch_source_set_event_handler(source, ^{
size_t resto = dispatch_source_get_data(source);
printf("Dados restantes %lu\n", resto);
read(f, dados, 1024);
});
dispatch_source_set_cancel_handler(source, ^{
close(f);
});
dispatch_resume(source);
Perguntas?
Referências
● Mac OS forge - http://libdispatch.macosforge.org/
● Apache GCD MPM - http://libdispatch.macosforge.org/trac/wiki/apache
● GCD no FreeBSD - http://wiki.freebsd.org/GCD
● Concurrency Programming Guide -
http://developer.apple.com/library/mac/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html
● Grand Central Dispatch (GCD) Reference -
http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html
● Blocks Programming Topics
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html#//apple_ref/doc/uid/TP40007502