Monte Carlo 模拟:为什么随机点数越少处理时间越长?

Monte Carlo Simulation: Why is the processing time greater for a smaller number of random points?

我正在编写一个 Monte Carlo 模拟来估计 Pi 的值,并且我正在记录每个连续点数所需的总处理时间为 运行 秒。奇怪的是,处理时间似乎开始随着每个 运行 而减少,然后随着点数的增加而随着每个 运行 而增加。我已经用 perf_counter()、time()、clock() 和 default_timer() 对此进行了测试。我也尝试使用 CPU 时钟函数(如 process_time() 和 thread_time() 进行测试,但对于大多数 运行s,它 return将总处理时间设为 0.0。

为什么CPU定时器总时间return0.0,而时钟定时器有这样奇怪的趋势?我希望处理时间线性增加,但显然情况并非如此,除非我的代码某处存在问题。我已经包含了我的代码和情节作为示例。

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()

Plot for Processing Time vs Number of Points

试试

N = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1]

您将看到以下结果:

n =  1  t =  6.614800076931715e-05
n =  10  t =  2.7269999918644316e-05
n =  100  t =  2.177599981223466e-05
n =  1000  t =  4.9498999942443334e-05
n =  10000  t =  0.00042855599986069137
n =  100000  t =  0.0026685809998525656
n =  1000000  t =  0.021433439000247745
n =  10000000  t =  0.19109468099941296
n =  1000000  t =  0.019547208999938448
n =  100000  t =  0.0036834789998465567
n =  10000  t =  0.0002759440003501368
n =  1000  t =  3.2883999665500596e-05
n =  100  t =  1.4722999367222656e-05
n =  10  t =  1.0972000382025726e-05
n =  1  t =  1.0822999684023671e-05

和编译代码有关。在你第一次调用你的函数后,代码就被编译了。所以第一次调用需要很长时间做初始处理。对于小 n,内存管理的时间与计算本身相当。