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 multi­thread 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 multi­
    processamento, 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) {
                                           const int N = 100000;
     int main(int argc, char* argv[])      int i, a[N];
     {
       #pragma omp parallel                 #pragma omp parallel for
       printf("Hello, world.n");           for (i = 0; i < N; i++)
       return 0;                               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


@task
def 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)


@decorador
def foo(arg):
    print(arg)

foo()
@task: Funcionamento usando 2 cpu
@task: Exemplo de código

    for m2ti import task

    @task
    def 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   @final
                                     def ultima():
@init                                    ...
def primeira():
    …
                                     for n in range(100):
@task                                    func(arg)
def func(arg):
    ...
@task: Funcionamento usando 2 cpu
       com roubo de tarefas
@task(n): Exemplo de código



from m2ti import task_cilk   bar(10)
                             ...
@task(1)                     bar(100)
def foo(arg):                …
    ...
                             for n in range(100):
@task(2)                         foo(n)
def bar(arg):
    …
    foo(10)
    ...
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

                         exclusive:
                             a += 1



                import multiprocessing
                ...
                lock = multiprocessing.Lock()
                lock.acquire()
                a += 1
                lock.release()
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:
                     …
                     @task
                     def 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.mems­exchange.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?
@final



Perguntas?


             Rodrigo Hübner
             e-mail:
             rhubner@gmail.com

M2ti - Python Brasil

  • 1.
    Python Brasil [5] Modelode Programação com Threads e Transações Implícitas em Python Rodrigo Hübner
  • 2.
    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
  • 3.
  • 4.
    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 multi­thread já existentes;  Aplicar estratégias existentes e buscar novas idéias
  • 5.
    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.
  • 6.
    Programação paralela emPython Bibliotecas tradicionais:  threading  multiprocessing Com mecanismos para SMP e Clusters  PP – Parallel Python
  • 7.
    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
  • 8.
    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()
  • 9.
    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...
  • 10.
    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()
  • 11.
    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)))
  • 12.
    Novo módulo emPython baseado na API OpenMP  API para programação paralela baseada em multi­ processamento, 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) { const int N = 100000; int main(int argc, char* argv[]) int i, a[N]; { #pragma omp parallel #pragma omp parallel for printf("Hello, world.n"); for (i = 0; i < N; i++) return 0; a[i] = 2 * i; } return 0; }
  • 13.
    Estratégias para acriaçã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
  • 14.
    Estratégias para acriação do módulo em Python multiprocessing + @decorator = @task @task def soma_primos(n):      … soma_primos(1000) Outros módulos: inspect, atexit, …
  • 15.
  • 16.
  • 17.
    @task: Exemplo decódigo for m2ti import task @task def 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)
  • 18.
    @task: Acrescentando inite 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.
  • 19.
    @task: Acrescentando inite final. Exemplo de código from m2ti import task, init, final @final def ultima(): @init     ... def primeira():     … for n in range(100): @task     func(arg) def func(arg):     ...
  • 20.
    @task: Funcionamento usando2 cpu com roubo de tarefas
  • 21.
    @task(n): Exemplo decódigo from m2ti import task_cilk bar(10) ... @task(1) bar(100) def foo(arg): …     ... for n in range(100): @task(2)     foo(n) def bar(arg):     …     foo(10)     ...
  • 22.
    Pré-processamento do códigofonte  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...
  • 23.
    Pré-processamento - exclusive Transformação simples a partir de locks exclusive: a += 1 import multiprocessing ... lock = multiprocessing.Lock() lock.acquire() a += 1 lock.release()
  • 24.
    Explicit is betterthan implicit.
  • 25.
    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: … @task def func(arg): … barrier ...
  • 26.
    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.mems­exchange.org/software/durus/;
  • 27.
    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 ...
  • 28.
    Conclusões e TrabalhosFuturos  Existem muitas limitações;  Resultados bons para alguns casos;  Verificar agora o que é mais importante;  Módulo ou pré­processamento?  Outras idéias?
  • 29.
    @final Perguntas? Rodrigo Hübner e-mail: rhubner@gmail.com