m2ti - python brasil
DESCRIPTION
Apresentação feita no 5º Encontro Brasileiro da comunidade PythonTRANSCRIPT
Python Brasil [5]
Modelo de Programação com Threads e Transações Implícitas em Python
Rodrigo Hübner
Conteúdo
● Introdução
● Motivação
● Programação paralela implícita
● Algumas estratégias já utilizadas
● Principais módulos para programação
paralela em Python
● Estratégia proposta para Python
● A expansão (Pré-processamento)
● Conclusões e trabalhos futuros
Introdução
Nos modelos atuais, o programador deve solicitar a criação de unidades paralelas explicitamente.
Tais modelos tornam a programação complexa para:
Criar
Gerenciar
Explorar a arquitetura
A proposta é criar unidades paralelas de forma implícita.
Motivação
Facilitar a construção de programas paralelos;
Explorar programação paralela em alguma linguagem;
Expandir uma linguagem de programação baseado em modelos multithread já existentes;
Aplicar estratégias existentes e buscar novas idéias
Modificar um compilador/interpretador já existente
Qualquer resultado positivo é válido e inquestionável.
Contras:
Difícil implementação para linguagens já existentes;
Resultados demoram;
Não existe linguagens que implentam unidades paralelas de forma implícita para tomar base.
Programação paralela em Python
Bibliotecas tradicionais:
threading
multiprocessing
Com mecanismos para SMP e Clusters
PP – Parallel Python
Python - threading
Método mais utilizado até o momento;
É um módulo completo, mas possuem problemas de desempenho...;
Threads utilizam o mesmo espaço de endereçamento;
Soluções: uso de locks...
GIL Global Interpreter Lock
Python – threading. Exemplo de código
from threading import Thread
def func(arg):
print(arg)
th = Thread(target=func, args=('executando thread', ) )
th.start()
th.join()
Python - multiprocessing
É similar ao módulo threading;
Oferece paralelismo local e remoto;
Evita problemas com o GIL usando subprocessos em vez de threads;
Shared memory e objetos ctypes compartilhados
Managers Queues, Pipes...
Python – threading. Exemplo de código
from multiprocessing import Process
def func(arg):
print(arg)
p = Process(target=func, args=('executando subprocesso', ) )
p.start()
p.join()
Python – threading. Exemplo de código
Além disso...
from multiprocessing import Pool
def f(x): return x*x
if __name__ == '__main__': pool = Pool(processes=4) result = pool.apply_async(f, [10]) print(pool.map(f, range(10)))
Novo módulo em Python baseado na API OpenMP
API para programação paralela baseada em multiprocessamento, para linguagens C, C++ e Fortran;
Base inicial para a construção de um módulo em Python:
Exemplos:
int main(int argc, char* argv[]) { #pragma omp parallel printf("Hello, world.\n"); return 0; }
int main(int argc, char **argv) { const int N = 100000; int i, a[N]; #pragma omp parallel for for (i = 0; i < N; i++) a[i] = 2 * i; return 0;}
Estratégias para a criação do módulo em Python
from multiprocessing import Pool
@Pool(5, 'apply')
def func()
…
Depende de parâmetros
>>> Criar um módulo que possa enviar parâmetros através de chamadas da função decorada
Estratégias para a criação do módulo em Python
multiprocessing + @decorator = @task
@taskdef soma_primos(n): …
soma_primos(1000)
Outros módulos: inspect, atexit, …
Python – decorators
class decorador(object): def __init(self, func): self.func = func def __call__(self, *args, **kargs): self.func(*args, **kargs)
@decoradordef foo(arg): print(arg)
foo()
@task: Funcionamento usando 2 cpu
@task: Exemplo de código
for m2ti import task
@taskdef fibonacci(n): a, b = 0, 1 for i in range(n) a, b = b, a+b return a
for i in range(1000): fibonacci(i)
@task: Acrescentando init e final
@init decora uma tarefa que será executada antes de todos os trabalhadores;
Permite preparar objetos que serão utilizados pelas tarefas. Ex: Construção de uma matriz
@final decora uma tarefa que será executada depois que todos os trabalhadores terminarem suas execuções;
Imprimir resultados, especificar outro conjunto de tarefas, etc.
@task: Acrescentando init e final. Exemplo de código
from m2ti import task, init, final
@initdef primeira(): …
@taskdef func(arg): ...
@finaldef ultima(): ...
for n in range(100): func(arg)
@task: Funcionamento usando 2 cpu com roubo de tarefas
@task(n): Exemplo de código
from m2ti import task_cilk
@task(1)def foo(arg): ...
@task(2)def bar(arg): … foo(10) ...
bar(10)...bar(100)…
for n in range(100): foo(n)
Pré-processamento do código fonte
Possibilidade de acrescentar novas idéias;
Permite inserir melhor o código depois de préprocessar;
É possível explorar melhor as funcionalidades da linguagem e suas bibliotecas...
Pré-processamento - exclusive
Transformação simples a partir de locks
import multiprocessing...lock = multiprocessing.Lock()lock.acquire()a += 1lock.release()
exclusive: a += 1
Explicit is better than implicit.
Pré-processamento - barrier
Implementação de sincronização através de barreiras
Eventos e trabalhadores ativos estariam implícitos
Não existe implementação de barreira no módulo multiprocessing;
Exemplo:…@taskdef func(arg): … barrier ...
Pré-processamento - atomic
Implementação de transações implícitas: Modo mais seguro de manipular objetos compartilhados;
Projetos existentes:
Kamaelia http://www.kamaelia.org/STM
Durus http://www.memsexchange.org/software/durus/;
Pré-processamento - atomic
Adapatar para funcionar junto ao módulo multiprocessing
Deixar com uma sintaxe mais pythonica :)
Exemplo: def foo(): …
def bar(): …
atomic: a = foo() b = bar() c = a + b...
Conclusões e Trabalhos Futuros
Existem muitas limitações;
Resultados bons para alguns casos;
Verificar agora o que é mais importante;
Módulo ou préprocessamento?
Outras idéias?