Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to improve Brownian motion monte carlo simulation speed?

I want to make my code run faster for more iterations and runs. Right now my code is too slow, but I don't know what to change to speed it up. I began by coding a kinetic Monte Carlo simulation, then editing it to become a Brownian motion simulation. My current code can't handle 10,000 runs with 10,000 iteration each, which is needed.

import numpy as np
import matplotlib.pyplot as plt
import time
%matplotlib inline

runs = int(input("Enter number of runs: "))
N = int(input("Enter number of iterations per simulation: "))

y = 0
R = 10*1  # R is the rate value
t0 = time.time()
for y in range(runs):  # Run the simulation 'runs' times
    T = np.array([0])
    dt = 0
    x = 0.5  # sets values 
    X = np.array([x])
    t = 0
    i = 0

    while t < N:  # N is the number of iterations per run
        i = i + 1  # i is number of iterations so far
        z = np.random.uniform(-1, 1, 1)  # sets z to be a random number between -1 to 1 size 1

        if z > (1/3):  # if conditions for z for alpha and gamma, beta 
            x = x + 1  # z[]=alpha state then + 1
        elif z < (-1/3):
            x = x-1  # z[]=gamma state then - 1
        elif z < (1/3) and z > (-1/3):
            x = x  # z=beta state then + 0

        X = np.append(X, x)  # adds new X value to original X array
        X[i] += X[i-1] * 0.01 * np.random.normal(0, 1, 1) * np.sqrt(dt)  # for Brownian motion with sigma as 0.01
        Z = np.random.uniform(0, 1)  # sets Z to be a random number between 0 and 1
        dt = 1/R * np.log(1/Z)  # formula for dt; R is the rate value
        t = t + dt  # ITERATED TIME
        T = np.append(T, t)
        plt.plot(T, X, lw='0.5', alpha=0.5)

t1 = time.time()
print("final %.10f seconds " % (t1-t0))
like image 700
pythonnewbie22 Avatar asked Nov 07 '22 19:11

pythonnewbie22


1 Answers

Here is an excellent example of a fast-running Brownian Motion Monte Carlo Simulation which is less computationally-expensive.

I've done the same thing as you in the past and made each step of each iteration take place within nested loops. Perhaps its the cost of context switching, running through different libraries, or simply running out of memory, but running each step of the code in each iteration definitely brought about slower performance and higher memory use.

In the above example the author creates arrays first and then iterates through them accordingly with a single for loop. All the random numbers are generated and placed into an array at the same time. Then all the Brownian Motion returns are calculated at the same time. etc. (Think of an assembly line - utilizing resources very well on each step and attaining economies of scale.) Critically also, take note that the plt function is run only one time (not within the loop) and only after all the iterations are complete.

This method should allow for a much higher number of iterations on much smaller hardware.

like image 63
MonteCarloSims Avatar answered Nov 15 '22 12:11

MonteCarloSims