I'm writing a Monte Carlo simulation to estimate the value of Pi, and I am recording the total processing time required for each successive number of points as it runs. Oddly enough, it seems that the processing time starts out decreasing with each run, then increases with each run as the number of points increases. I've tested this with perf_counter(), time(), clock(), and default_timer(). I've also attempted to test this with CPU clock functions like process_time() and thread_time() as well, but for most runs, it returned the total processing time as 0.0.
Is there a reason that the CPU timers return 0.0 as the total time, while the clock timers have such an odd trend? I'd expect the processing time to increase linearly, but clearly this is not the case unless there is an issue with my code somewhere. I've included both my code and a plot as an example.
import numpy as np
from numpy import random
import matplotlib.pyplot as plt
import time
import math
#Plot number of points vs fractional error of pi)
def piPlot(piList):
#Set correct plot size
piAx = plt.gca()
piAx.set_aspect(1)
#Generate and label plot, set to logarithmic scale
plt.scatter(N,piList)
plt.xscale("log")
plt.yscale("log")
plt.title('Fractional Error vs Number of Points')
plt.xlabel('Number of Points [Logarithmic]')
plt.ylabel('Fractional Error [Logarithmic]')
#Plot generator for number of points vs processing time
def timePlot(timeList):
#Set correct plot size
timeAx = plt.gca()
timeAx.set_aspect(1)
#Generate and label plot, set to logarithmic scale
plt.scatter(N,timeList)
plt.xscale("log")
plt.yscale("log")
plt.title('Processing Time vs Number of Points')
plt.xlabel('Number of Points [Logarithmic]')
plt.ylabel('Processing Time [Logarithmic]')
def simulation(n, t):
#Begin timer
startTime = t
#Initialize list for current run
run = []
#Generate random points, find number inside circle
xPoint = np.random.rand(n)
yPoint = np.random.rand(n)
total = ((xPoint ** 2) + (yPoint ** 2) <= 1).sum()
#Estimate pi
pi = 4*(total/n)
run.append(pi)
#End timer, calculate total processing itme
endTime = time.perf_counter()
T = endTime - startTime
run.append(T)
return run
def main():
#Define the total numbers of points for each simulation
N = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000]
#Run the simulation and calculate fractional error for returned pi
results1 = [simulation(i, time.perf_counter()) for i in N]
pis1, times1 = map(list, zip(*results1))
error1 = [abs((math.pi - i)/math.pi) for i in pis1]
#Generate plots
plot1 = plt.figure(1)
piPlot(error1)
plot2 = plt.figure(2)
timePlot(times1)
main()