Avoiding CPU branching on leapfrog simulation
up vote
0
down vote
favorite
I have written a computational simulation that accepts some optional parameters (as boundary conditions). As shown in the code below
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
While the code works fine, it for sure triggers CPU branching since I check if I added boundary condition in main and secondary grid (u
and v
) at left and right (_l
and _r
), for example, u_l
means left boundary condition in main grid.
u_l
, u_r
, v_l
and v_r
are numpy arrays like np.array([0])
. I need to add dimension, otherwise (if a scaler) it has no len and also that makes things more uniform.
In other hands sometimes I do not want to add boundary conditions, in these cases I use the if
statement to catch it.
My question is, is there any way to avoid the branching (and all ifs)?
Of course, I could create 'specialized' functions with and without boundary condition (in main and secondary grids), but I'm looking a more generic approach.
Also, any other hints to improve the code are very welcome.
python-3.x numerical-methods branch-prediction
add a comment |
up vote
0
down vote
favorite
I have written a computational simulation that accepts some optional parameters (as boundary conditions). As shown in the code below
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
While the code works fine, it for sure triggers CPU branching since I check if I added boundary condition in main and secondary grid (u
and v
) at left and right (_l
and _r
), for example, u_l
means left boundary condition in main grid.
u_l
, u_r
, v_l
and v_r
are numpy arrays like np.array([0])
. I need to add dimension, otherwise (if a scaler) it has no len and also that makes things more uniform.
In other hands sometimes I do not want to add boundary conditions, in these cases I use the if
statement to catch it.
My question is, is there any way to avoid the branching (and all ifs)?
Of course, I could create 'specialized' functions with and without boundary condition (in main and secondary grids), but I'm looking a more generic approach.
Also, any other hints to improve the code are very welcome.
python-3.x numerical-methods branch-prediction
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I have written a computational simulation that accepts some optional parameters (as boundary conditions). As shown in the code below
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
While the code works fine, it for sure triggers CPU branching since I check if I added boundary condition in main and secondary grid (u
and v
) at left and right (_l
and _r
), for example, u_l
means left boundary condition in main grid.
u_l
, u_r
, v_l
and v_r
are numpy arrays like np.array([0])
. I need to add dimension, otherwise (if a scaler) it has no len and also that makes things more uniform.
In other hands sometimes I do not want to add boundary conditions, in these cases I use the if
statement to catch it.
My question is, is there any way to avoid the branching (and all ifs)?
Of course, I could create 'specialized' functions with and without boundary condition (in main and secondary grids), but I'm looking a more generic approach.
Also, any other hints to improve the code are very welcome.
python-3.x numerical-methods branch-prediction
I have written a computational simulation that accepts some optional parameters (as boundary conditions). As shown in the code below
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
While the code works fine, it for sure triggers CPU branching since I check if I added boundary condition in main and secondary grid (u
and v
) at left and right (_l
and _r
), for example, u_l
means left boundary condition in main grid.
u_l
, u_r
, v_l
and v_r
are numpy arrays like np.array([0])
. I need to add dimension, otherwise (if a scaler) it has no len and also that makes things more uniform.
In other hands sometimes I do not want to add boundary conditions, in these cases I use the if
statement to catch it.
My question is, is there any way to avoid the branching (and all ifs)?
Of course, I could create 'specialized' functions with and without boundary condition (in main and secondary grids), but I'm looking a more generic approach.
Also, any other hints to improve the code are very welcome.
python-3.x numerical-methods branch-prediction
python-3.x numerical-methods branch-prediction
edited Nov 9 at 15:27
Elham Esmaeeli
795
795
asked Nov 9 at 15:13
Lin
424214
424214
add a comment |
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53228388%2favoiding-cpu-branching-on-leapfrog-simulation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown