为了账号安全,请及时绑定邮箱和手机立即绑定

对 Java、Groovy、Jython 和 Python 进行基准测试

对 Java、Groovy、Jython 和 Python 进行基准测试

千万里不及你 2022-05-12 18:52:01
我正在尝试对 PI (3.14159) 飞镖的蒙特卡洛计算进行基准测试。我已经用 Java、Groovy、BeanShell、Julia、Jython 和 Python(Python2 用 C 实现)实现了我的代码。这是我的原始 Java 代码“MonteCarloPI.java”:import java.util.Random; public class MonteCarloPI {     public static void main(String[] args)       {         int nThrows = 0;         int nSuccess = 0;         double x, y;         long then = System.nanoTime();         int events=(int)1e8;         Random r = new Random();          for (int i = 0; i < events; i++) {            x = r.nextFloat();      // Throw a dart            y = r.nextFloat();            nThrows++;            if ( x*x + y*y <= 1 )  nSuccess++;       } double itime = ((System.nanoTime() - then)/1e9); System.out.println("Time for calculations (sec): " + itime+"\n"); System.out.println("Pi = " + 4*(double)nSuccess/(double)nThrows +"\n");      }}这是文件“MonteCarloPI.groovy”中的 Groovy 代码:import java.util.Randomint nThrows = 0int nSuccess = 0double x, ylong then = System.nanoTime()int events=1e8r = new Random()for (int i = 0; i < events; i++) {            x = r.nextFloat()      // Throw a dart            y = r.nextFloat()            nThrows++            if ( x*x + y*y <= 1 )  nSuccess++}itime = ((System.nanoTime() - then)/1e9)System.out.println("Time for calculations (sec): " + itime+"\n")System.out.println("Pi = " + 4*(double)nSuccess/(double)nThrows +"\n")       或者,我删除了诸如“float”和“int”(即松散类型)之类的定义。这使用“松散”类型检查性能。我已将“MonteCarloPI.groovy”重命名为 BeanShell 脚本文件“MonteCarloPI.bsh”(BeanShell 的语法与 Groovy 非常相似)对于标准 Python 语言,代码“MonteCarloPI_CPython.py”如下所示:import random,timenThrows,nSuccess = 0,0then = time.time()events=int(1e8)for i in xrange(events):   x,y = random.random(),random.random();   # Throw a dart                      nThrows +=1   if ( x*x + y*y <= 1 ):  nSuccess+=1itime = time.time() - thenprint ("Time: ",itime,"sec Pi = ",4*nSuccess/float(nThrows))此代码在 CPython 2.7.18(用 C 实现的 Python)或 Jython 2.7.2(Java 实现)中执行。对于 Python 3.8.3(“Python3”),将“xrange”替换为“range”。
查看完整描述

2 回答

?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

不错的作品。有趣的比较你已经到了那里。作为一名 python 开发人员,我想添加一些关于 Python 的额外视图。


我认为它较慢主要是因为动态类型。另一个原因是您正在计算标量值(即使用 for 循环并一次计算一个数字)。Python 的优点之一是使用 NumPy 库的向量计算(这允许同时计算多个数字)。所以,这是我的算法实现。注意:我使用的是 python 3.6。


import numpy as np

import time


start = time.time()


events = int(1e8)

nThrows, nSuccess = 0, 0


x, y = np.random.uniform(size=(2, events))

nSuccess = (x*x + y*y <= 1).sum()

nThrows = events

pi = 4*nSuccess/float(nThrows)


stop = time.time()

print('Time: {}, Pi = {}'.format(stop-start, pi))

以下是我的 i7 x64 计算机 (Windows 10) 上的基准测试结果:


Python (original code):      42.6s  Pi = 3.1414672

Python (my optimized code):  4.7s   Pi = 3.1417642

如您所见,在我的计算机上运行的原始 python 代码比您计算机上的 python 代码慢。因此,优化后的版本可能比 Java 或 Groovy 更快。


希望这可以帮助。


查看完整回答
反对 回复 2022-05-12
?
慕斯709654

TA贡献1840条经验 获得超5个赞

对于 Julia 代码,您在基准测试中包含编译时间。另一件需要注意的事情是您正在使用全局变量,众所周知这会降低性能。使用您的基准版本,我的机器上的执行时间是 17.7 秒。将所有内容移到一个函数中,我得到了 0.83 秒。从中删除编译时间使我降至 713.625 毫秒。我的代码的最终版本是这个(注意你在循环中计算了一个太多)。


using Random

using BenchmarkTools


function benchmark()

    nThrows = 0

    nSuccess = 0

    events = 100_000_000

    for j in 1:events

            x = rand()      #  Throw a dart

            y = rand()

            nThrows += 1

            if  x^2 + y^2 <= 1

                nSuccess += 1

            end

    end

    4.0*nSuccess/nThrows

end


pi = @btime benchmark()

println( "Pi = ",  pi)

请注意,进一步的改进是可能的。在循环之外分配一个随机数数组而不是每次迭代调用 rand 两次可能是有益的。您可以在此处找到其他性能提示:https ://docs.julialang.org/en/v1/manual/performance-tips/


查看完整回答
反对 回复 2022-05-12
  • 2 回答
  • 0 关注
  • 192 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号