SlideShare uma empresa Scribd logo
Alejandro Mesias @meszias
• Campineiro
• Pai de 3 filhos
• Zup Innovation
• Pythonista a +10 anos.
• Tkinter, Django, Flask, Pymodbus...
Introdução ao Zumba - Contexto
• Python se tornou uma linguagem muito popular de computação
cientifica.
• Python integra bem com bibliotecas compiladas: MKL (intel),
TensorFlow, ROOT (Análise matemática), etc.
• Compilação de modulos em C/C++, ctypes, libs próprias em binário.
*Stan Seibert, Anaconda
Introdução ao Numba – Motivação
A Compiler for Python?
Striking a Balance Between Productivity
and Performance.
(Atingindo um equilíbrio entre produtividade e desempenho.)
*Stan Seibert, Anaconda
Introdução ao Numba - Motivação
O objetivo foi fazer um compilador que atenda:
• Funcione no interpretador python padrão, e não substituir o mesmo
• Que se integre perfeitamente com Numpy
• Compativel com paradgmas de computação multitread e distribuída
• Pode ser direcionado a non-CPU hardware (fazer uso de GPU/Cuda)
*Stan Seibert, Anaconda
Numba: Um compilador JIT Compiler para Python
• Uma biblioteca de compilação “uma função por vez” para python
• Um toolbox de compilação com diferentes objetivos e modelos de execução:
• Single-tread CPU, multi-threaded CPU, GPU
• Funções regulares, funções de array, etc.
• Speed-up: 2x comparado a Numpy, até 200x (comparado com Python puro)
• Combinar facilidade de escrever Python com a velocidades próximas do Fortran.
• O objetivo é capacitar cientistas que criam ferramentas para outros cientistas.
*Stan Seibert, Anaconda
Um labirinto sinuoso de trade-offs
Numba pode ser melhor entendido pelo que ele Não é:
• Substituição do interpretador Python: PyPy, Pyston, Pyjion
• Dificil de implementar
• Dificil (mas não impossível) de manter compatibilidade
com extensões python existentes
• Não endereça para destinos não-CPU
• Tradutor do python para C/C++: Cython, Pythran, Theano, ShedSkin, Niutka
• Análise estática de linguagens dinâmicas é limitante
• Código gerado antecipado é subespecializado (tanto em tipos de dados quanto em recursos
de CPU) ou inchado para cobrir todas as variantes.
• Compilação com JIT requer compilador C/C++ no sistema do usuário
Exemplo Básico
Sequencia de Fibonacci não recursiva.
Até 92, 1.000.000 execuções.
Usando time.perf_counter_ns()
4315505000µs ou 4.31s
def fibonacci(n):
a, b = 0, 1
for _ in range(0, n-1):
c = a + b
a = b
b = c
return a
Exemplo Básico
Sequencia de Fibonacci não recursiva.
Até 92, 1.000.000 execuções.
Usando time.perf_counter_ns()
Sem otimização: 4.19s
Otimizado: 0.22s (19.5x mais rápido)
@njit
def fibonacci(n):
a, b = 0, 1
for _ in range(0, n-1):
c = a+b
a = b
b = c
return a
Exemplo Básico
Sequencia de Fibonacci não recursiva.
Até 92, 1.000.000 execuções.
Usando time.perf_counter_ns()
Sem otimização: 4.19s
Otimizado: 0.27s (19.5x mais rápido)
“... até 200x
(comparado
com Python
puro)”
Exemplo Básico
Sequencia de Fibonacci não recursiva.
Até 92, 1.000.000 execuções.
Usando time.perf_counter_ns()
Sem otimização: 4.3s
Otimizado: 0.22s (19.5x mais rápido)
Loop Otimizado: 0.042s (101x mais rápido)
@numba.njit("uint64(uint64, uint64)")
def runner(runs, fibn):
val1 = 0
for i in range(runs):
val1 = fibonacci(fibn)
return val1
Numba - Instalação
pip install numba
conda install numba
O que será instalado:
Numba – 0.51.2 => Lib
Numpy – 1.19.4 => Tudo é ndarray
llvmlite - 0.34.0 => Compilação
Dicas over exemplos
Pontos fracos do Numba
• Documentação com poucos detalhes (nem todos são especialistas!)
• Stack de falha pouco detalhada
• Nem sempre são explícitos os erros de execução. (ex: index no array)
Opcional (NUMBA_DEVELOPER_MODE=1)
• Voltar ao python puro é sempre uma boa opção (NUMBA_DISABLE_JIT=1)
• Use sua intuição !
Tipos de variável
Type name(s) Shorthand Comments
intc – C int-sized integer
uintc –
C int-sized unsigned
integer
intp – pointer-sized integer
uintp –
pointer-sized
unsigned integer
float32 f4
single-precision
floating-point
number
float64, double f8
double-precision
floating-point
number
complex64 c8
single-precision
complex number
complex128 c16
double-precision
complex number
Type name(s) Shorthand Comments
Boolean b1
represented as a
byte
uint8, byte u1 8-bit unsigned byte
uint16 u2
16-bit unsigned
integer
uint32 u4
32-bit unsigned
integer
uint64 u8
64-bit unsigned
integer
int8, char i1 8-bit signed byte
int16 i2 16-bit signed integer
int32 i4 32-bit signed integer
int64 i8 64-bit signed integer
Numba - utilização
Algumas regras de utilização:
• Evite dict, list, tuplas. Existem recomendações para esses tipos:
• Typed Dict
• key_type
• value_type
from numba.typed import Dict
from numba.core import types
from numpy as np
# The Dict.empty() constructs a typed dictionary.
# The key and value typed must be explicitly declared.
d = Dict.empty(
key_type=types.unicode_type,
value_type=types.float64[:],
)
d['posx'] = np.asarray([1, 0.5, 2], dtype='f8')
String
Lista de float64
ndarray
Numba - utilização
Algumas regras de utilização:
• Typed List
• Empty_list
• pega o primeiro tipo usado
from numba import types
from numba.typed import List
alloc_list = List.empty_list(types.int64,
10)
mylist = List()
mylist.append(100)
Numba - utilização
Algumas regras de utilização:
• Manupulação de String dentro do numba é limitado
• Não há fstring, string format ou “%s %d” %(‘a’, 1)
• É possível concatenar somando strings
• É possível usar selectors “bom dia”[4:]
• Evite acesso a variáveis globais, a não ser que sejam do numba,
prefira passar por parâmetro (cuidado com o gil).
• Existem classes, mas não funcionam como nopython=true
Numba - utilização
Algumas regras de utilização:
• O tipo de cada atributo é
especificado (obrigatório)
• Funciona como uma classe mas,
tem peso extra para compilar
dinamicamente (não tem cache=True)
• Prático para trocar variáveis com
funções numba
spec = [
('value', int32), # a simple scalar field
('array', float32[:]), # an array field
]
@jitclass(spec)
class Bag(object):
def __init__(self, value):
self.value = value
self.array = np.zeros(value, dtype=np.float32)
@property
def size(self):
return self.array.size
n = 21
mybag = Bag(n)
Numba - utilização
Algumas regras de utilização:
• Conflito com tipos numpy no @jitclass:
No spec = [ ] apenas tipos
do Numba.
Alternativas
para extrair tipos numpy:
Numpy, processamento paralelo, otimização
Calculando distribuição 50:50 de 2 colunas randomicas
def calculate3(x):
a = b = c = d = 0
for i in prange(x.shape[0]):
row = x[i]
if row[0] > 50:
a += 1
else:
b += 1
if row[1] < 50:
c += 1
else:
d += 1
return [a, b, c, d]
@njit(cache=True)
def calculate2(x):
a = b = c = d = 0
for i in prange(x.shape[0]):
row = x[i]
if row[0] > 50:
a += 1
else:
b += 1
if row[1] < 50:
c += 1
else:
d += 1
return [a, b, c, d]
@njit(parallel=True, nogil=True,
cache=True,
locals={'a': uint64, 'b': uint64,
'c': uint64,'d': uint64})
def calculate1(x):
a = b = c = d = 0
for i in prange(x.shape[0]):
row = x[i]
if row[0] > 50:
a += 1
else:
b += 1
if row[1] < 50:
c += 1
else:
d += 1
return [a, b, c, d]
Python puro Njit Simples Njit paranelizado
Comparação de resultados
# size_array = 10**6
size_array = 10**9
ttt1 = time.perf_counter_ns()
x1 = random.randint(100, size=(size_array, 2))
total_pos1 = calculate1(x1)
ttt1= time.perf_counter_ns() - ttt1
x1 = None
del x1
print(f'Fim 1 Tempo: {ttt1:,}us ({ttt1/10**9}s)')
Iterações Calc1 Calc2 Calc3
10**3 0.049s 0.002s 0.0007s
10**6 0.7s 0.12s 0.68s
10**8 2.29s (34x) 1.68 (48x) 78s
10**9 17.72s 17.54s 778s
0.00
100.00
200.00
300.00
400.00
500.00
600.00
700.00
800.00
900.00
mil 1 milhão 100 mi 1 bilhão
Comparação de tempos
Calc1 Calc2 Calc3
0
2
4
6
8
10
12
14
16
18
20
mil 1 milhão 100 mi 1 bilhão
Comparação 1x2
Calc1 Calc2
Fim
...poderia ter falado de Cuda e processamento por GPU
Mas nem cheguei a executar, não tenho Nvidia, então ficará para próxima.
Perguntas?

Mais conteúdo relacionado

Semelhante a Ganhando performance no Python com Numba em projetos não científicos

Objetos Pythonicos - compacto
Objetos Pythonicos - compactoObjetos Pythonicos - compacto
Objetos Pythonicos - compacto
Luciano Ramalho
 
Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)Luciano Ramalho
 
Computação Científica com SciPy - Brevíssimo Tutorial
Computação Científica com SciPy - Brevíssimo TutorialComputação Científica com SciPy - Brevíssimo Tutorial
Computação Científica com SciPy - Brevíssimo TutorialFabio Spanhol
 
Python
PythonPython
Computação Manycore: Uma Arquitetura muito além do Multicore!
Computação Manycore: Uma Arquitetura muito além do Multicore!Computação Manycore: Uma Arquitetura muito além do Multicore!
Computação Manycore: Uma Arquitetura muito além do Multicore!
Intel Software Brasil
 
2016/01/27 - Aprendendo a programar com Python
2016/01/27 - Aprendendo a programar com Python2016/01/27 - Aprendendo a programar com Python
2016/01/27 - Aprendendo a programar com Python
Jardel Weyrich
 
Introdução a programação
Introdução a programaçãoIntrodução a programação
Introdução a programaçãoGustavo Nazário
 
Programando para web com python - Introdução a Python
Programando para web com python - Introdução a PythonProgramando para web com python - Introdução a Python
Programando para web com python - Introdução a Python
Alvaro Oliveira
 
Aula3PythonBasico (1).ppt
Aula3PythonBasico (1).pptAula3PythonBasico (1).ppt
Aula3PythonBasico (1).ppt
MichaelArrais1
 
Aula3PythonBasico.ppt
Aula3PythonBasico.pptAula3PythonBasico.ppt
Aula3PythonBasico.ppt
MichaelArrais1
 
Aula python
Aula pythonAula python
Python para Desenvolvedores
Python para DesenvolvedoresPython para Desenvolvedores
Python para Desenvolvedores
Wellington Oliveira
 
Curso de Python (Básico) - Português
Curso de Python (Básico) - PortuguêsCurso de Python (Básico) - Português
Curso de Python (Básico) - Português
Helio Colombe
 
Linguagem de Programação Python
Linguagem de Programação PythonLinguagem de Programação Python
Linguagem de Programação Python
Junior Sobrenome
 
9. IA 1 - Introdução a programação em Python.pdf
9. IA 1 - Introdução a programação em Python.pdf9. IA 1 - Introdução a programação em Python.pdf
9. IA 1 - Introdução a programação em Python.pdf
MilvaNnMarluZz
 
Linguagem_C.pdf
Linguagem_C.pdfLinguagem_C.pdf
Linguagem_C.pdf
ApebNetherlands
 
Principais conceitos técnicas e modelos de programação paralela
Principais conceitos técnicas e modelos de programação paralelaPrincipais conceitos técnicas e modelos de programação paralela
Principais conceitos técnicas e modelos de programação paralela
Intel Software Brasil
 
Estrutura de dados
Estrutura de dadosEstrutura de dados
Estrutura de dadosgjpbg
 
Apostila estrutura de dados 2
Apostila estrutura de dados 2Apostila estrutura de dados 2
Apostila estrutura de dados 2Leandro Lopes
 
Seja DinâMico Com Python
Seja DinâMico Com PythonSeja DinâMico Com Python
Seja DinâMico Com Python
Campus Party Brasil
 

Semelhante a Ganhando performance no Python com Numba em projetos não científicos (20)

Objetos Pythonicos - compacto
Objetos Pythonicos - compactoObjetos Pythonicos - compacto
Objetos Pythonicos - compacto
 
Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)
 
Computação Científica com SciPy - Brevíssimo Tutorial
Computação Científica com SciPy - Brevíssimo TutorialComputação Científica com SciPy - Brevíssimo Tutorial
Computação Científica com SciPy - Brevíssimo Tutorial
 
Python
PythonPython
Python
 
Computação Manycore: Uma Arquitetura muito além do Multicore!
Computação Manycore: Uma Arquitetura muito além do Multicore!Computação Manycore: Uma Arquitetura muito além do Multicore!
Computação Manycore: Uma Arquitetura muito além do Multicore!
 
2016/01/27 - Aprendendo a programar com Python
2016/01/27 - Aprendendo a programar com Python2016/01/27 - Aprendendo a programar com Python
2016/01/27 - Aprendendo a programar com Python
 
Introdução a programação
Introdução a programaçãoIntrodução a programação
Introdução a programação
 
Programando para web com python - Introdução a Python
Programando para web com python - Introdução a PythonProgramando para web com python - Introdução a Python
Programando para web com python - Introdução a Python
 
Aula3PythonBasico (1).ppt
Aula3PythonBasico (1).pptAula3PythonBasico (1).ppt
Aula3PythonBasico (1).ppt
 
Aula3PythonBasico.ppt
Aula3PythonBasico.pptAula3PythonBasico.ppt
Aula3PythonBasico.ppt
 
Aula python
Aula pythonAula python
Aula python
 
Python para Desenvolvedores
Python para DesenvolvedoresPython para Desenvolvedores
Python para Desenvolvedores
 
Curso de Python (Básico) - Português
Curso de Python (Básico) - PortuguêsCurso de Python (Básico) - Português
Curso de Python (Básico) - Português
 
Linguagem de Programação Python
Linguagem de Programação PythonLinguagem de Programação Python
Linguagem de Programação Python
 
9. IA 1 - Introdução a programação em Python.pdf
9. IA 1 - Introdução a programação em Python.pdf9. IA 1 - Introdução a programação em Python.pdf
9. IA 1 - Introdução a programação em Python.pdf
 
Linguagem_C.pdf
Linguagem_C.pdfLinguagem_C.pdf
Linguagem_C.pdf
 
Principais conceitos técnicas e modelos de programação paralela
Principais conceitos técnicas e modelos de programação paralelaPrincipais conceitos técnicas e modelos de programação paralela
Principais conceitos técnicas e modelos de programação paralela
 
Estrutura de dados
Estrutura de dadosEstrutura de dados
Estrutura de dados
 
Apostila estrutura de dados 2
Apostila estrutura de dados 2Apostila estrutura de dados 2
Apostila estrutura de dados 2
 
Seja DinâMico Com Python
Seja DinâMico Com PythonSeja DinâMico Com Python
Seja DinâMico Com Python
 

Ganhando performance no Python com Numba em projetos não científicos

  • 1. Alejandro Mesias @meszias • Campineiro • Pai de 3 filhos • Zup Innovation • Pythonista a +10 anos. • Tkinter, Django, Flask, Pymodbus...
  • 2. Introdução ao Zumba - Contexto • Python se tornou uma linguagem muito popular de computação cientifica. • Python integra bem com bibliotecas compiladas: MKL (intel), TensorFlow, ROOT (Análise matemática), etc. • Compilação de modulos em C/C++, ctypes, libs próprias em binário. *Stan Seibert, Anaconda
  • 3. Introdução ao Numba – Motivação A Compiler for Python? Striking a Balance Between Productivity and Performance. (Atingindo um equilíbrio entre produtividade e desempenho.) *Stan Seibert, Anaconda
  • 4. Introdução ao Numba - Motivação O objetivo foi fazer um compilador que atenda: • Funcione no interpretador python padrão, e não substituir o mesmo • Que se integre perfeitamente com Numpy • Compativel com paradgmas de computação multitread e distribuída • Pode ser direcionado a non-CPU hardware (fazer uso de GPU/Cuda) *Stan Seibert, Anaconda
  • 5. Numba: Um compilador JIT Compiler para Python • Uma biblioteca de compilação “uma função por vez” para python • Um toolbox de compilação com diferentes objetivos e modelos de execução: • Single-tread CPU, multi-threaded CPU, GPU • Funções regulares, funções de array, etc. • Speed-up: 2x comparado a Numpy, até 200x (comparado com Python puro) • Combinar facilidade de escrever Python com a velocidades próximas do Fortran. • O objetivo é capacitar cientistas que criam ferramentas para outros cientistas. *Stan Seibert, Anaconda
  • 6. Um labirinto sinuoso de trade-offs Numba pode ser melhor entendido pelo que ele Não é: • Substituição do interpretador Python: PyPy, Pyston, Pyjion • Dificil de implementar • Dificil (mas não impossível) de manter compatibilidade com extensões python existentes • Não endereça para destinos não-CPU • Tradutor do python para C/C++: Cython, Pythran, Theano, ShedSkin, Niutka • Análise estática de linguagens dinâmicas é limitante • Código gerado antecipado é subespecializado (tanto em tipos de dados quanto em recursos de CPU) ou inchado para cobrir todas as variantes. • Compilação com JIT requer compilador C/C++ no sistema do usuário
  • 7. Exemplo Básico Sequencia de Fibonacci não recursiva. Até 92, 1.000.000 execuções. Usando time.perf_counter_ns() 4315505000µs ou 4.31s def fibonacci(n): a, b = 0, 1 for _ in range(0, n-1): c = a + b a = b b = c return a
  • 8. Exemplo Básico Sequencia de Fibonacci não recursiva. Até 92, 1.000.000 execuções. Usando time.perf_counter_ns() Sem otimização: 4.19s Otimizado: 0.22s (19.5x mais rápido) @njit def fibonacci(n): a, b = 0, 1 for _ in range(0, n-1): c = a+b a = b b = c return a
  • 9. Exemplo Básico Sequencia de Fibonacci não recursiva. Até 92, 1.000.000 execuções. Usando time.perf_counter_ns() Sem otimização: 4.19s Otimizado: 0.27s (19.5x mais rápido) “... até 200x (comparado com Python puro)”
  • 10. Exemplo Básico Sequencia de Fibonacci não recursiva. Até 92, 1.000.000 execuções. Usando time.perf_counter_ns() Sem otimização: 4.3s Otimizado: 0.22s (19.5x mais rápido) Loop Otimizado: 0.042s (101x mais rápido) @numba.njit("uint64(uint64, uint64)") def runner(runs, fibn): val1 = 0 for i in range(runs): val1 = fibonacci(fibn) return val1
  • 11. Numba - Instalação pip install numba conda install numba O que será instalado: Numba – 0.51.2 => Lib Numpy – 1.19.4 => Tudo é ndarray llvmlite - 0.34.0 => Compilação
  • 13. Pontos fracos do Numba • Documentação com poucos detalhes (nem todos são especialistas!) • Stack de falha pouco detalhada • Nem sempre são explícitos os erros de execução. (ex: index no array) Opcional (NUMBA_DEVELOPER_MODE=1) • Voltar ao python puro é sempre uma boa opção (NUMBA_DISABLE_JIT=1) • Use sua intuição !
  • 14. Tipos de variável Type name(s) Shorthand Comments intc – C int-sized integer uintc – C int-sized unsigned integer intp – pointer-sized integer uintp – pointer-sized unsigned integer float32 f4 single-precision floating-point number float64, double f8 double-precision floating-point number complex64 c8 single-precision complex number complex128 c16 double-precision complex number Type name(s) Shorthand Comments Boolean b1 represented as a byte uint8, byte u1 8-bit unsigned byte uint16 u2 16-bit unsigned integer uint32 u4 32-bit unsigned integer uint64 u8 64-bit unsigned integer int8, char i1 8-bit signed byte int16 i2 16-bit signed integer int32 i4 32-bit signed integer int64 i8 64-bit signed integer
  • 15. Numba - utilização Algumas regras de utilização: • Evite dict, list, tuplas. Existem recomendações para esses tipos: • Typed Dict • key_type • value_type from numba.typed import Dict from numba.core import types from numpy as np # The Dict.empty() constructs a typed dictionary. # The key and value typed must be explicitly declared. d = Dict.empty( key_type=types.unicode_type, value_type=types.float64[:], ) d['posx'] = np.asarray([1, 0.5, 2], dtype='f8') String Lista de float64 ndarray
  • 16. Numba - utilização Algumas regras de utilização: • Typed List • Empty_list • pega o primeiro tipo usado from numba import types from numba.typed import List alloc_list = List.empty_list(types.int64, 10) mylist = List() mylist.append(100)
  • 17. Numba - utilização Algumas regras de utilização: • Manupulação de String dentro do numba é limitado • Não há fstring, string format ou “%s %d” %(‘a’, 1) • É possível concatenar somando strings • É possível usar selectors “bom dia”[4:] • Evite acesso a variáveis globais, a não ser que sejam do numba, prefira passar por parâmetro (cuidado com o gil). • Existem classes, mas não funcionam como nopython=true
  • 18. Numba - utilização Algumas regras de utilização: • O tipo de cada atributo é especificado (obrigatório) • Funciona como uma classe mas, tem peso extra para compilar dinamicamente (não tem cache=True) • Prático para trocar variáveis com funções numba spec = [ ('value', int32), # a simple scalar field ('array', float32[:]), # an array field ] @jitclass(spec) class Bag(object): def __init__(self, value): self.value = value self.array = np.zeros(value, dtype=np.float32) @property def size(self): return self.array.size n = 21 mybag = Bag(n)
  • 19. Numba - utilização Algumas regras de utilização: • Conflito com tipos numpy no @jitclass: No spec = [ ] apenas tipos do Numba. Alternativas para extrair tipos numpy:
  • 21. Calculando distribuição 50:50 de 2 colunas randomicas def calculate3(x): a = b = c = d = 0 for i in prange(x.shape[0]): row = x[i] if row[0] > 50: a += 1 else: b += 1 if row[1] < 50: c += 1 else: d += 1 return [a, b, c, d] @njit(cache=True) def calculate2(x): a = b = c = d = 0 for i in prange(x.shape[0]): row = x[i] if row[0] > 50: a += 1 else: b += 1 if row[1] < 50: c += 1 else: d += 1 return [a, b, c, d] @njit(parallel=True, nogil=True, cache=True, locals={'a': uint64, 'b': uint64, 'c': uint64,'d': uint64}) def calculate1(x): a = b = c = d = 0 for i in prange(x.shape[0]): row = x[i] if row[0] > 50: a += 1 else: b += 1 if row[1] < 50: c += 1 else: d += 1 return [a, b, c, d] Python puro Njit Simples Njit paranelizado
  • 22. Comparação de resultados # size_array = 10**6 size_array = 10**9 ttt1 = time.perf_counter_ns() x1 = random.randint(100, size=(size_array, 2)) total_pos1 = calculate1(x1) ttt1= time.perf_counter_ns() - ttt1 x1 = None del x1 print(f'Fim 1 Tempo: {ttt1:,}us ({ttt1/10**9}s)') Iterações Calc1 Calc2 Calc3 10**3 0.049s 0.002s 0.0007s 10**6 0.7s 0.12s 0.68s 10**8 2.29s (34x) 1.68 (48x) 78s 10**9 17.72s 17.54s 778s 0.00 100.00 200.00 300.00 400.00 500.00 600.00 700.00 800.00 900.00 mil 1 milhão 100 mi 1 bilhão Comparação de tempos Calc1 Calc2 Calc3
  • 23. 0 2 4 6 8 10 12 14 16 18 20 mil 1 milhão 100 mi 1 bilhão Comparação 1x2 Calc1 Calc2
  • 24. Fim ...poderia ter falado de Cuda e processamento por GPU Mas nem cheguei a executar, não tenho Nvidia, então ficará para próxima. Perguntas?