Numba in a class: TypingError: non-precise type pyobject

Hi,

I’m trying to run the following snippet using numba; some aspects might be clumsy but I do not understand how to specify a type to numba. What am i missing?

Thanks

paul

from numba import jit, prange
import numpy as np


class test:
    
    def __init__(self, M: np.ndarray = np.array([])) -> np.ndarray:
        
        self.M = M
        
    @jit(nopython=True, parallel=True)
    def eigenValues(self):
        
        Matrix = self.M
        
        r, c = np.shape(Matrix)
        M_princ = np.zeros( (r, 3), dtype = np.float64)
        
        
        for i in prange(r):  
            A = np.array( [[Matrix[i, 0], Matrix[i, 1], Matrix[i, 2]],
                           [Matrix[i, 1], Matrix[i, 3], Matrix[i, 4]],
                           [Matrix[i, 2], Matrix[i, 4], Matrix[i, 3]]])
            
            val, vect = np.linalg.eig(A)
            index = val.argsort()[::-1]
            M_princ[i, :] = val[index]
        
        return(M_princ)
    
    
    
if __name__ == "__main__":
    
    n = 10
    tensor = 10.25*np.random.rand(n,6)
    
    obj = test(M = tensor)
    eigen_val = obj.eigenValues()

Normal python classes don’t work with numba, can you reformulate the problem without a class?

Or try jitclass/structref. But plain functions are simplest.

Hi

Thanks for the answer.

No i can’t. The code mimic a current dev using oop.

After digging in internet, i found the following solution; some topic remain unclear for me for the moment, but it seems to work: is it correct? something to improve?

Thanks

Paul

import numba as nb
from numba.experimental import jitclass
import numpy as np
import time

# https://stackoverflow.com/questions/67458749/how-to-create-a-list-of-numpy-arrays-in-jitclass

float_array = nb.types.Array(dtype = nb.float64, ndim = 2, layout= 'A')
spec = [('M', float_array)]

@jitclass(spec)
class test:
    
    def __init__(self, M):
        
        self.M = M
        
    def eigenValues(self):
        
        Matrix = self.M
        
        r, c = np.shape(Matrix)
        M_princ = np.zeros( (r, 3), dtype = np.float64)
        
        
        for i in range(r):  
            A = np.array( [[Matrix[i, 0], Matrix[i, 1], Matrix[i, 2]],
                           [Matrix[i, 1], Matrix[i, 3], Matrix[i, 4]],
                           [Matrix[i, 2], Matrix[i, 4], Matrix[i, 3]]])
            
            val, vect = np.linalg.eig(A)
            index = val.argsort()[::-1]
            M_princ[i, :] = val[index]
        
        return(M_princ)
    
    
    
if __name__ == "__main__":
    
    n = 100_000
    tensor = 10.25*np.random.rand(n,6)
    
    obj = test(M = tensor)
    t0 = time.time()
    eigen_val = obj.eigenValues()
    t1 = time.time()
    print(f"Duration = {t1 - t0}")

Imagine now that i want to pass arguments not using the constructor, but through a method, where can i found informations?

Thanks

import numba as nb
from numba import int64
from numba.experimental import jitclass
import numpy as np

# https://stackoverflow.com/questions/67458749/how-to-create-a-list-of-numpy-arrays-in-jitclass

float_array = nb.types.Array(dtype = nb.float64, ndim = 2, layout= 'A')
spec = [('M', float_array),
        ('row', int64),
        ('col', int64),]

@jitclass(spec)
class test(object):
    
    # constructor
    def __init__(self):
        pass
      

    # method    
    def CreateMatrix(self, row = 0, col = 0):
        
        self.M = 10.25*np.random.rand(row, col)


    # method    
    def eigenValues(self):
        
        Matrix = self.M
        
        r, c = np.shape(Matrix)
        M_princ = np.zeros( (r, 3), dtype = np.float64)
        
        
        for i in range(r):  
            A = np.array( [[Matrix[i, 0], Matrix[i, 1], Matrix[i, 2]],
                           [Matrix[i, 1], Matrix[i, 3], Matrix[i, 4]],
                           [Matrix[i, 2], Matrix[i, 4], Matrix[i, 3]]])
            
            val, vect = np.linalg.eig(A)
            index = val.argsort()[::-1]
            M_princ[i, :] = val[index]
        
        return(M_princ)

Perhaps the trick in this thread (4th post) of allocating the object with “new” instead of using the constructor, and then setting each attribute of the object might work. Or you could just call the constructor directly in your method. Note 1) that the linked example uses structref instead of jitclass, I don’t recall if there is a different special new() for jitclass, you can check the jitclass source 2) if you don’t set every attribute when you do this approach then it is possible to have uninitialized values in the object that have undefined behavior.