Как создать список структурированных скаляров в Numba? - PullRequest
0 голосов
/ 10 ноября 2019
import numpy as np
from numba import njit

dt = np.dtype([('x', np.float64), ('y', np.float64)])

@njit
def f():
#    a = np.zeros(2, dtype=dt)         # this works
#    return a['x']
    b = np.array((0.5, 1.5), dtype=dt)    # this doesn't
#    return b['x']
f()

Сообщение об ошибке:

NotImplementedError: Cannot cast float64 to Record(x[type=float64;offset=0],y[type=float64;offset=8];16;False): %".69" = phi double [%".70", %"switch.0"], [%".72", %"switch.1"]

Без @jit все работает нормально.

Что я действительно пытаюсь добиться, так это создать список пользовательских скаляров dtype. Я пробовал следующие альтернативы:

  • массив numpy не подходит, так как количество элементов заранее неизвестно,
  • список векторов numpy требует слишком многочисловое индексирование, что я стараюсь избегать
  • список диктов (предположительно) занимает слишком много памяти
  • слишком большой массив объединенных классов слишком медленный по сравнению с любым из других перечисленных вариантоввыше.

Обновление: Самая дальняя точка, которую я смог получить, это:

dt = np.dtype([('x', np.float64), ('y', np.float64)])
@nb.njit
def f():
    a = np.array((0.5, 1.5))
    b = a.view(dt)
    return b.x
f()

array([0.5])

, но это не скаляр, это 1-размерный массив (с @jit или без него).

Update2:

Функции пока не покрыты numba.

from numpy.lib import recfunctions
from numba import njit
dt = np.dtype([('x', np.float64), ('y', np.float64)])
@njit
def f():
    a = np.array((1,2))
    b = recfunctions.unstructured_to_structured(a, dt)
    return b['x']
f()

Unknown attribute 'unstructured_to_structured' of type 
Module(<module 'numpy.lib.recfunctions'

1 Ответ

1 голос
/ 10 ноября 2019

Очевидно, numba не полностью реализовал функциональность структурированного массива numpy. Ошибка указывает на то, что возникают проблемы с присвоением значений из кортежа определенному массиву.

Поиграв немного, я обнаружил, что это работает:

In [399]: dt = np.dtype([('x', np.float64),('y', np.float64)])                  
In [400]: @numba.njit 
     ...: def nf(vals, dt): 
     ...:     b = np.zeros((), dtype=dt) 
     ...:     b['x'][...] = vals[0] 
     ...:     b['y'][...] = vals[1] 
     ...:     return b 
     ...:                                                                       
In [401]: nf((.5,1.5),dt)                                                       
Out[401]: array((0.5, 1.5), dtype=[('x', '<f8'), ('y', '<f8')])

Или создать массив 1d:

In [405]: @numba.njit 
     ...: def nf1(n, x, y , dt): 
     ...:     b = np.zeros(n, dtype=dt) 
     ...:     b['x'][...] = x 
     ...:     b['y'][...] = y 
     ...:     return b 
     ...:                                                                       
In [406]: nf1(3, np.arange(3), np.ones(3), dt)                                  
Out[406]: array([(0., 1.), (1., 1.), (2., 1.)], dtype=[('x', '<f8'), ('y', '<f8')])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...