[Pereira ic'2011] explorando o paralelismo no nível de threads
[Zhang pact07] resume
1. aug-2011 1
Language and Virtual Machine Support for Efficient fine-Grained
Futures in Java
Lingli Zhang Chandra Krintz Priya Nagpurkar
Computer Science Department
University of California, snta Barbara
{lingli_z, ckrintz, priya} @ cs.ucsb.edu
Resumo realizado por Marcio Machado Pereira – RA 780681
afetam diretamente a semântica do programa. Em particular,
os autores introduziram a anotação future (denotada @future
I. INTRODUÇÃO no código fonte) para variáveis locais. Os usuários usam esta
N o artigo [1], os autores investigaram a implementação de
futures no Java J2SE v5.0. Future é uma construção de
linguagem de programação paralela que permite aos
diretiva para anotar variáveis locais que podem ser usadas
como resultados (placeholders) de valores retornados por
funções que potencialmente podem ser executadas
programadores especificar computações potencialmente concorrentemente pelo sistema. Se a chamada de uma função
assíncronas. Neste modelo, denominado Executor-Callable- armazena seu valor de retorno em uma variável local anotada,
Future, os usuários encapsulam uma computação que pode ela é identificada como uma future-function call.
ser potencialmente avaliada em paralelo usando o objeto
Callable e submete este ao objeto Executor. Apesar desta O modelo DBLFuture evita a criação (e portanto, a
metodologia desacoplar a lógica da aplicação do escalonador especificação por parte do usuário) de objetos Callable,
de tarefas (thread scheduling), o mesmo impõe uma Future, LazyFuture e outros objetos quando o mesmo é
sobrecarga para os usuários médios além de introduzir um executado sequencialmente (inlined) pelo sistema. Em
overhead significativo no desempenho. consequencia, evita-se a alocação de memória, o
gerenciamento de memória e a inserção de código fonte extra
Para endereçar estes problemas, os autores propuseram então requerido pelas abordagens anteriores.
Lazy Java Futures, uma implementação do Java Future
baseada na técnica originalmente proposta por Mohr e outros II. O ALGORITMO DBLFUTURE
denominada Lazy Task Creation (LTC) [2]. Lazy Future
Como primeiro passo do algoritmo, a diretiva future é salva
primeiramente executa as computações potencialmente
como um atributo do método na representação intermediária
concorrentes sequencialmente (inline) e então subdivide as
(bytecode). O carregador das classes java (class loader) da
computações através da divisão da pilha de execução (runtime JVM modificada (DBLFuture-aware JVM) reconhece o
stack) durante o escalonamento e troca das linhas de atributo e constrói uma tabela de variáveis locais future para
execução (threads) se a estimativa do sistema sobre o tempo cada método, contendo o nome, o índice e a faixa de índices
de execução restante da computação Future amortizar o custo do bytecode de cada variável local future. O compilador
da divisão. dinâmico Just-in-time consulta esta tabela durante a
compilação.
Lazy Future segue a abordagem baseada em interface, similar
(embora mais eficiente) à Java Futures. Como resultado, esta Inicialmente, a JVM trata toda future-function call como
herda uma semelhante produtividade imposta ao programador chamada de função normal e executa o código
e as mesmas limitações de desempenho. Para endereçar estas sequencialmente, na pilha de execução da thread corrente.
limitações, os autores proposurem neste artigo uma nova Para cada chamada desta, o sistema mantém também uma
implementação do Java Futures que eles chamaram de pequena pilha (future stack) com referências para as
Directive-based Lazy Futures (DBLFutures). potenciais chamadas future e um contador que estima a
duração da chamada future. O sistema usa esta informação
DBLFutures extende Lazy Futures para melhorar a facilidade para tomar decisões de divisão e geração de novas linhas de
de uso do paralelismo baseado em Java Futures assim como o execução (splitting and spawning decisions).
desempenho e escalabilidade. DBLFutures explora a
extensão da linguagem java criada para anotações [3]. As Na figura a seguir, a thread corrente tem 3 chamadas future
anotações são directivas de código fonte que transmitem na sua pilha. Em algum momento, o controller decide que
vale a pena gerar a chamada future, com a contagem de
informações de metadados do programa para as ferramentas,
amostra 10, para execução paralela. A linha cheia identifica o
bibliotecas e as máquinas virtuais Java (JVMs). Estas não ponto de divisão da pilha. O divisor (future splitter) então
O trabalho em referência foi apresentado na conferência PACT'07 realizado cria uma nova thread para a continuação da future call
entre os dias 15 e 19 de setembro de 2007 na cidade de Brasov, Romenia. O gerada, copia os frames da pilha abaixo do future frame, que
resumo é parte do trabalho de pesquisa de doutorado do Instituto de Computação
da UNICAMP (IC-Unicamp) e foi elaborado por Pereira, M. M. (e-mail: corresponde à thread corrente (chamada de continuation
mpereira@ic.unicamp.br ). thread), restaura o contexto de execução a partir dos frames
2. aug-2011 2
da pilha corrente, e reinicia a thread corrente no endereço de está no modelo adotado. No modelo Lazy Future, a JVM tem
retorno da future call gerada. a flexibilidade para decidir se sequencializa (inline) ou gera a
thread future (spawn), mas sempre cria os objetos Callable e
Future devido ao modelo baseado em interface. DBLFuture,
por sua vez, emprega um modelo baseado em chamada de
função (function-call) no qual evita-se a criação de objetos
Callable completamente e permite que a JVM crie objetos
Future somente quando tomar a decisão de dividir a thread,
decisão esta baseada na disponibilidade dos recursos e no
comportamento dinâmico do sistema.
IV. CONCLUSÃO
Futures provê uma simples e elegante maneira para os
programadores introduzirem concorrência nos seus
programas. No modelo corrente de Java, os programadores
adicionam futures nas suas aplicações usando o modelo
Executor-Callable-Future. Este modelo de programação
impõe uma sobrecarga para os usuários médios, além de
introduzir um overhead significativo no desempenho. Para
endereçar estas limitações, os autores introduziram um
O local do valor de retorno após completar a future call modelo baseado em anotações (DBLFuture) e apresentaram
requer um tratamento especial. Se a future call não é as extensões necessárias ao compilador Java e à JVM.
dividida, o valor de retorno deve ser armazenado na variável
local especificada. Se a future call é dividida e deu origem a Com DBLFuture, os programadores facilmente introduzem
uma nova thread, o retorno deve ser armazenado em um paralelismo nas suas aplicações anotando variaveis locais que
espaço reservado (i.e., um objeto future) para o acesso pela recebem resultados de chamadas de funções que podem ser
continuation thread. executadas com segurança em paralelo. Veja o exemplo da
função de Fibonacci abaixo:
Para saber se a future foi paralelizada, adiciona-se uma
palavra chamada split flag para cada frame da pilha de public class Fib {
execução. Este flag é um bitmap das future calls geradas public int fib (int n) {
(spawned), indexada pelo índice da variável local marcada if (n < 3) return n;
@future int x = fib (n – 1);
como future no vetor de variáveis locais do bytecode. A JVM int y = fib (n – 2);
verifica este bit em dois pontos do código: no armazenamento return x + y;
e no primeiro uso do valor de retorno. O modelo suporta até }
32 anotações futures (64 em máquinas de 64 bits) por método, ...
}
podendo ser facilmente extendido.
Similarmente, as instruções que usam o valor de retorno Note que na implementação proposta, a JVM toma decisões
precisam ser expandidas. Se o split flag estiver setado, o eficientes e automáticas de paralelização de tarefas, no
código deverá usar o valor de retorno diretamente da pilha no entanto, os usuários ainda são os responsáveis por garantir a
espaço (slot) da variável local. Do contrário, o código deverá segurança (safety) da execução concorrente.
executar o método get() do objeto future extraído do mesmo
slot, o qual irá bloquear a thread corrente se o valor de
V. REFERENCIAS
retorno não estiver pronto.
[1] L. Zhang, C. Krintz, and S. Soman. Efficient Support of Fine-grained Futures
in Java. In International Conference on Parallel and Distributed Computing
Para estimar o tempo de execução de uma future usa-se o Systems (PDCS), 2006.
serviço de monitoração de desempenho comum na maioria
das implementações JVM. Quando o sistema de amostragem [2] E. Mohr, D. A. Kranz, and J. R. H. Halstead. Lazy task creation: A technique
(sampling) identifica uma future como de longa duração e há for increasing the granularity of parallel programs. IEEE Trans. Parallel Distrib.
recursos suficientes no processador, o sistema divide a pilha Syst., 2(3):264-280, 1991.
da thread em duas, cria o objeto future e executa a future- [3] JSR-175: A Metadata facility for the JavaTM Programming Language.
function e a thread corrente em paralelo. http://jcp.org/en/jsr/detail?id=175.
III. IMPEMENTAÇÃO E AVALIAÇÃO
Para avaliar o DBLFuture, os autores implementaram o
algoritimo no Jikes Research Virtual Machine (JikesRVM).
Na média das experimentações, DBLfuture mostrou-se de 2.4
a 2.8 vezes mais eficiente do que o modelo baseado em Lazy
Futures. A razão principal para a melhora do desempenho