Alternative syntax for `# pythran block`

Issue #9 closed
Pierre Augier created an issue

An alternative syntax for # pythran block could be:

import numpy as np
# pythran import numpy as np

from fluidpythran import pythran_block

class MyClass:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    @pythran_block
    def compute(self, n):

        a = self.a
        b = self.b

        # pythran block (
        #     float[][] a, b;
        #     int n
        # ) -> result

        # pythran block (
        #     float[][][] a, b;
        #     int n
        # ) -> result

        result = np.zeros_like(a)
        for _ in range(n):
            result += a ** 2 + b ** 3

        # pythran end block

        return result

Advantages

Drawbacks

  • more magic and less explicit
  • we would need dynamically generated Python method -> less simple run type exceptions
  • with this alternative syntax, we really need the -> result (but it could be written only once)

Comments (6)

  1. Pierre Augier reporter
    • changed status to open

    Indeed, it is really nicer...

    Regarding the problem of the dynamically generated method leading to less simple exceptions, we have the same problem with # pythran class.

  2. Ashwin Vishnu

    It would be a welcome change, but I also agree it is a bit of magic as only parts of the function are pythranized. An advantage would be toggling between pure python and pythranized versions is easier. Dealing with multiple blocks within the function is not easy however.

  3. Pierre Augier reporter

    Just to see what it gives, what it gives on a real function:

    class TimeSteppingPseudoSpectral(TimeSteppingBase):
    
        @pythran_block
        def _time_step_RK4_fluidpythran(self):
            dt = self.deltat
            diss, diss2 = self.exact_linear_coefs.get_updated_coefs()
    
            compute_tendencies = self.sim.tendencies_nonlin
            state_spect = self.sim.state.state_spect
    
            tendencies_0 = compute_tendencies()
            state_spect_tmp = self._state_spect_tmp
            state_spect_tmp1 = self._state_spect_tmp1
            state_spect_np12_approx1 = state_spect_tmp1
    
            # based on approximation 0
            # pythran block (
            #     complex128[][][] state_spect, state_spect_tmp,
            #                      tendencies_0, state_spect_np12_approx1;
            #     float64[][] diss, diss2;
            #     float dt
            # )
    
            # pythran block (
            #     complex128[][][] state_spect, state_spect_tmp,
            #                      tendencies_0, state_spect_np12_approx1;
            #     complex128[][][] diss, diss2;
            #     float dt
            # )
    
            # pythran block (
            #     complex128[][][] state_spect, state_spect_tmp,
            #                      tendencies_0, state_spect_np12_approx1;
            #     float64[][][] diss, diss2;
            #     float dt
            # )
    
            # pythran block (
            #     complex128[][][][] state_spect, state_spect_tmp,
            #                      tendencies_0, state_spect_np12_approx1;
            #     float64[][][] diss, diss2;
            #     float dt
            # )
    
            state_spect_tmp[:] = (state_spect + dt / 6 * tendencies_0) * diss
            state_spect_np12_approx1[:] = (
                state_spect + dt / 2 * tendencies_0
            ) * diss2
    
            # pythran end block
    
            tendencies_1 = compute_tendencies(
                state_spect_np12_approx1, old=tendencies_0
            )
            del state_spect_np12_approx1
    
            state_spect_np12_approx2 = state_spect_tmp1
    
            # based on approximation 1
            # pythran block (
            #     complex128[][][] state_spect, state_spect_tmp,
            #                      state_spect_np12_approx2, tendencies_1;
            #     float64[][] diss2;
            #     float dt
            # )
    
            # pythran block (
            #     complex128[][][] state_spect, state_spect_tmp,
            #                      state_spect_np12_approx2, tendencies_1;
            #     complex128[][][] diss2;
            #     float dt
            # )
    
            # pythran block (
            #     complex128[][][] state_spect, state_spect_tmp,
            #                      state_spect_np12_approx2, tendencies_1;
            #     float64[][][] diss2;
            #     float dt
            # )
    
            # pythran block (
            #     complex128[][][][] state_spect, state_spect_tmp,
            #                      state_spect_np12_approx2, tendencies_1;
            #     float64[][][] diss2;
            #     float dt
            # )
    
            state_spect_tmp[:] += dt / 3 * diss2 * tendencies_1
            state_spect_np12_approx2[:] = (
                state_spect * diss2 + dt / 2 * tendencies_1
            )
    
            # pythran end block
    
            tendencies_2 = compute_tendencies(
                state_spect_np12_approx2, old=tendencies_1
            )
            del state_spect_np12_approx2
    
            state_spect_np1_approx = state_spect_tmp1
    
            # based on approximation 2
            # pythran block (
            #     complex128[][][] state_spect, state_spect_tmp,
            #                      state_spect_np1_approx, tendencies_2;
            #     float64[][] diss, diss2;
            #     float dt
            # )
    
            # pythran block (
            #     complex128[][][] state_spect, state_spect_tmp,
            #                      state_spect_np1_approx, tendencies_2;
            #     complex128[][][] diss, diss2;
            #     float dt
            # )
    
            # pythran block (
            #     complex128[][][] state_spect, state_spect_tmp,
            #                      state_spect_np1_approx, tendencies_2;
            #     float64[][][] diss, diss2;
            #     float dt
            # )
    
            # pythran block (
            #     complex128[][][][] state_spect, state_spect_tmp,
            #                      state_spect_np1_approx, tendencies_2;
            #     float64[][][] diss, diss2;
            #     float dt
            # )
    
            state_spect_tmp[:] += dt / 3 * diss2 * tendencies_2
            state_spect_np1_approx[:] = (
                state_spect * diss + dt * diss2 * tendencies_2
            )
    
            # pythran end block
    
            tendencies_3 = compute_tendencies(
                state_spect_np1_approx, old=tendencies_2
            )
            del state_spect_np1_approx
    
            # result using the 4 approximations
            # pythran block (
            #     complex128[][][] state_spect, state_spect_tmp, tendencies_3;
            #     float dt
            # )
            # pythran block (
            #     complex128[][][][] state_spect, state_spect_tmp, tendencies_3;
            #     float dt
            # )
    
            state_spect[:] = state_spect_tmp + dt / 6 * tendencies_3
    
            # pythran end block
    
  4. Log in to comment