Предотвращение ветвления процессора при симуляции перепрыгивания - PullRequest
0 голосов
/ 09 ноября 2018

Я написал вычислительное моделирование, которое принимает некоторые необязательные параметры (в качестве граничных условий). Как показано в коде ниже

def leapfrog(dx, dt, u_0, v_0, U, V, u_l=None, u_r=None, v_l=None, v_r=None, 
        n_max=None, **kwargs):
    """Every call returns a timestep of leapfrog iteration given:
        dx: Spatial step
        dt: Time step
        u0: Initial condition of regular grid
        v0: Initial condition of staggered grid
        U: Operator to apply over the regular grid
        V: Operator to apply over staggered grid
        u_l: left boundary condition to regular grid
        u_r: right boundary condition to regular grid
        v_l: left boundary condition to staggered grid
        v_r: right boundary conditiion to staggered grid
        n_max: If nmax is given, stops after n_max iterations (> 2)

        For every call returns another timestep

    """
    # Initial condition
    yield u_0, v_0

    # First iteration
    u = u_0 - (dt/dx) * (V @ v_0)
    if u_l is not None:
        u[:len(u_l)] = u_l
    if u_r is not None:
        u[-len(u_r):] = u_r

    v = v_0 - (dt/dx) * (U @ u_0)
    if v_l is not None:
        v[:len(v_l)] = v_l
    if v_r is not None:
        v[-len(v_r):] = v_r
    yield u, v

    # All other iterations
    for n in itertools.count(start=2, step=1):
        u = u - (dt/dx) * (V @ v)
        if u_l is not None:
            u[:u_l.size] = u_l
        if u_r is not None:
            u[-u_r.size:] = u_r

        v = v - (dt/dx) * (U @ u)
        if v_l is not None:
            v[:v_l.size] = v_l
        if v_r is not None:
            v[-v_r.size:] = v_r

        if n_max is not None and n >= n_max:
            break

        yield u,v

Хотя код работает нормально, он наверняка вызывает ветвление ЦП, поскольку я проверяю, добавил ли я граничное условие в основную и вторичную сетку (u и v) слева и справа (_l и _r) Например, u_l означает условие левой границы в основной сетке.

u_l, u_r, v_l и v_r являются массивами типа numpy, такими как np.array([0]). Мне нужно добавить размерность, в противном случае (если масштабатор) у него нет len, а также это делает вещи более равномерными .

В других руках иногда я не хочу добавлять граничные условия, в этих случаях я использую оператор if, чтобы поймать его.

У меня вопрос, есть ли способ избежать разветвления (и все если)?

Конечно, я мог бы создавать «специализированные» функции с и без граничных условий (в основной и вторичной сетках), но я ищу более общий подход.

Также приветствуются любые другие советы по улучшению кода.

...