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.










share|improve this question




























    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.










    share|improve this question


























      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.










      share|improve this question















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 9 at 15:27









      Elham Esmaeeli

      795




      795










      asked Nov 9 at 15:13









      Lin

      424214




      424214





























          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          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






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          Schultheiß

          Verwaltungsgliederung Dänemarks

          Liste der Kulturdenkmale in Wilsdruff