4

I have a very simple problem I can't solve.

I'm using Numba and Cuda. I have a list T=[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0] and I want a tuple with the elements of the list, like this: C=(1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0).

In Python I would code C=tuple(T), but I can't with Numba.

I tried these solutions but none of them work because you can't modify the type of a variable inside a loop with Numba.

Important My list has a length which is a multiple of 3 and I use this knowledge for my algorithms.

Code

First algorithm, recursively, it works by giving the algorithm L=[(1.0,),(2.0,),(3.0,),(4.0,),(5.0,),...,(9.0,)]

@njit
def list2tuple(L):

    n=len(L)
    if n == 1:
        return L[0]
    else:
        C=[]
        for i in range(0,n-2,3):
            c=L[i]+L[i+1]+L[i+2]
            C.append(c)
        return list2tuple(C)

Problem: It enters an infinite loop and I must stop the kernel. It works in basic Python.

algorithm 2: it works by giving T=[1.0,2.0,3.0,...,9.0]

@njit
def list2tuple2(T):

    L=[]
    for i in range(len(T)):
        a=(T[i],)
        L.append(a)
    for k in range(len(T)//3-1):
        n=len(L)
        C=[]
        for j in range(0,n-2,3):
            c=L[j]+L[j+1]+L[j+2]
            C.append(c)
        L=C
    return L[0]

Problem When C=[(1.0,2.0,3.0),(4.0,5.0,6.0),(7.0,8.0,9.0)], you can't say L=C because L = [(1.0,),(2.0,),(3.0,),....(9.0,)] is List(Unituple(float64x1)) and can't be unified with List(Unituple(float64x3)).

I can't find a solution for this problem.

Pierre00
  • 41
  • 3
  • The beginning of the question is clear but the end is very confusing. `list2tuple` is not recursive since it calls `list2tuple2` and not itself. It also do not convert a list to a tuple as stated but make a sum... It is unclear what you want to convert a list to a tuple. Can you clarify these points? – Jérôme Richard Jan 04 '22 at 20:32
  • Yeah sorry, I clarified my algos but in the end I have a list and I want a tuple with the elements of the list inside. – Pierre00 Jan 05 '22 at 08:09
  • same issue here, do u find a solution? – Nicholas Jela Jul 25 '23 at 10:03

1 Answers1

0

Tuples and list are very different in Numba: a list is an unbounded sequence of items of the same type while a tuple is a fixed-length sequence of items of possibly different type. As a result, the type of a list of 2 element can be defined as List[ItemType] while a tuple of 2 items can be Tuple[ItemType1, ItemType2] (where ItemType1 and ItemType2 may be the same). A list of 3 items still have the same type (List[ItemType]). However, a tuple of 3 element is a completely different type: Tuple[ItemType1, ItemType2, ItemType3]. Numba defines a UniTuple type to easily create a N-ary tuple where each item is of the same type, but this is only for convenience. Internally, Numba (and more specifically the JIT compiler: LLVM-Lite) needs to iterates over all the types and generate specific functions for each tuple type.

As a result, creating a recursive function that works on growing tuples is not possible because Numba cannot generate all the possible tuple type so to be able to just compile all the functions (one by tuple type). Indeed, the maximum length of the tuple is only known at runtime.

More generally, you cannot generate a N-ary tuple where N is variable in a Numba function. However, you can instead to generate and compile a function for a specific N. If N is very small (e.g. <15), this is fine. Otherwise, it is really a bad idea to write/generate such a function. Indeed, for the JIT, this is equivalent to generate a function with N independent parameters and when N is big, the compilation time can quickly become huge and actually be much slower than the actual computation (many compiler algorithms have theoretically a pretty big complexity, for example the register allocation which is known to be NP-complete although heuristics are relatively fast in most practical cases). Not to mention the required memory to generate such a function can also be huge.

Jérôme Richard
  • 41,678
  • 6
  • 29
  • 59
  • Ok big thanks Jerôme ! I kind of understood this thing but you really clarified it ! I thought maybe there was a trick to bypass this but anyway, thank for your explication ! – Pierre00 Jan 07 '22 at 08:14