Buscar

Relatório Programação Multithread

Prévia do material em texto

INSTITUTO FEDERAL DO ESPÍRITO SANTO 
 
 
BACHARELADO EM SISTEMA DE INFORMAÇÃO 
 
AUGUSTO COELHO 
JEAN CARLOS PENAS 
SISTEMAS OPERACIONAIS 
 
 
 
 
 
 
 
 
 
 
 
SERRA 
2015 
P a g i n a 2 
 
 
AUGUSTO COELHO 
JEAN CARLOS PENAS 
SISTEMAS OPERACIONAIS 
 
 
 
 
 
 
Trabalho apresentado no curso de 
Bacharelado em Sistemas De Informação, 
Na disciplina Sistemas Operacionais no 
Instituto Federal do Espírito Santo 
Professor: Flavio Giraldeli 
 
 
 
 
 
 
 
 
 
SERRA 
2015 
 
 
P a g i n a 3 
 
Resumo 
O relatório está recheado de diversos conceitos que foram identificados em um 
algoritmo que trabalha com um conjunto de números naturais aleatórios de 0 a 29999 das 
quais serão escritos em cada campo de uma matriz N x M tal que N e M fazem parte do 
conjunto dos números naturais não nulos de modo que a matriz possa ser dividida em 
pequenos blocos de mesmo tamanho chamadas de macro blocos que durante a execução do 
algoritmo são varridos por N threads criadas por um processo. 
Vimos que um processo é nada mais nada menos que uma entidade ativa com a penas 
um fluxo de execução e que este poderá criar vários fluxos chamados de threads que segundo 
Silberschatz trazem diversos benefícios como responsividade, compartilhamento de recursos, 
economia e o proveito das arquiteturas multiprocessadas. 
Nós mostramos como os programas usufruem da programação paralela por meio da 
criação de diversas threads e desta forma concluímos como o sistema operacional administra 
os seus recursos utilizando essa mesma tecnologia só que em níveis mais complexos e 
também as consequências que ela traz quando usada de forma indiscriminada. Além disto, 
através de um algoritmo na linguagem C identificamos muitos conceitos visto em sala de aula 
dentre eles as regiões críticas, técnicas para tratar problemas de sincronismo e conceitos sobre 
os estados das threads cuja chamadas estão implícitas nas API’s da linguagem que vamos 
trabalhar e uma série de recursos inclusive estruturas que são compartilhadas entre elas por 
meio da thread principal. 
 
 
 
 
 
 
 
 
 
P a g i n a 4 
 
Abstract 
The report is full of many concepts that were identified in an algorithm that works 
with a random set of natural numbers 0-29999 of which will be written in each field of an N x 
M matrix such that N and M are part of the set of numbers natural non-null so that the array 
can be divided into small blocks of equal size called macro blocks for implementing the 
algorithm are swept by N threads created by a process. 
We have seen that a process is nothing more nor less than an active entity with feathers 
a thread, and that this can create multiple streams called threads that according Silberschatz 
bring many benefits such as responsiveness, resource sharing, economy and advantage of 
multiprocessor architectures . 
We show how the programs enjoy the parallel programming through the creation of 
several threads and thus conclude how the operating system manages its resources using the 
same technology but in more complex levels and also the consequences that it brings when 
used indiscriminately . In addition, through an algorithm in C identified many concepts seen 
in class among them the critical regions, techniques to address timing issues and concepts 
about the states of the threads whose calls are implied in the API's of the language that will 
work and a number of features including structures that are shared between them through the 
main thread. 
 
 
 
 
 
 
 
 
 
 
P a g i n a 5 
 
ILUSTRAÇÕES 
 
 
Tabela 1 - Configurações Básicas Dos Computadores Usados Nos Testes. ............................. 10 
 
Gráfico 1 – Tempo Dos Testes Com Matriz De 1000x1000, Blocos De 5x5. .......................... 11 
Gráfico 2 – Gráfico Do Percentual De Ganho do Algoritmo Nos Testes. ................................ 11 
Gráfico 3 - Testes Com Matrizes Cujo Macro Blocos São Maiores......................................... 12 
 
Figura 1 - Declaração Das Variáveis Globais do Algoritmo. ................................................... 12 
Figura 2 – Protegendo as regiões críticas do Algoritmo. .......................................................... 13 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
P a g i n a 6 
 
 
SUMÁRIO 
 
INTRODUÇÃO .......................................................................................................................... 7 
PROCESSOS .............................................................................................................................. 8 
THREADS .................................................................................................................................. 9 
QUEBRANDO PARADIGMAS ................................................................................................ 9 
SINCRONIZAÇÃO ................................................................................................................. 12 
O ALGORITMO ...................................................................................................................... 14 
CONCLUSÃO .......................................................................................................................... 15 
REFERÊNCIAS BIBLIOGRÁFICAS ..................................................................................... 18 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
P a g i n a 7 
 
 
INTRODUÇÃO 
 
 
Atualmente quase todos os sistemas operacionais modernos possuem arquiteturas 
multiprocessadas, isto é uma consequência de uma mudança de organização do processador, 
mudança que chamamos hoje de multiprocessamento. Mas as arquiteturas MP também são 
uma consequência de outro fato, a era da informação com a necessidade de processar dados 
em grandes escalas que segundo a Universidade Federal De Santa Catarina inclui a 
necessidade de aumentar funcionalidades, interfaces gráficas, comunicação, carga, números 
de usuários, tempo de resposta e confiabilidade. 
 Foi graças a uma série de modificações que foram acontecendo nas últimas décadas 
nos níveis da organização e arquitetura computacional, como o nível lógico digital, micro 
arquitetura, arquitetura de instruções, sistema operacional, linguagem assembly e linguagem 
de auto nível que foi possível a implementação dos processadores MP que aconteceu 
exatamente no primeiro nível (Nível lógico digital), que segundo a Universidade Federal De 
Campina Grande é o nível em que as portas lógicas são combinadas para formar os 
registradores e principalmente o processador, este por sua vez é o componente principal e que 
de fato é o primeiro componente a sofrer as mudanças para tornar a programação paralela 
possível. O resultado dessas mudanças é o que tornou possível a construção de processadores 
de múltiplos núcleos que possuem unidades de processamento em um único processador e 
ainda aqueles com tecnologias Hiperthread, que para cada 1 núcleo físico simula 1 lógico. 
 A programação paralela ou concorrente é um mecanismo que consiste em executar de 
forma simultânea várias partes de uma mesma aplicação (em alguns contextos paralelismo e 
concorrência possuem significados distintos). Umas das condições para que o paralelismo 
utilizando threads funcione já foi satisfeita que são as questões que envolve a arquitetura e a 
organização do computador, ou seja, já temos um processador que possui tecnologia MP e 
também bibliotecascom diversas API’s para aplicar o conceito da programação paralela como 
a POSIX PThreads, a outra condição é que o problema que será modelado tenha possibilidade 
de ser dividido em partes que possam ser processadas de forma independente. Mas ao tentar 
modelar esse problema surgem outros desafios como a divisão de atividades que foca áreas do 
código que pode ou não ser dividido em tarefas separadas ou concorrentes. O equilíbrio, 
associado a importância de como dosar as atividades para que apresentam esforço 
P a g i n a 8 
 
computacional semelhante. A divisão de dados que se preocupa como os dados devem ser 
divididos para execução em núcleos separados. A dependência dos dados, que por sua vez cria 
a necessidade dos dados serem examinados para determinar as suas relações para que 
posteriormente possam ser feitas as sincronizações e, finalmente, a correção desses programas 
que também é um desafio pois possuem diversas linhas de execução e por este motivo a sua 
depuração se torna mais complexa. 
 
PROCESSOS 
 
 O processo é definido como uma entidade ativa, ou seja o código do programa sendo 
executado por um fluxo de execução. Durante o seu ciclo de execução ele terá diversos 
estados como Novo, Pronto, Executando, Esperando, Terminando e Interrompido e ficará 
migrando entre diversas filas. 
Cada processo possui por um bloco de controle de processo ou PCB que funciona 
como um repositório de dados. No PCB são encontradas informações como estado do 
processo, contador de programa, registradores, informações de escalonamento de CPU, 
informação de gerência de memória, informação contábil e informação de status de E/S. 
 Quando o estado do processo muda de pronto para executando é criada uma thread 
principal chamada de thread Pai (Alguns autores chamam de thread mãe). Com apenas uma 
thread o processo executa apenas uma tarefa por vez. Em todo o seu ciclo de vida o processo 
migra entre diversas filas e o seu estado variando conforme foi dito na introdução deste 
tópico. 
 Quando ocorre uma interrupção, o sistema operacional salva o contexto do processo 
atual que é o status do PCB em um determinado instante e então o SO atende a interrupção e 
volta para restaurar o contexto salvo do antigo processo para o novo, voltando ao ponto onde 
foi interrompido e executando as suas tarefas como se nada tivesse acontecido, este 
procedimento é chamado de troca de contexto e o tempo dessa troca é chamado de overhead 
(custo). Então os projetistas perceberam que ao criar vários processos para executar tarefas de 
forma simultânea gerava muito custo no sistema operacional (O custo pode estar atrelado 
desde o tempo de execução até a quantidade de memória ocupada), então a solução foi migrar 
para a utilização das threads, pois era mais fácil criar e fazer troca de contexto entre threads 
do que processos (Silberschartz – Sistemas Operacionais). 
P a g i n a 9 
 
THREADS 
 
 A thread, segundo Silberschartz é a unidade básica de utilização de CPU e possui um 
id exclusivo, um contador de programa que calcula o próximo endereço da instrução que será 
executada, um conjunto de registradores e uma pilha. Além disto, as estruturas da thread 
principal como a seção de código, dados e arquivos são compartilhados entre as threads filhas. 
Depois que as threads passaram a ser implementadas em programas de sistemas, 
aplicativos e softwares, os projetista de SO’s começaram identificar aspectos positivos da 
implementação, como a responsividade que se refere a capacidade da aplicação continuar 
funcionando mesmo que parte dela esteja bloqueada, a economia, pois perceberam que a 
alocação de recursos utilizando processos gerava muito custo e como as threads 
compartilhavam recursos do processo que as criou era mais econômico fazer troca de contexto 
entre elas. O compartilhamento de recursos foi outro ponto chave que tornou as threads a 
melhor opção na programação paralela, porque por padrão as threads já compartilhavam 
recursos como seção de código, dados e até mesmo os arquivos pertencentes ao processo que 
as criou, além disto em um dos artigos da Universidade Federal Do Rio De Janeiro revela que 
várias threads diferentes podem ser criadas dentro do espaço de endereço do processo que as 
criou. 
Devido a essas propriedades, as threads passaram a ser o melhor caminho para tornar 
os sistemas operacionais mais próximo dos objetivos do usuário e ao mesmo tempo aos de 
projeto. Mas como toda solução tem o seu grau de complexidade haveria um momento em 
que a criação indiscriminada de threads causaria uma queda de desempenho nas aplicações, 
então resolvemos conjecturar esta ideia no próximo tópico. 
 
 
QUEBRANDO PARADIGMAS 
 
 Se a utilização das threads trouxe tantos benefícios, porque não criar milhões de 
threads no sistema operacional para melhorar o seu rendimento ainda mais, é claro que 
existem limitações físicas quanto a isto, mas o maior problema ainda não é este. A Tabela 1 
abaixo mostras as configurações básicas de dois computadores para este tópico e por meio de 
um algoritmo paralelizado vamos explorar alguns aspectos e curiosidades dessa nova 
P a g i n a 10 
 
tecnologia no processamento de vários blocos dentro de uma matriz de números que variam 
entre 0 a 29999 contabilizando então a quantidade total de números primos. 
 
Tabela 1 - Configurações Básicas Dos Computadores Usados Nos Testes. 
 MOBILE DESKTOP 
Processador INTEL CORE I5 2.4 GHZ INTEL DUAL CORE 2.6 
Tamanho Memória 4 4 
 
 A princípio achávamos que quanto maior o número de threads trabalhando em vários 
blocos, menor seria o tempo do processamento de toda a matriz e consequentemente melhor o 
ganho, mas não foi o que esperávamos. O tempo tende a diminui consideravelmente nos 
primeiros testes com N threads maior ou igual a 2, mas a duração do processamento com 
números de threads na ordem de dezenas e centenas teve uma duração que divergia muito 
pouco em relação aos testes envolvendo números menores. Neste caso a magnitude dos 
números foi levado em consideração nesta prova e por este motivo todos os testes do gráfico 
foram feitos com a mesma matriz e esses dados podem ser vistos no Gráfico 1. 
 O Gráfico 1 revela que o teste que teve menor tempo de duração foi o de 600 threads 
com 265 segundos, em média o tempo de duração ficou em torno de 298 segundos 
considerando os testes feitos a partir 2 threads. Depois de calcularmos o coeficiente de 
variação desses dados apresentados no Gráfico 1 ficamos surpresos, ele ficou em torno 5%, 
isto quer dizer que a maioria dos testes obteve um tempo de duração com uma amplitude 
muito pequena e com isto concluímos que ao aumentar indiscriminadamente o número de 
threads o ganho de tempo é corroído pela troca de contexto das threads criadas, causando o 
que chamamos de overhead. Uma explicação possível e mais técnica para comprovar essa 
conjectura estaria baseado no modelo de múltiplas threads que são modelos que descrevem a 
forma como as threads no nível do usuário são mapeadas para as threads no kernel que 
segundo a Microsoft, o modelo do Windows seria o de “um para um”. Qual a desvantagem 
deste modelo? A desvantagem deste modelo é que para cada thread que é criada no nível do 
usuário, uma thread correspondente no kernel também é criada. Cada vez que uma thread de 
kernel ou mesmo uma thread de usuário é criada, várias chamadas de sistemas estão sendo 
feitas e trocas de contextos estão acontecendo e quanto maior for o número de troca de 
contextos, maior será o tempo que o processador ficará ocioso. 
P a g i n a 11 
 
 
Apesar do tempo 
de duração entre os testes 
serem bem próximos, o 
percentual de ganho éconsideravelmente grande. 
No Gráfico 2, calculamos 
que o ganho médio foi de 
43% em relação ao serial 
no Core I5, mas ao longo 
dos testes o ganho varia, pois o coeficiente de variação dos dados desse gráfico foi de 18%, 
isto quer dizer que houve testes com percentual de ganho baixo como por exemplo o teste 
com 3 threads que teve 30% e ganhos maiores como o de 600 threads que obteve 59% de 
ganho. 
 
A conclusão desses 
dados é que até uma certa 
quantidade de threads o 
ganho tenderá aumentar e 
o tempo de execução a 
diminuir, mas haverá um 
momento em que o custo 
para manter várias threads rodando no sistema operacional vai ser tão grande que o tempo de 
duração tenderá a uma padronização ou seja o tempo de processamento com 4 threads terá 
uma amplitude muito pequena em relação ao de 500 threads, isto acontece por que cada vez 
que um conjunto maior threads está sendo criado, várias chamadas de sistemas, dentre elas 
para efetuar a troca de contextos estão sendo feitas na mesma proporção e isto acaba 
atrasando o algoritmo no processamento da matriz. Mas o que se espera-se desta tecnologia 
não é a redução do tempo de execução e sim o usufruto de outras propriedades como a 
responsividade, compartilhamento de recursos, economia e o uso das propriedades dos 
processadores de múltiplos núcleos. 
Gráfico 1 – Tempo Dos Testes Com Matriz De 1000x1000, Blocos De 5x5. 
Gráfico 2 – Gráfico Do Percentual De Ganho do Algoritmo Nos Testes. 
P a g i n a 12 
 
 Fizemos um outro teste para saber se as threads demoravam mais tempo processando 
matrizes com a mesma quantidade de blocos, mas com blocos maiores. Esse teste foi com um 
dual core. 
 
Este resultado já era 
esperado apesar de todas essas 
matrizes terem a mesma 
quantidade de blocos, o tempo 
do dual core com 2 threads é 
proporcional ao tamanho dos 
macros blocos. Então 
concluímos que mantendo a 
quantidade blocos da matriz e aumentando o tamanho dos macros blocos as threads 
demoravam mais tempos para processar toda a matriz. 
SINCRONIZAÇÃO 
 
 Regiões críticas são regiões compartilhadas por várias unidades de utilização da cpu 
criadas pelo mesmo processo e por este motivo essas regiões podem receber acessos 
concorrentes capazes de alterar o resultado final da aplicação. No algoritmo foram declaradas 
diversas variáveis globais que são as candidatas as regiões críticas, mas apenas duas delas 
obedecem a definição. A primeira é um vetor de blocos que carrega informações a respeito da 
posição inicial e a disponibilidade do bloco na matriz. Através desse vetor de blocos é que 
será feita alocação dos blocos da matriz a cada thread do processo. A outra região receberá a 
quantidade total de números primos contidos na matriz e será manipulada diretamente pelas 
threads e por este motivo foi definida como uma seção crítica. 
Existem várias modelos de soluções 
para regiões críticas, algumas 
implementadas em nível de 
hardware e outras em software, 
como a primeira possui uma implementação mais complexa do ponto de vista do programador 
a maioria das soluções acabam sendo implementadas a nível de software. Existem várias 
0
100
200
300
400
500
600
700
800
TE
M
PO
 (S
)
mATRIZES
DUAL CORE INTEL
Gráfico 3 - Testes Com Matrizes Cujo Macro Blocos São Maiores. 
Figura 1 - Declaração Das Variáveis Globais do Algoritmo. 
P a g i n a 13 
 
soluções em níveis softwares e que usufruem de diversas técnicas para o tratar o problema, 
mas neste caso vamos nos contentar com a exclusão mútua e o mais utilizado e fácil de ser 
implementado é o Semáforo. O semáforo pode ser implementado de duas formas como 
contador, podendo ter um domínio de controle mais complexo e como binário podendo variar 
entre 0 e 1. O semáforo binário também é chamado de mutex, pois são os locks que fornecem 
a exclusão mútua. 
 Para resolver o problema da região crítica em nosso código usamos a técnica de 
exclusão mútua, ou seja, quando a thread entrar numa zona crítica, ela ganha o lock da região 
e nenhuma outra poderá interferir, 
portanto apenas uma thread poderá 
acessar essa região, desta forma a 
exclusão mútua fica garantida. Então, 
quando a thread pegar o primeiro bloco 
da matriz, primeiramente, irá verificar se 
o bloco foi visitado ou não, caso não, a thread ganha o lock dessa seção crítica e ajusta o 
bloco como visitado e libera a região. 
Quando essas regiões ficam desprotegida existe uma grande possibilidade do resultado 
do algoritmo não estar certo. Mas se existe a possiblidade do resultado ser alterado devido 
algum acesso concorrente a uma região crítica é melhor tratá-la. Tentamos alterar o algoritmo 
para que o acesso concorrente fosse possível, mas devido a ordem sequencial com que cada 
thread apanha o bloco e a magnitude dos números primos que eram escolhidos de forma 
aleatória, foi difícil chegar nessa conclusão, mas se a alocação do bloco a cada thread fosse 
feita de forma aleatória as condições para que o resultado fosse alterado seriam mais fáceis de 
serem atingidas. 
 
 
 
 
 
Figura 2 – Protegendo as regiões críticas do Algoritmo. 
P a g i n a 14 
 
O ALGORITMO 
 
O primeiro procedimento que nos preocupamos em executar foi verificar se esse 
problema podia ser otimizado, depois de modelá-lo na sua forma paralelizada verificamos no 
código quais são as regiões críticas, depois de definidas procuramos a melhor forma de 
protegê-las. Alocamos uma quantidade de blocos que receberá os dados essenciais dos blocos 
contidos na matriz, e na inicialização deles atribuímos as posições iniciais dos blocos da 
matriz e ajustamos a disponibilidade de todos os blocos para zero para informar as threads, 
que todos os blocos da matriz estão livres para serem processados, feito isto será possível 
localizar os blocos dentro da matriz e processá-los. 
Definimos o que cada thread terá que fazer e os parâmetros essenciais como o id do 
bloco que ela irá processar quando criada e executada na função “Threads” dentro da função 
“ExecutaThreads”. Quando a primeira thread for criada e executada, ela verificará a 
disponibilidade do primeiro bloco, caso tenha sido visitado ela vai para o próximo bloco, caso 
não, ela bloqueia essa região para que as outras threads não interfira e marca o bloco como 
visitado e então ela obtém a posição inicial do bloco e através de algum cálculos algébricos 
ela obtém a posição final e desta forma ela determina as extremidades do bloco na matriz e 
começa calcular a quantidade de primos no respectivo bloco. Depois de calculados, ela ganha 
o lock da região da variável “global” para que possa entregar o resultado e libera região e 
volta a repetir o ciclo novamente em outro bloco. 
Sabemos que a criação indiscriminada de threads gera overhead no SO, então tivemos 
a necessidade de trabalhar só com o número de threads informado na entrada pelo usuário, 
depois que esse número for atingido todas as threads terão que esperar até que a última 
termine a sua tarefa para que todas elas possam apanhar as próximas tarefas. No final dessa 
iteração a thread principal ainda terá que esperar pela última thread em execução, então esta 
espera é feita. Definimos o tempo inicial da sua execução e o tempo final para marcar a sua 
duração e enfim é feita a impressão da duração e o resultado esperado e então depois que 
todas threads terminarem a sua tarefa a thread principal termina sua execução. 
P a g i n a 15 
 
 
 
CONCLUSÃO 
 
 Por meios de artigos, enciclopédias, aulas com profissionais da área e livros de autores 
como Silberschartz identificamos vários conceitos e conjecturamos alguns. Dentreeles, as 
causas que obrigaram as tecnologias a se desenvolveram e chegarem ao nível que estão hoje, 
como o aumento do número de funcionalidades em programas, interfaces gráficas cada vez 
mais complexas, aumento da comunicação, carga e execução, número de usuários, menor 
tempo de resposta e maior confiabilidade. 
 Conceituamos também o grau de dependência que existe entre a programação paralela 
e os níveis da organização e arquitetura que começa com o nível lógico digital, micro 
arquitetura, arquitetura de instruções, sistema operacional, linguagem assembly e a linguagem 
de auto nível onde as mudanças acontecem em praticamente em todos níveis, principalmente 
no primeiro nível. Depois que a organização e arquitetura do ambiente computacional sofreu 
mudanças para atender as expectativas das arquiteturas MP, as próximas mudanças 
aconteceriam em nível de software, ou seja um novo campo na área de desenvolvimento viria 
a tona e é chamado de programação paralela. Com ela diversos desafios teriam que ser 
encarados na implementação de um software, os mesmos que enfrentamos ao desenvolver o 
algoritmo deste trabalho como a divisão de atividades, equilíbrio, divisão de dados, 
dependência de dados e teste e depuração. 
 Na divisão de atividades, nós identificamos no código quais áreas poderiam ser 
divididas e separadas para serem tarefas paralelas como por exemplo a busca em um bloco da 
matriz. O equilíbrio das atividades foi associada com uso da instrução join fazendo com que 
todas as threads tivesse que esperar umas pelas outras para que todas pudessem pegar as 
próximos blocos em conjunto. Na divisão de dados tivemos como desafio identificar quais 
seriam as variáveis locais e funções que seriam usadas durante a tarefa efetuada por cada 
thread. A dependência dos dados seria a análise para identificar partes do código que seriam 
compartilhadas entre as threads, identificando assim uma relação de pendência entre elas, que 
no nosso caso foi a variável global que recebia o resultado de números primos de cada thread 
e o vetor que controlava a alocação de cada bloco e o método de solução para manter a 
sincronização foi o de exclusão mútua, utilizando semáforos binários que também são 
P a g i n a 16 
 
chamados de mutex. Quanto aos testes e a depuração do código, não tivemos muita 
dificuldade mas acreditamos que isto depende da complexidade do modelo do algoritmo, que 
neste caso não era tão grande, mas em outras situações como na construção de um software 
com mais funcionalidades, o nível de dificuldade seria notável. 
 Mesclamos alguns conceitos sobre processos quanto aos seus estados, o seu 
repositório de dados chamado PCB (Bloco De Controle Do Processo) que guarda informações 
como estado do processo, contador de programa, registradores da CPU, informações de 
escalonamento de CPU, informações de gerência de memória, informações contábeis e 
informações de status de E/S. Além disto, o overhead que é um termo muito comum entre 
projetistas de hardware que neste caso é o tempo em que o processador fica ocioso na troca de 
contexto de um processo e algo similar acontece também com as chamadas de sistemas em 
que o SO tem que ficar mudando de modo para alocar e receber recurso solicitados pelas 
chamadas de sistemas, segundo Silberchartz, o instante em que o SO muda de modo, não 
importando se é para usuário ou para kernel também é chamado de overhead, por este motivo 
é que algumas arquiteturas de sistemas operacionais foram modificadas como por exemplo a 
arquitetura em camadas. Encontramos em livros o porquê do uso das threads e não de 
processos em execuções concorrentes e chegamos na conclusão de que não se tratava só de 
terminar as tarefas em menos tempo mas sim de uma série de fatores como economia, 
responsividade, compartilhamento de recursos e a utilização das arquiteturas 
multiprocessadas. 
Quantificamos o ganho que o algoritmo teve no processamento dos blocos que variava 
entre 30 e 59% no Core I5 Mobile a partir de 2 threads. Uma outra curiosidade relacionado a 
threads foi apontada pelos testes que foram feitos durante este trabalho, ao aumentarmos o 
número de threads e mantermos a mesma matriz com os mesmos valores e portanto com as 
mesma magnitudes, o tempo de execução tendia a um padrão, ou seja, uma hora ele 
aumentava ou diminuía mas sempre numa amplitude bem pequena então para conjecturar essa 
teoria usamos a estatística como ferramenta de prova, calculamos média, desvio padrão e 
finalmente o coeficiente de variação dos valores obtidos com os testes e chegamos a um cv de 
aproximadamente 5%, isto quer dizer que o tempo de execução dos testes eram homogêneos. 
A única explicação que poderíamos dar para isto seria o overhead causado pela criação 
indiscriminada de threads, ou seja, chegaria um momento em que haveria tantas trocas de 
contexto acontecendo na criação de novas threads que o tempo de execução acabaria sendo 
penalizado. Se aumentarmos o zoom em cima da API’ responsável pela criação de threads 
P a g i n a 17 
 
nosso algoritmo, veremos as API’s podem efetuar diversas chamadas de sistemas e cada vez 
que isto ocorre, o sistema fica mudando de modo usuário para modo kernel e vice versa, o 
tempo todo e o tempo que essa mudança ocorre também é overhead, pois o processador fica 
ocioso. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
P a g i n a 18 
 
REFERÊNCIAS BIBLIOGRÁFICAS 
 
 
Sítios Eletrônicos 
 
 
IFSP. Processos e Threads. 
Disponível em: http://ctd.ifsp.edu.br/~marcio.andrey/images/Implementacao-processos-
threads.pdf 
Acesso em 19 de Fevereiro, 2015. 
 
Training. Multithread. 
Disponível em: http://www.training.com.br/lpmaia/multithread.pdf 
Acesso em 19 de Fevereiro, 2015. 
 
 
UFRGS. Threads. 
Disponível em: http://www.inf.ufrgs.br/~johann/sisop1/aula07.threads.pdf 
Acesso em 19 de Fevereiro, 2015. 
 
UFRJ. Multthread. 
Disponível em: http://equipe.nce.ufrj.br/gabriel/microarq/Multithread.pdf 
Acesso em 19 de Fevereiro, 2015. 
 
UFRJ. Arquitetura De Computadores II. 
Disponível em: http://equipe.nce.ufrj.br/gabriel/arqcomp2/Multithread.pdf 
Acesso em 19 de Fevereiro, 2015. 
 
 
UFSCAR. Processos e Threads. 
Disponível em: http://www2.dc.ufscar.br/~regina/RecursosSO/cap-02-2004.pdf 
Acesso em 19 de Fevereiro, 2015. 
 
 
USP. Programação Threads. 
Disponível em: http://www.ime.usp.br/~danielc/aulas/mac431-ProgramacaoThreads.pdf 
Acesso em 19 de Fevereiro, 2015. 
 
UFSC. Threads. 
Disponível em: http://www.inf.ufsc.br/~fernando/ine5412/INE5412Cap2-threads.pdf 
Acesso em 19 de Fevereiro, 2015. 
 
UFU. Threads. 
Disponível em: http://www.inf.ufsc.br/~fernando/ine5412/INE5412Cap2-threads.pdf 
Acesso em 19 de Fevereiro, 2015. 
 
 
 
 
 
P a g i n a 19 
 
 
 
Livros 
 
Silberschartz Abraham, Peter Baer Galvin, Greg Gagne. 
Sistemas Operacionais Com Java. 
Traduzido por Daniel Vieira. 
7ª edição. 
Rio De Janeiro: Editora Elsevier, ano 2008,673 páginas.

Continue navegando