50
Programação em Memória Partilhada com o Pthreads Ricardo Rocha Departamento de Ciência de Computadores Faculdade de Ciências Universidade do Porto Computação Paralela 2015/2016 R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 1 / 50

Programaçãoem MemóriaPartilhada comoPthreadsricroc/aulas/1516/cp/...Programaçãoem MemóriaPartilhada comoPthreads RicardoRocha Departamento de Ciência de Computadores Faculdade

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

  • Programação emMemória Partilhadacom o Pthreads

    Ricardo Rocha

    Departamento de Ciência de ComputadoresFaculdade de CiênciasUniversidade do Porto

    Computação Paralela 2015/2016

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 1 / 50

  • Concorrência ou Paralelismo Potencial

    Concorrência ou paralelismo potencial diz-se quando um programa possuitarefas que podem ser executadas em qualquer ordem sem alterar oresultado final.

    Uma razão óbvia para explorar concorrência é conseguir reduzir o tempode execução dos programas em máquinas multiprocessador e/oumulticore. Existem, no entanto, outras situações em que o paralelismopotencial de um programa pode ser explorado: ocorrência assíncrona deeventos, escalonamento de tarefas em tempo-real, operações de I/O, etc.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 2 / 50

  • Concorrência com Processos

    Heap

    Data

    Text

    Stack

    Recursos

    Identidade

    ...

    ...

    ...pid= fork()......

    FilesSockets...

    PID= 1000UIDGID...

    ...Registos

    SPPC...

    Heap

    Data

    Text

    Stack

    Recursos

    Identidade

    ...

    ...

    ...pid= fork()......

    FilesSockets...

    PID= 1001UIDGID...

    ...Registos

    SPPC...

    Processo Pai Processo Filho

    var1var2pid= 0

    var1var2pid= 1001

    fork()

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 3 / 50

  • Concorrência com Processos Multithreaded

    Heap

    Data

    Text

    Stack

    Stack

    Resources

    Identity

    Registers

    ...

    var1var2

    start()...task_one()...task_two()...terminate()...

    task_one()start()

    task_two()

    FilesLocksSockets...

    PIDUIDGID...

    SPPC...

    ...

    Registers SPPC...Thread 1

    Thread 2

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 4 / 50

  • Processos Multithreaded

    Um thread representa um fluxo de execução sequencial dentro doprocesso.

    A cada thread está associado uma pilha de execução (stack) e umconjunto de registos de contexto, tais como o stack pointer e oprogram counterOs restantes recursos do processo são partilhados pelo conjunto dosthreads: espaço de endereçamento, ficheiros abertos, identidade doutilizador, ...

    Processo = Conjunto de Threads + Conjunto de Recursos

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 5 / 50

  • Execução de Processos Multithreaded

    Todos os threads de um processo podem ser executados concorrentementee em diferentes processadores/cores.

    tempo

    CPU

    CPU

    P1

    P2

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 6 / 50

  • Multithreading

    Vantagens e inconvenientes:(+) Facilita a estruturação dos programas pois grande parte dosprogramas são intrinsecamente estruturados em múltiplas unidades deexecução(+) Elimina espaços de endereçamento múltiplos, permitindo reduzira carga de memória do sistema e melhorar o tempo de resposta dosprogramas(+) A partilha do espaço de endereçamento permite utilizarmecanismos de sincronização mais eficientes e trocas de contextoentre threads mais rápidas do que entre processos(–) A partilha transparente de recursos exige do programadorcuidados redobrados de sincronização

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 7 / 50

  • O Modelo POSIX Threads (Pthreads)

    Como é que um programa pode ser desenhado para executar múltiplosthreads dentro de um processo?

    É necessário um modelo de execução que suporte a criação emanipulação de tarefas cuja execução possa ser intercalada eexecutada concorrentemente. Os modelos mais conhecidos sãoPOSIX Threads, Windows Threads e Java Threads

    Aqui, iremos focar em detalhe o modelo Pthreads que pertence à famíliaPOSIX (Portable Operating System Interface):

    As definições da biblioteca Pthreads encontram-se em pthread.h e asua implementação em libpthread.so. Para compilar um programacom threads é necessário incluir o cabeçalho #include no início do programa e compilá-lo com a opção -pthread

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 8 / 50

  • Criação de Threads

    Quando se inicia um programa, um thread é desde logo criado (mainthread). Outros threads podem ser criados através de:

    int pthread_create(pthread_t *th, pthread_attr_t *attr,void * (*start_routine)(void *), void *arg)

    pthread_create() cria um novo thread que inicia a sua execução nafunção indicada por start_routine com o argumento indicado em arg.Em caso de sucesso instancia th com o identificador do novo thread eretorna 0, senão retorna um código de erro.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 9 / 50

  • Criação de Threads

    int pthread_create(pthread_t *th, pthread_attr_t *attr,void * (*start_routine)(void *), void *arg)

    th é o identificado do novo threadattr permite especificar atributos de como o novo thread deveinteragir com o resto do programa. Se NULL o novo thread é criadocom os atributos por omissão. Os threads possuem atributos comopolítica de escalonamento, prioridade, tipo de estado, etc, que podemser definidos posteriormente por invocação de funções adequadas,como por exemplo pthread_attr_setdetachstate()start_routine é a função inicial que o novo thread deve executararg é o argumento único a passar à função start_routine(múltiplos argumentos podem ser passados recorrendo a umaestrutura de dados e utilizando o endereço da estrutura como únicoargumento)

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 10 / 50

  • Junção de Threads (ou Sincronização Bloqueante)

    Tal como com os processos, por vezes é necessário esperar que um dadothread termine antes de continuar a execução. Com processos essasincronização é conseguida pelas funções wait() ou waitpid(). Comthreads a função é pthread_join().

    int pthread_join(pthread_t th, void **thread_return)

    pthread_join() suspende a execução até que o thread th termine.Assim que termine, thread_return é instanciado com o valor de retornode th e pthread_join() retorna 0, senão retorna um código de erro.

    th é o identificador do thread a esperar que terminethread_return é o valor de retorno do thread th (indicar NULL se ovalor de retorno for desprezável)

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 11 / 50

  • Terminar Threads

    Existem várias formas de um thread terminar:A função que iniciou o thread retornaA função main() retorna ou algum thread chama a função exit()(nestes 2 casos todos os threads terminam)O thread invoca diretamente a função pthread_exit()

    void pthread_exit(void *retval)

    pthread_exit() termina o thread correnteretval é o valor de retorno do thread

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 12 / 50

  • Joinable Threads x Detached Threads

    Um thread pode estar num dos seguintes estados: joinable ou detached.O estado de um thread apenas condiciona o modo como este termina.

    Quando um joinable thread termina, parte do seu estado é mantidopelo sistema (identificador do thread e stack) até que um outrothread chame pthread_join() para obter o seu valor de retorno. Sóentão os recursos do thread são totalmente libertados.Os recursos de um detached thread são totalmente libertados logoque este termina. Qualquer chamada posterior a pthread_join()retorna um erro.Um thread pode ser criado como joinable ou como detached (veratributos da função pthread_create()). Por omissão, os threadssão criados como joinable. É também possível mudar dinamicamenteo estado do thread para detached.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 13 / 50

  • Joinable Threads x Detached Threads

    int pthread_detach(pthread_t th)

    pthread_detach() permite mudar o estado de um thread para detached.Retorna 0 se OK, valor positivo se erro.

    th é o identificador do thread a colocar detached

    pthread_t pthread_self(void)

    pthread_self() retorna o identificador do thread corrente.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 14 / 50

  • Sequência de Utilização Básica

    pthread_t th[NTHREADS];float result[NTHREADS];

    main() {...// main thread launches a set of threadsfor (i = 0; i < NTHREADS; i++)

    pthread_create(&th[i], NULL, thread_main, (void *) i);// main thread waits for all other threads to completefor (i = 0; i < NTHREADS; i++)

    pthread_join(th[i], NULL);// do something with the results...

    }

    void *thread_main(void *id_ptr) {long id = (long) id_ptr;...result[id] = ...; // save thread result in global array result[]return NULL;

    }

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 15 / 50

  • Cuidados na Utilização de Threads

    Passar endereços de variáveis em pthread_create() pode ser perigoso!

    main() {...// main thread launches a set of threadsfor (i = 0; i < NTHREADS; i++)

    pthread_create(&th[i], NULL, thread_main, (void *) &i);...

    }

    void *thread_main(void *id_ptr) {long id = *((long *) id_ptr);...

    }

    A variável i pode ser alterada no main thread antes de ser lida pelo novothread!

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 16 / 50

  • Cuidados na Utilização de Threads

    Retornar diretamente o valor calculado nem sempre é possível!

    main() {float thread_result;...// main thread waits for all other threads to completefor (i = 0; i < NTHREADS; i++)

    pthread_join(th[i], (void **) &thread_result);...

    }

    void *thread_main(void *id_ptr) {float result;...// gcc error: cannot convert to a pointer typereturn ((void *) result);

    }

    Se o valor a retornar for por exemplo do tipo float, o compilador nãoconsegue converter para um apontador.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 17 / 50

  • Cuidados na Utilização de Threads

    Retornar endereços de variáveis locais pode originar erros ou segmentationfault!

    main() {float *thread_result;...// main thread waits for all other threads to completefor (i = 0; i < NTHREADS; i++)

    pthread_join(th[i], (void **) &thread_result);...

    }

    void *thread_main(void *id_ptr) {float result;...// gcc warning: function returns address of local variablereturn ((void *) &result);

    }

    Como a função termina, o endereço de memória da variável local resultfica fora de âmbito.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 18 / 50

  • Cuidados na Utilização de Threads

    Mesmo utilizando a função pthread_exit() o problema acontece!

    void *thread_main(void *id_ptr) {float result;...pthread_exit((void *) &result);...

    }

    O endereço de memória da variável local result fica igualmente fora deâmbito quando o main thread sincroniza através da chamada apthread_join().

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 19 / 50

  • Sincronização e Regiões Críticas

    A principal causa da ocorrência de erros na programação de threads estárelacionada com o fato dos dados serem todos partilhados. Apesar de esteser um aspetos mais poderosos da utilização de threads, também pode serum dos mais problemáticos.

    O problema existe normalmente quando dois ou mais threads tentamaceder/alterar as mesmas estruturas de dados (race conditions, i.e., oresultado depende da ordem em que os acessos ocorrem).

    Existem dois mecanismos principais de sincronização:Mutexs: para situações de curta duraçãoVariáveis de Condição: para situações em que o tempo de esperanão é previsível (pode depender da ocorrência de um evento)

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 20 / 50

  • Mutexs

    Um mutex (MUTual EXclusion) é um lock que apenas pode estar naposse de um thread de cada vez, garantindo exclusão mútua. Osrestantes threads que tentem aceder ao lock ficam bloqueados até que esteseja libertado.

    int pthread_mutex_init(pthread_mutex_t *mutex,pthread_mutexattr_t *mutexattr)

    pthread_mutex_init() inicia um mutex. Retorna 0 se OK, valorpositivo se erro.

    mutex é a variável que representa o mutexmutexattr permite especificar atributos do mutex (se NULL o mutexé iniciado com os atributos por omissão)

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 21 / 50

  • Mutexs

    Quando um mutex é alocado estaticamente, este também pode seriniciado (com os atributos por omissão) utilizando a macroPTHREAD_MUTEX_INITIALIZER.

    // mutex statically allocatedpthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

    // mutex dynamically allocatedstruct {

    pthread_mutex_t mutex;...

    } *xpto;...xpto = malloc(...);pthread_mutex_init(&xpto->mutex, NULL);

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 22 / 50

  • Operações sobre Mutexs

    Obter o lock no mutex:

    int pthread_mutex_lock(pthread_mutex_t *mutex)

    Libertar o lock:

    int pthread_mutex_unlock(pthread_mutex_t *mutex)

    Faz tentativa de obter o lock mas não bloqueia caso não seja possível:

    int pthread_mutex_trylock(pthread_mutex_t *mutex)

    Todas as funções retornam 0 se OK, valor positivo se erro. mutex é avariável que representa o mutex.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 23 / 50

  • Atualização Exclusiva com Mutexs

    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;float result;

    main() {...// main thread launches a set of threadsfor (i = 0; i < NTHREADS; i++)

    pthread_create(&th[i], NULL, thread_main, (void *) i);// main thread waits for all other threads to completefor (i = 0; i < NTHREADS; i++)

    pthread_join(th[i], NULL);// do something with the result...

    }

    void *thread_main(void *id_ptr) {...pthread_mutex_lock(&mutex);result = ...; // update global result with thread’s partial resultpthread_mutex_unlock(&mutex);return NULL;

    }

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 24 / 50

  • Fila de Tarefas com Mutexs I

    pthread_mutex_t flag_mutex = PTHREAD_MUTEX_INITIALIZER;int flag_is_set = FALSE;

    void *thread_main(void *thread_arg) {while (TRUE) {

    pthread_mutex_lock(&flag_mutex);if (flag_is_set) {

    get_task();if (no_more_tasks()) flag_is_set = FALSE;pthread_mutex_unlock(&flag_mutex);do_work();

    } elsepthread_mutex_unlock(&flag_mutex);

    }}

    void new_task() {pthread_mutex_lock(&flag_mutex);put_task();flag_is_set = TRUE;pthread_mutex_unlock(&flag_mutex);

    }

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 25 / 50

  • Fila de Tarefas com Mutexs II

    pthread_mutex_t flag_mutex = PTHREAD_MUTEX_INITIALIZER;int flag_is_set = FALSE;

    void *thread_main(void *thread_arg) {while (TRUE) {

    // while no available tasks, busy wait but without lockingwhile (flag_is_set == FALSE);pthread_mutex_lock(&flag_mutex);if (flag_is_set) {

    get_task();if (no_more_tasks()) flag_is_set = FALSE;pthread_mutex_unlock(&flag_mutex);do_work();

    } elsepthread_mutex_unlock(&flag_mutex);

    }}

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 26 / 50

  • Variáveis de Condição

    Os mutexs permitem prevenir acessos simultâneos a variáveis partilhadas.No entanto, por vezes o uso de mutexs pode ser bastante ineficiente. Sepretendermos realizar uma dada tarefa apenas quando uma dada variáveltome um certo valor, temos que consultar sucessivamente a variável atéque esta tome o valor pretendido.

    Em lugar de testar exaustivamente uma variável, o ideal seria adormecer othread enquanto a condição pretendida não sucede. As variáveis decondição permitem adormecer threads até que uma dada condiçãosuceda.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 27 / 50

  • Variáveis de Condição

    Ao inverso dos semáforos, as variáveis de condição não têm contadores.Se um thread A sinalizar uma variável de condição antes de um outrothread B estar à espera, o sinal perde-seO thread B ao sincronizar mais tarde nessa variável, deverá ficar àespera que um outro thread volte a sinalizar a variável de condição

    int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr)

    pthread_cond_init() inicia uma variável de condição. Retorna 0 se OK,valor positivo se erro.

    cond representa a variável de condiçãocond_attr permite especificar atributos da variável de condição (seNULL é iniciada com os atributos por omissão)

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 28 / 50

  • Variáveis de Condição

    Quando uma variável de condição é alocada estaticamente, estatambém pode ser iniciada (com os atributos por omissão) utilizando amacro PTHREAD_COND_INITIALIZER.

    // condition variable statically allocatedpthread_cond_t cond = PTHREAD_COND_INITIALIZER;

    // condition variable dynamically allocatedstruct {

    pthread_cond_t cond;...

    } *xpto;...xpto = malloc(...);pthread_cond_init(&xpto->cond, NULL);

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 29 / 50

  • Sinalizar uma Variável de Condição

    int pthread_cond_signal(pthread_cond_t *cond)

    pthread_cond_signal() acorda um dos threads bloqueados na variávelcond. Caso existam vários threads bloqueados, apenas um é acordado(não é especificado qual).

    int pthread_cond_broadcast(pthread_cond_t *cond)

    pthread_cond_broadcast() acorda todos os threads que possam estarbloqueados na variável cond.

    Em ambos os casos, se nenhum thread estiver bloqueado na variávelespecificada, nada acontece. Ambas as funções retornam 0 se OK, valorpositivo se erro.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 30 / 50

  • Bloquear numa Variável de Condição

    A uma variável de condição deve estar sempre associado um mutexde modo a garantir que entre o testar de uma dada condição e o ativar daespera sobre uma variável de condição, nenhum outro thread sinaliza avariável de condição, o que poderia originar a perca desse mesmo sinal.

    int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex)

    De um modo atómico, pthread_cond_wait() liberta o mutex (tal comose executasse pthread_mutex_unlock()) e bloqueia na variável decondição cond até que esta seja sinalizada. Isto requer, obviamente, quese obtenha o lock sobre o mutex antes de invocar a função.

    Quando a variável é posteriormente sinalizada e o thread é acordado,pthread_cond_wait() readquire o lock no mutex (tal como seexecutasse pthread_mutex_lock()) e só depois regressa à execução.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 31 / 50

  • Fila de Tarefas com Variáveis de Condição

    pthread_cond_t flag_cond = PTHREAD_COND_INITIALIZER;pthread_mutex_t flag_mutex = PTHREAD_MUTEX_INITIALIZER;int flag_is_set = FALSE;

    void *thread_main(void *thread_arg) {while (TRUE) {

    pthread_mutex_lock(&flag_mutex);// while no available tasks, block on condition variablewhile (flag_is_set == FALSE)

    pthread_cond_wait(&flag_cond, &flag_mutex);get_task();if (no_more_tasks()) flag_is_set = FALSE;pthread_mutex_unlock(&flag_mutex);do_work();

    }}

    void new_task() {pthread_mutex_lock(&flag_mutex);put_task(); flag_is_set = TRUE;pthread_cond_signal(&flag_cond);pthread_mutex_unlock(&flag_mutex);

    }R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 32 / 50

  • Thread-Specific Data

    Existem duas soluções básicas para associar dados a um thread durantetoda a execução:

    Guardar os dados numa estrutura global associada com o threadPassar os dados como argumento em todas as funções que o threadinvoque

    No entanto, em algumas circunstâncias, nenhuma das soluções funciona.Vejamos o que acontece se pretendermos reescrever uma biblioteca oumódulo de funções para suportar multithreading (thread-safe functions).

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 33 / 50

  • Thread-Specific Data

    long fd;

    init_module(...) {...fd = open("file.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);...

    }

    use_module(...) {...write(fd, ...);...

    }

    Problema: Por um lado não queremos redefinir os argumentos dasfunções e por outro lado não sabemos o número adequado de variáveis ouestruturas globais a utilizar (variáveis fd no exemplo).

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 34 / 50

  • Chaves

    Para resolver este problema, o Pthreads introduz o conceito de chave,i.e., um tipo de apontador que associa dados com threads. Durantea execução, todos os threads referem a mesma chave, mas cada um acedea dados diferentes.

    int pthread_key_create(pthread_key_t *key,void (*destr_function) (void *))

    pthread_key_create() aloca em todos os threads uma nova chaveidentificada por key e inicia-a com NULL. Se novos threads forementretanto criados, todas as chaves existentes são igualmente alocadaspara os novos threads e iniciadas com NULL.

    key é o identificador da chave a alocardestr_function, se não NULL, especifica a função a ser executadano caso do thread corrente terminar, em que o argumento da função éo valor associado com key

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 35 / 50

  • Iniciação Única

    int pthread_once(pthread_once_t *once_control,void (*init_routine) (void))

    pthread_once() é um mecanismo que permite garantir que umdeterminado código de iniciação não é executado mais do que uma vez. Aprimeira vez que pthread_once() é invocado para um dado argumentode controle once_control, a função init_routine é executada.Chamadas subsequentes a pthread_once() com o mesmo argumento decontrole não fazem nada.

    once_control é o argumento de controle (deve ser estaticamenteiniciado com PTHREAD_ONCE_INIT)init_routine é a função a executar não mais do que uma vez

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 36 / 50

  • Operações com Chaves

    int pthread_setspecific(pthread_key_t key, const void *pointer)

    pthread_setspecific() instancia a chave key do thread corrente com ovalor pointer.

    void * pthread_getspecific(pthread_key_t key)

    pthread_getspecific() retorna o valor associado com a chave key dothread corrente.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 37 / 50

  • Thread-Specific Data (pthreads-modulekey.c)

    pthread_once_t fd_once = PTHREAD_ONCE_INIT;pthread_key_t fd_key;

    init_module( ... ) {long fd;...pthread_once(&fd_once, module_once);sprintf(filename, "file_t%d.log", (int) pthread_self());fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);pthread_setspecific(fd_key, (void *) fd);...

    }

    use_module( ... ) {long fd = (long) pthread_getspecific(fd_key);...write(fd, ...);...

    }

    void module_once(void) { pthread_key_create(&fd_key, module_destr); }void module_destr(void *fd) { close((long)fd); }

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 38 / 50

  • Implementações de Threads

    As implementações de threads podem dividir-se em 3 categorias:User ThreadsKernel ThreadsTwo-Level Scheduler Threads

    Cada uma das implementações condiciona de modo diferente o modo deescalonamento e performance dos threads de um programa. No entanto,todas disponibilizam alguma forma de concorrência.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 39 / 50

  • User Threads

    São executados e geridos no espaço do utilizador, no âmbito de umprocesso, sem estarem visíveis para o kernel do sistema.

    A biblioteca implementa toda a política de escalonamento e multiplexagemdos contextos de execução. O kernel não tem a noção de threads,continua apenas a escalonar processos.

    Exemplos de implementações:Solaris Green ThreadsGNU Portable Threads

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 40 / 50

  • User Threads

    2 CPUsKernel

    SchedulerProcesses

    Threads Scheduler

    Threads Scheduler

    Threads Scheduler

    running

    running

    runnable

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 41 / 50

  • User Threads

    Vantagens e inconvenientes:(+) São mais fáceis de implementar pois não interferem com o kernel.(+) São bastante eficientes, pois não envolvem o kernel parasincronização.(+) São escalares, pois a criação de mais threads não sobrecarrega osistema.(–) Threads de um mesmo processo competem entre si pelo tempode CPU e não entre todos os threads/processos existentes no sistema.(–) Em máquinas multiprocessador/multicore não é possível terthreads de um mesmo processo em paralelo.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 42 / 50

  • Kernel Threads

    São executados e geridos pelo kernel como se fossem processos.

    O kernel é o responsável pela multiplexagem do contexto de execução decada thread. Como tal, alguma informação tradicionalmente associada aprocessos, como sejam a prioridade de escalonamento, atribuição de CPUpara execução, conjunto de registos guardados, é igualmente necessáriapara gerir threads.

    Exemplos de implementações:LinuxWindows NT/XP/2000Solaris (versão 9 e posteriores)

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 43 / 50

  • Kernel Threads

    2 CPUsKernel

    SchedulerProcesses

    Threads Library

    Threads Library

    Threads Library

    runnable

    running

    runnable

    runnable

    runnable

    running

    runnable

    runnable

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 44 / 50

  • Kernel Threads

    Vantagens e inconvenientes:(+) Todos os threads do sistema competem entre si pelo tempo deCPU e não entre os threads do mesmo processo.(+) Em máquinas multiprocessador/multicore é possível executarthreads de um mesmo processo em paralelo.(–) Requer um maior esforço de implementação.(–) Apesar de menos dispendiosa que a criação de um processo, acriação e manutenção de novos threads acarreta algum custo aosistema. Este custo pode ser desnecessário se o nosso programa nãocorrer em máquinas multiprocessador/multicore (provavelmente userthreads seria suficiente).(–) São menos escalares, já que o manuseamento de bastantesthreads pode degradar consideravelmente a performance do sistema.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 45 / 50

  • Two-Level Scheduler Threads

    São executados e geridos em cooperação entre a biblioteca dethreads e o kernel. Ambos mantêm estruturas de dados para representaruser e kernel threads respetivamente.

    Utiliza dois níveis de controlo em que conjuntos de user threads sãomapeados sobre kernel threads que por sua vez são escalados paraexecução nos processadores/cores do sistema. O programador escreve oseu programa em termos de user threads e pode especificar quantos kernelthreads vão estar associados ao processo.

    Exemplos de implementações:Solaris (anteriores a versão 9)Windows ThreadFiber package (NT/2000)

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 46 / 50

  • Two-Level Scheduler Threads

    2 CPUsKernel

    SchedulerProcesses

    Threads Scheduler

    Threads Scheduler

    Threads Scheduler

    running

    running

    runnable

    runnable

    runnable

    blocked

    blocked

    blocked

    blocked blocked

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 47 / 50

  • Two-Level Scheduler Threads

    Vantagens e inconvenientes:(+) O melhor dos dois mundos: boa performance e baixos custos decriação/manutenção.(–) Complexidade do sistema que se reflete quando o programadornecessita de fazer debugging.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 48 / 50

  • Processos x Threads

    Todos os threads num programa executam o mesmo executável. Umprocesso filho pode executar um programa diferente se invocar a chamadaao sistema exec().

    A memória a copiar na criação de um novo processo acrescenta um pesomaior ao sistema do que na criação de um novo thread. No entanto, acópia é retardada o mais possível e apenas é efetuada quando a memória éalterada por um dos processos (copy-on-write). Isto diminui, de certaforma, o custo a pagar nos casos em que o processo filho apenas lê dadosou invoca de imediato a chamada ao sistema exec().

    A utilização de processos é mais indicada para problemas de granularidadegrossa/média, enquanto que os threads são mais indicados para problemasde granularidade fina.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 49 / 50

  • Processos x Threads

    Partilhar dados entre threads é trivial porque estes partilham a mesmamemória. Partilhar dados entre processos requer a utilização de uma dastécnicas de comunicação entre processos (IPC). Apesar de mais penoso,isso torna a utilização de múltiplos processos menos suscetível de erros deconcorrência.

    Um thread vagabundo pode corromper as estruturas de dados de todos osoutros threads. Um processo vagabundo não consegue fazer isso porque oseu espaço de endereçamento é privado.

    R. Rocha (DCC-FCUP) Programação com o Pthreads Computação Paralela 15/16 50 / 50