Link to this document's Jupyter Notebook

In order to successfully complete this assignment you need to participate both individually and in groups during class. If you attend class in-person then have one of the instructors check your notebook and sign you out before leaving class on Wednesday March 17. If you are attending asynchronously, turn in your assignment using D2L no later than _11:59pm on Wednesday March 17.


In-Class Assignment: Parallel Python

Image from: https://www.amazon.com/

Agenda for today's class (70 minutes)

  1. (20 minutes)Pre class Review
  2. (30 minutes)How do you make Python go faster?
  3. (20 minutes)Wave Equation

1. Pre class Review

0318--Parallel_Python_pre-class-assignment


2. How do you make Python go faster?

What Ideas did you find using google?


3. Wave Equation

In this section we will explore the speed of a 1D wave equation simulation. This section can be broken up into the following subsections:

Wave equation overview

This subsection describes the math behind this particular 1D wave simulation. Knowing this math is not important to the lesson on speeding up code but is included for completness (And I already had it written up).

The wave equation is an second-order linear partial differential equation for the description of waves as they occur in classical physics (for example: water waves, sound waves and seismic waves, light waves). The basic algorithm splits the wave into a grid of points and calculates the point's position, velocity and acceleration. The key incite to making the wave equations work that an individuals point will lead/follow the behavior of that points neighbors.

In the 1D case we will model a line of points in the x-direction such that thy can only move in the y direction. The position for each point $y$ can be calculated by the particle's previous position and the particle's velocity multiplied by the change in time:

$$y_{i+1} = y_i + \dot{y}_idt$$

Notation: $$\frac{dy}{dt} = \dot{y} = v = \text{velocity of particle in y direction}$$

We calculation the velocity using the acceleration:

$$\dot{y}_{i+1} = \dot{y}_i + \ddot{y}_idt$$

Notation: $$\frac{d^2y}{dt^2} = \frac{dv}{dt} = \ddot{y} = a = \text{acceleration of particle in y direction}$$

Given the above equations, if we know the starting values $y_0$, $\dot{y}_0$, $\ddot{y}_0$ then the only unknown is the equation for how the acceleration changes.

Wave Equation: We will estimate acceleration in time by using acceleration in space. Intuitively we can think about this as any point can estimate where it will be in the future by looking at it's neighbors. Mathematically we show this equation as follows:

$$\frac{d^2y}{dt^2} = \gamma\frac{d^2y}{dx^2}$$

We know the acceleration in space using the Euler's finite difference of the particle's position:

$$\frac{d^2y}{dx^2} \approx \frac{y[i+1]-2y[i]+y[i-1]}{dx^2}$$

To get the above equation we estimate the velocity to the Left and Right (Before and After) the point of interest using Finite Difference:

$$\dot{y}[i]_L = \frac{y[i]-y[i-1]}{dx}$$$$\dot{y}[i]_R = \frac{y[i+1]-y[i]}{dx}$$

Second, using the Left and Right Velocity, we use finite difference again to estimate the acceleration:

$$\ddot{y}[i] = \frac{\dot{y}[i]_R - \dot{y}[i]_L}{dx}$$

Putting it all together and simplifying we get the followign:

$$\ddot{y}[i] = \frac{y[i+1]-2y[i]+y[i-1]}{dx^2}$$

Given the above we can calculate a points position at time step $t+1$ by using it's position/velocity at timestep $t$ and it's neighbors position at time step $t-1$.

Pseudocode and settings for 1D Wave Equation

Divide simulation into grid in the x direction

$xmin = 0; xmax=10; nx=500$

$dx = \frac{xmax-xmin}{nx}$

$x = \text{linspace}(xmin, xmax, nx)$ #Returns a row vector of nx evenly spaced points between xmin and xmax.

Divide time into discrete units

$tmin = 0; tmax=10; nt=1000000$

$dt = \frac{tmax-tmin}{nt}$

$times = \text{linespace}(tmin,tmax, nt)$ #Returns a row vector of nt evenly spaced points between tmin and tmax.

Initialize starting position as a simple pulse

$y_i = e^{-(x_i-5)^2}$ for all $i \in [0,nx)$

Initialize velocity and acceleration to zero

$\dot{y}_i = 0$ for all $i \in [0,nx)$

$\ddot{y}_i = 0$ for all $i \in [0,nx)$

$\gamma = 1$

Run the simulation of t timesteps

Loop over index $t$ in $times$:

$\ddot{y}_0 = 0$ # Keep acceleration to zero on ends

$\ddot{y}_{nx-1} = 0$ # Keep acceleration to zero on ends

$\ddot{y}_i \approx \gamma \frac{y_{(i+1)} + y_{(i-1)}-2y_i}{dx^2}$ for all $i \in (0,nx-1)$ # Estimate acceleration using position

$y_i = y_i + \dot{y}_i dt$ for all $i \in [0,nx)$ # Update position

$\dot{y}_{i} = \dot{y}_i+ \ddot{y}_idt$ for all $i \in [0,nx)$ # Update velocity

Basic Python Example

DO THIS: Run the above simple python simulation (It will take a while) with the show variable set to True and False. Record the time it takes to run below.

Put your times here

Vectorizing code with Numpy

Numpy uses C-compiled code to speed up Python. Most slowdown's in code happen when there are big loops. Numpy uses a lot of very cool tricks (ex vectorization) to make loops go really fast. SO, the trick to making Numpy go fast is to let Numpy run your loops for you.

Consider the 1D wave equation example:

DO THIS: Run the above numpy python simulation (It will take a while) with the show variable set to True and False. Record the time it takes to run below.

Put your times here

Compiling Python code using Numba

Numba is a module that takes your standard python function and turns it into c-code then compiles/runs the c version of the funciton. It can speed things up very nicely. In this example, we will use the @jit (Just in time) to convert the code in seciton 2 (Slow 2D Wave Equation Example) to work with numba. Here are the steps:

  1. Import the numba jit module usingfrom numba import jit
  2. Copy all of your code into a function so jit has something to work with.
  3. Add the @jit with options before the declaration of the function to enable just in time compiling on the function.

DO THIS: Run the above simple python simulation (It will take a while) with the show variable set to True and False. Record the time it takes to run below. NOTE: You will probably get some compile warnings, irgnore these for now.

Put your times here

DO THIS: Modify the function to only use "core" python methods only. i.e. completely comment out all lines of code that use libraries such as numpy and/or matplotlib. IN the above example, comment out lines 40-45. Record the time it takes to run below. NOTE: This will get rid of the compile warnings from above.

Put your times here

Parallel Python

Another way to achieve speedup is to utilize multiple processors on your computer.

DO THIS: Replace the jit line from above with the following @jit (nopython=True, parallel=True). When avaliable this will run the code on more than one core. Give it a try and record your results.

Put your times here

DO THIS: Take your results from the entire study and plot them.✅


Congratulations, we're done!

If you attend class in-person then have one of the instructors check your notebook and sign you out before leaving class. If you are attending asynchronously, turn in your assignment using D2L.

Course Resources:

Written by Dr. Dirk Colbry, Michigan State University Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.