В последние дни я ищете эффективный способ отправить в часть кода Numba все переменные (в основном логические значения, целые числа, числа с плавающей запятой и массивы с плавающей запятой), стараясь при этом сохранить код читабельным и понятным. В моем случае это подразумевает ограничение количества аргументов и, если возможно, перегруппировку некоторых переменных в зависимости от системы, к которой они относятся.
Я определил четыре способа сделать это:
- брутфорс: отправка всех переменных по одной в качестве аргументов первой вызванной функции Numba. Я считаю, что это решение неприемлемо, поскольку оно делает код едва читаемым (очень большой список аргументов) и несовместимым с моим желанием перегруппировать переменные,
- Словари, набранные Numba (см., например, этот пост): Я не нашел это решение приемлемым, поскольку я понимаю, что данный словарь может содержать только переменные похожих типов (например, словарь float64), в то время как данная система может иметь связанные переменные разных типов. типы. Кроме того, я заметил значительную потерю производительности (~ +10 % времени вычислений) при использовании этой опции.
- Numba Nametuples: довольно проста в реализации и использовании, но я понимаю, что их можно эффективно использовать только в том случае, если они определены в функции Numba, и, следовательно, их нельзя отправить из необработанной функции/кода в jitted-функцию, не делая невозможным получение выгоды от опции кэш=True . Для меня это является препятствием, поскольку время компиляции может превышать время выполнения самого кода.
- Numba @jitclass: изначально я не хотел использовать классы для своего кода. но оказывается, что это очень практично... но, как и в случае с именованными кортежами, если объект из @jitclass инициализируется внутри необработанной функции, я заметил, что становится невозможно извлечь из этого выгоду опция кэш=True (см. этот пост).
Вот что я сделал в итоге: я объединил использование обычных классов Python и Numba @jitclass чтобы сохранить возможность использовать опцию кэша=True.
Вот мой mwe:
Код: Выделить всё
import numba as nb
from numba import jit
from numba.experimental import jitclass
spec_cls = [
('a', nb.types.float64),
('b', nb.types.float64),
]
# python class
class ClsWear_py(object):
def __init__(self, a, b):
self.a = a
self.b = b
# mirror Numba class
@jitclass(spec_cls)
class ClsWear(object):
def __init__(self, a, b):
self.a = a
self.b = b
def function_python(obj):
print('from the python class :', obj.a)
# call of a Numba function => this is where I must list explicitly all the keys of the python class object
oa, ob = function_numba(obj.a, obj.b)
return obj, oa, ob
@jit(nopython=True)
def function_numba(oa, ob):
# at the beginning of the Numba function, the arguments are used to define the @jitclass object
obj_nb = ClsWear(oa, ob)
print('from the numba class :', obj_nb.a)
return obj_nb.a, obj_nb.b
# main code :
obj_py = ClsWear_py(11,22)
obj_rt, a, b = function_python(obj_py)
Код: Выделить всё
$ python mwe.py
from the python class : 11
from the numba class : 11.0
- У меня чистая структура данных в Python и Numba (использование классов)< /li>
У меня быстро работает код, и кэш=True работает
- Надо определить классы Python и их зеркало в Numba
- осталась одна едва читаемая часть кода: первый вызов jitted-функции, в которой все содержимое моих объектов должно быть указано явно
Подробнее здесь: https://stackoverflow.com/questions/790 ... -functions