Support @boost in classes with methods and functions calls

Issue #8 wontfix
Pierre Augier created an issue
from fluidpythran import Type, NDim, Array, boost

import numpy as np

T = Type(int, np.float64)
N = NDim(1)

A1 = Array[T, N]
A2 = Array[float, N + 1]

def sum_arrays(arr0, arr1):
    return arr0 + arr1

@boost
class MyClass:

    arr0: A1
    arr1: A1
    arr2: A2

    def __init__(self, n, dtype=int):
        self.arr0 = np.zeros(n, dtype=dtype)
        self.arr1 = np.zeros(n, dtype=dtype)
        self.arr2 = np.zeros(n)

    @boost
    def compute(self, alpha: float):
        tmp = self.sum_arrays().mean()
        return tmp ** alpha * self.arr2

    def sum_arrays(self):
        return self.arr0 + self.arr1

    @boost
    def compute1(self, alpha: float):
        tmp = sum_arrays(self.arr0, self.arr1).mean()
        return tmp ** alpha * self.arr2

class MyClassChild(MyClass):
    def sum_arrays(self):
        return 2 * self.arr0 + self.arr1

With classes, we have a problem with heritage. Note that for standard functions (like sum_arrays), we actually also have the problem with monkey patching.

We can just say that monkey patching of sum_arrays is not supported (so that sum_arrays can be treated as a Pythran function, and potentially inlined) but for class, we really want to support heritage (like in MyClassChild) so we would need to replace compute by a Python method calling Pythran functions and Python methods (which themselves call Pythran functions).

The mechanism needed for compute is much more complicated than the simple case in pythran_class.py and more complicated than what is needed for compute1 (which is actually similar to issue #7).

Comments (8)

  1. Pierre Augier reporter

    I don't think Cython would add anything great in this case. Anyway, Python classes in Cython are just Python classes. They use the interpreter exactly the same way as normal Python class. But you need to compile...

    Moreover, one will have exactly the same problem in Cython than in Python. If we want to be able to replace self.sum_array in MyClassChild (in another Python file), we cannot inline self.sum_array.

    Thus, it is better to use pure Python solution + Pythran.

  2. Pierre Augier reporter

    Function calls in methods (case of compute1) is now supported with FluidPythran 0.1.5 (using @include).

    For method calls, I think the solution proposed in #29 (blocks) is much better than what we have here. With blocks, we clearly see that we use Python to call the method.

    With method call in boosted methods, it is not clear if the called method is Pythranized.

    • if it is pythranized, we have the problem with inheritance described above.
    • if it is not pythranized, we have no way to follow the types.

    I close this issue because I think the better solution is

    • to say that method calls in boosted methods will not be supported
    • if we need method calls, we can used blocks and it is also possible to "boost" the called methods.

    Example for the case above:

    @boost
    class MyClass:
    
        arr0: A1
        arr1: A1
        arr2: A2
    
        def __init__(self, n, dtype=int):
            self.arr0 = np.zeros(n, dtype=dtype)
            self.arr1 = np.zeros(n, dtype=dtype)
            self.arr2 = np.zeros(n)
    
        @with_blocks
        def compute(self, alpha: float):
            tmp = self.sum_arrays()
    
            with block(tmp=A1):
                tmp = tmp.mean()
                return tmp ** alpha * self.arr2
    
        @boost
        def sum_arrays(self):
            return self.arr0 + self.arr1
    

    Note that we explicitly give the type of tmp with with block(tmp=A1):. We could also use with cachedjit_block():...

  3. Log in to comment