es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Compilar clase de Python con numba.

Estoy utilizando el decorador numba.jitclass() para compilar una clase de Python Honda que toma otra clase de Python Car como argumento de entrada:

class Car(object):
    cc = '10'

class Honda(object):
    def __init__(self):
        self.car = Car()

    def cal(self):
        'Realizar cálculos pesados'

¡Numba no puede identificar el tipo del objeto (clase) de Python!

object = Car()
numba.typeof(object)      # Error (no es un tipo de numba)
from numba.experimental import jitclass
from numba import types, jit, njit

@jitclass([('car', types.pyobject)])  # Intenté agregar `nopython=False`, pero genera un error
class Honda(object):
    def __init__(self):
        self.car = Car()

    @jit
    def cal(self):  # TypeError: los miembros de la clase todavía no son compatibles
        'Realizar cálculos pesados'
@jitclass([('car', types.pyobject)])  # Intenté agregar `nopython=False`, pero genera un error
class Honda(object):
    def __init__(self):
        self.car = typed.pyobject(Car())

    @jit
    def cal(self):  # TypeError: los miembros de la clase todavía no son compatibles
        'Realizar cálculos pesados'
@jitclass()
class Honda(object, Car):
    def __init__(self):
        pass

    @jit
    def cal(self):  # TypeError: los miembros de la clase todavía no son compatibles
        'Realizar cálculos pesados'

¿Cómo puedo simplemente utilizar cualquier objeto de Python (de cualquier tipo de clase) dentro de una clase que esté compilada por numba.jitclass() y agregar miembros de clase (métodos @njit) para ser utilizados?

¿Hay alguna manera mejor de lograr esto en lugar de usar numba.jitclass()?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Desafortunadamente, como has descubierto, numba no admite el uso de objetos de Python (clases) directamente como tipo en una definición de jitclass. Sin embargo, hay algunas soluciones alternativas que puedes usar para lograr una funcionalidad similar.

    Un enfoque es crear una versión compatible con numba de la clase Car, que luego puedes usar como tipo para el atributo car en la clase Honda. Esto se puede hacer utilizando el decorador numba.jitclass para definir una nueva clase que tenga los mismos atributos y métodos que la clase Car original, pero sea compatible con numba:

    import numpy as np
    from numba import jitclass, int32, float32
    
    spec = [
        ('cc', int32),
    ]
    
    @jitclass(spec)
    class NumbaCar(object):
        def __init__(self):
            self.cc = 10
    
        def drive(self, distance):
            fuel_consumed = distance * 0.05 * self.cc
            return fuel_consumed
    

    Una vez que hayas definido esta clase compatible con numba, puedes usarla como tipo para el atributo car en la clase Honda, de la siguiente manera:

    @jitclass([
        ('car', NumbaCar),
    ])
    class Honda(object):
        def __init__(self):
            self.car = NumbaCar()
    
        def cal(self):
            # realizar cálculos pesados
            pass
    

    Ahora puedes usar la clase Honda con numba y debería funcionar como se espera. Ten en cuenta que cualquier método que desees usar con numba dentro de la clase Honda también debe decorarse con los decoradores @njit o @jit, según corresponda.

    Otro enfoque es definir el método cal fuera de la clase Honda, como una función independiente que recibe un objeto Honda como entrada. Esta función luego se puede decorar con los decoradores @njit o @jit, según corresponda. Aquí tienes un ejemplo:

    def honda_cal(honda):
        # realizar cálculos pesados
        pass
    
    @jit(nopython=True)
    def jit_honda_cal(honda):
        # realizar cálculos pesados en código compilado
        pass
    
    @jitclass([
        ('car', types.pyobject),
    ])
    class Honda(object):
        def __init__(self):
            self.car = Car()
    
    # ejemplo de uso
    h = Honda()
    honda_cal(h)  # se ejecuta en modo Python
    jit_honda_cal(h)  # se ejecuta en código compilado con numba
    

    Ten en cuenta que, en este enfoque, no puedes usar los decoradores @njit o @jit directamente en el método dentro de la definición de la clase, porque numba aún no lo admite. En su lugar, debes definir el método fuera de la clase y luego pasar el objeto Honda como argumento.

    En general, aunque hay algunas limitaciones al usar numba con objetos de Python, aún hay formas de sortearlas y lograr mejoras significativas en el rendimiento.

Comments are closed.