[Monte-Carlo-Methode](https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%B3%E3%83%86%E3%82%AB%E3%83%AB%E3% 83% AD% E6% B3% 95) Der Geschwindigkeitsvergleich jeder Sprache wird durchgeführt, indem das Umfangsverhältnis in jeder Sprache unter Verwendung der Monte-Carlo-Methode berechnet wird. Die Monte-Carlo-Methode besteht darin, einen beliebigen Punkt (Zufallszahl) bei 1,0> = x> = 0, 1,0> = y> = 0 abzulegen, und der abgelegte Punkt fällt innerhalb des Kreises vom Ursprung (0,0). Das Verhältnis zwischen dem Ding und dem Ding, das außerhalb des Kreises gefallen ist, wird berechnet, und dieses Verhältnis wird zum Umfangsverhältnis. Obwohl es nahe an dem durch Berechnung erhaltenen Umfangsverhältnis liegt, gibt es natürlich keinen genauen Wert, aber ich denke, es ist sinnvoll, es in einer Programmiersprache zu implementieren. Der Grund ist -Die Geschwindigkeit der Gleitkommaberechnung kann verglichen werden. ・ Die Schleifengeschwindigkeit kann verglichen werden.
Unten jede Sprachquelle perl
Da Perl ein sehr schnelles Image hatte, das ich bisher ausprobiert hatte, habe ich es als Benchmark (≒ Standard) vorbereitet. Da die Quelle einfach ist, sollte sie aufgrund der Objektorientierung mit hoher Geschwindigkeit ohne Overhead arbeiten.
montecarlo.pl
use Time::HiRes qw( gettimeofday tv_interval);
local $ave = 0;
local $time_start, $time_end, $time_split = 0;
local $max_times = 10000000;
local $test_times = 100;
local $cnt = 0;
for ( $i = 1 ; $i <= $test_times ; $i++ ) {
print($i."\n");
$time_start = [gettimeofday];
$cnt = 0;
for ( $j = 0 ; $j < $max_times ; $j++) {
$x = rand();
$y = rand();
if ( $x * $x + $y * $y <= 1) {
$cnt++;
}
}
$time_split = tv_interval($time_start);
print("pi ".(4 * $cnt / $max_times)."\n");
print("split:".$time_split."\n");
$ave += $time_split;
}
print("AVE:".($ave / $test_times)."\n");
~ ~
Vorerst habe ich es vorbereitet, weil "C schnell ist, nicht wahr?" Es kann schneller sein, wenn Sie es fest einstellen, Ich habe versucht, es auf dieser Ebene zu unterdrücken, weil die Codierung einfach ist.
montecarlo.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
float montecarlo();
void main() {
float ave = 0;
int times = 100;
for (int i = 1 ; i <= times ; i++){
printf("%03d\n", i );
ave += montecarlo();
}
printf("AVE %f\n\n", ave / times);
}
float montecarlo() {
clock_t time_start, time_end;
double time_split;
int times = 10000000;
float x, y;
time_start = clock();
int cnt = 0;
for ( int i = 0; i < times ; i++) {
x = (float)rand() / (float)RAND_MAX;
y = (float)rand() / (float)RAND_MAX;
if ( (x * x + y * y) <= 1) {
cnt++;
}
}
time_end = clock();
time_split = (double)(time_end - time_start) / 1000000;
printf("%f\n", 4.0 * cnt / times);
printf("time_split : %lf\n", time_split);
return(time_split);
}
Da go vorher einen guten Ruf hatte, habe ich es als Benchmark vorbereitet, der sich von Perl unterscheidet. Wie dünn kann es in C-Sprache sein, da es sich um eine Kompilierungssprache handelt? Das interessiert mich auch.
montecarlo.go
package main
import (
"fmt"
"time"
"math/rand"
)
var i, j, cnt int
var x, y float64
var time_start, time_end int64
var ave, time_split float64
const MAX_TIMES = 10000000
const TEST_TIMES = 100
func main() {
//fmt.Printf("%03d\n", 10)
//fmt.Printf("%d\n", time.Now())
//fmt.Printf("%f\n", float64(time.Now().UnixNano()) / 1000000000.0)
//fmt.Printf("%f\n", float64(time.Now().UnixNano()) / 1000000000.0)
//fmt.Printf("%f\n", float64(time.Now().UnixNano()) / 1000000000.0)
rand.Seed(time.Now().UnixNano())
ave := 0.0
for i := 1 ; i <= TEST_TIMES ; i++ {
fmt.Printf("%03d times\n", i)
time_start := time.Now().UnixNano()
cnt := 0
for j := 0 ; j < MAX_TIMES ; j++ {
x := rand.Float64()
y := rand.Float64()
if x * x + y * y <= 1 {
cnt++
}
}
fmt.Printf("pi : %f\n", 4 * float64(cnt) / float64(MAX_TIMES))
time_end := time.Now().UnixNano()
time_split := float64(time_end - time_start) / 1000000000
fmt.Printf("time : %f\n", time_split)
ave += time_split
//ave := time_split
}
fmt.Printf("AVE : %f\n", ave / TEST_TIMES)
}
Java
Als Zusammenstellungssprache denke ich, dass es derzeit als Eisenplatte positioniert ist. (Obwohl es Meinungen für jeden geben kann ...) Es wird erwartet, dass es aufgrund der dazwischenliegenden VM langsamer als die C-Sprache ist, aber in der Vergangenheit scheint es nicht tödlich langsam zu sein.
montecarlo.java
import java.util.Random;
import java.util.*;
class Montecarlo {
public static void main(String[] args) {
//System.out.println( getNowTime() );
//Geben Sie den Radius des Kreises an
double iR = 1.0;
//Geben Sie die Anzahl der Ziehungen an
int MAX_POINT = 10000000;
//Geben Sie die Anzahl der Tests an
int TEST_TIMES = 100;
//Zufällige Objektdefinition
Random rand = new Random();
//Start- und Endzeiten
long time_start, time_end = 0;
double time_split;
double ave = 0.0;
//Definition der Sicherungsvariablen für den Zufallswert
double ranValue = 0.0;
double POS_X = 0.0;
double POS_Y = 0.0;
for ( int j = 1 ; j <= TEST_TIMES ; j ++) {
//System.out.println("%03d", j);
System.out.printf("%03d\n", j);
//Startzeit
time_start = System.nanoTime();
//System.out.println( "start : " + time_start );
//Zählen Sie die Anzahl der Fälle, die in einen Bogen gefallen sind
int HIT_COUNT = 0;
//Initialisierung von Arbeitsvariablen für die Ausgabe
for ( int i = 0 ; i < MAX_POINT ; i++ ) {
POS_X = rand.nextDouble();
POS_Y = rand.nextDouble();
if ( iR >= POS_X * POS_X + POS_Y * POS_Y ) {
HIT_COUNT++;
}
}
// System.out.println(HIT_COUNT );
System.out.println( ( 4 * HIT_COUNT / (double)MAX_POINT ) );
//Endzeit
time_end = System.nanoTime();
//System.out.println( "end : " + time_end );
time_split = (double)(time_end - time_start) / 1000000000.0;
//System.out.println( "split : " + (time_end - time_start) );
System.out.println( "split : " + time_split );
ave += time_split;
}
//System.out.println( getNowTime() );
System.out.println( "AVE : " + ave / TEST_TIMES );
}
///Aktuelle Zeit JJJJ/mm/dd hh:mm:ss(jpn)Holen Sie sich in Format
public static String getNowTime() {
return(String.format("%1$tF %1$tT" ,Calendar.getInstance()));
}
}
lua Es hat den Ruf, leicht als Skriptsprache zu sein, also habe ich es hinzugefügt. Als Sprachspezifikation ist es ein Image, das schnell ist, weil es Anweisungen verwendet, die dem Betriebssystem nahe kommen.
montecarlo.lua
local socket = require("socket")
math.randomseed(os.time())
MAX_LOOP = 10000000
TEST_TIMES = 100
ave = 0.0
for i = 1, TEST_TIMES do
print(string.format("%03d times", i))
time_start = socket.gettime()
cnt = 0
for j = 1 , MAX_LOOP do
x = math.random()
y = math.random()
if x * x + y * y <= 1 then
cnt = cnt + 1
end
end
time_end = socket.gettime()
time_split = time_end - time_start
print(string.format("pi : %f", 4 * cnt / MAX_LOOP))
print(string.format("split : %f", time_split))
ave = ave + time_split
end
print(string.format("ave : %f", ave / TEST_TIMES))
python Unnötig zu sagen, es ist Python. Dieses Mal werden wir mit der 2. und 3. Serie sowie mit Pypy vergleichen.
montecarlo.py
import random
import time
import math
_times = 10000000
def pi():
_time_start = time.time()
_cnt = 0
for i in range(_times):
_x = random.random()
_y = random.random()
#if _x ** 2 + _y **2 <= 1:
if _x * _x + _y * _y <= 1:
_cnt += 1
print( 4.0 * _cnt / _times )
_time_end = time.time()
_time_split = _time_end - _time_start
print(_time_split)
return _time_split
_test = 100
_ave = 0.0
for _i in range(_test):
print('{:03d} times'.format(_i+1))
_ave += pi()
print('ave: {} s'.format(_ave/_test))
Rust Rust ist eine Sprache, die in der KI und beim maschinellen Lernen Aufmerksamkeit erregt. Es ist eine Sprache, die schneller als Python und einfacher zu entwickeln ist als C.
Cargo.toml
[package]
name = "montecarlo"
version = "0.1.0"
authors = ["ubuntu"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.6"
floating-duration="0.1.2"
src/main.rs
fn main() {
use rand::Rng; //Für Zufallszahlen
use std::time::Instant; //Zur Zeiterfassung
use floating_duration::TimeAsFloat; //Zur Umstellung von Zeit auf Float
println!("Hello, world!");
let loop_max = 10000000; //Anzahl der Treffer
let test_max = 100; //Schleife, um den Durchschnitt zu erhalten
let mut x: f32;
let mut y: f32;
let mut rng = rand::thread_rng();//Randseed-Einstellungen
let mut split_time: f32 = 0.0;
//for _test_count in 1..test_max {
for _test_count in 1..=test_max {
println!("times:{:?}", _test_count );
let start_time = Instant::now();
let mut count = 0;
//for _loot_count in 1..loop_max {
for _loot_count in 1..=loop_max {
x = rng.gen_range(0., 1.); //Zufallszahl 0.0~1.0
y = rng.gen_range(0., 1.);
if x * x + y * y <= 1.0 {
count = count + 1;
}
}
println!("pi:{}", 4.0 * count as f32 / loop_max as f32); //als f32 ist ein Typ gegossen
let end_time = start_time.elapsed().as_fractional_secs();//Zeit in Sekunden umrechnen
println!("time:{:?}", end_time );
split_time = split_time + end_time as f32;
}
println!("AVE:{}", split_time / test_max as f32);
}
Xoroshiro-Versionsquelle bereitgestellt von @ tatsuya6502
Cargo.toml
[package]
name = "montecarlo"
version = "0.1.0"
authors = ["ubuntu"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.7"
rand_xoshiro = "0.4"
src/main.rs
//Für Zufallszahlen
use rand::Rng;
use rand_xoshiro::{rand_core::SeedableRng, Xoroshiro128Plus};
//Zur Zeiterfassung
use std::time::{Instant, SystemTime};
const LOOP_MAX: usize = 10_000_000; //Anzahl der Treffer
const TEST_MAX: usize = 100; //Schleife, um den Durchschnitt zu erhalten
fn main() -> Result<(), Box<dyn std::error::Error>> {
//Setze zufälligen Samen
let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?;
let mut rng = Xoroshiro128Plus::seed_from_u64(now.as_millis() as u64);
let mut split_time: f32 = 0.0;
for _test_count in 1..=TEST_MAX {
println!("times:{}", _test_count);
let start_time = Instant::now();
let mut count = 0;
for _loot_count in 0..LOOP_MAX {
//Zufallszahlen generieren[0.0, 1.0)・ ・ 0.0 oder mehr 1.Weniger als 0
let x: f32 = rng.gen_range(0.0, 1.0);
let y: f32 = rng.gen_range(0.0, 1.0);
if x * x + y * y <= 1.0 {
count += 1;
}
}
println!("pi:{}", 4.0 * count as f32 / LOOP_MAX as f32); //als f32 ist ein Typ gegossen
let end_time = start_time.elapsed().as_secs_f32(); //Zeit in Sekunden umrechnen
println!("time:{}", end_time);
split_time += end_time as f32;
}
println!("AVE:{}", split_time / TEST_MAX as f32);
Ok(())
}
Nim Zum Vergleich ...
montecarlo.nim
import random
import times
randomize()
const TEST_MAX = 10000000
const LOOP_MAX = 100
var x, y = 0.0
var ave = 0.0
for loop in 1..LOOP_MAX:
echo $loop & " times"
var time_start = cpuTime()
var count = 0
for test in 1..TEST_MAX:
x = rand(0.0..1.0)
y = rand(0.0..1.0)
# echo $x
# echo $y
if ( x * x + y * y <= 1):
count += 1
echo "pi:" & repr(float(4.0 * float(count) / float(TEST_MAX)))
var time_split = cpuTime() - time_start
echo "split" & repr(time_split)
ave += time_split
echo "AVE:" & repr(ave / float(LOOP_MAX))
~
Ruby Ich habe Ruby hinzugefügt, weil @scivola die Quelle bereitgestellt hat.
montecarlo.rb
TIMES = 10000000
def pi
time_start = Time.now
cnt = 0
TIMES.times do
x = rand
y = rand
if x * x + y * y <= 1
cnt += 1
end
end
puts 4.0 * cnt / TIMES
time_end = Time.now
time_split = time_end - time_start
puts time_split
time_split
end
test = 100
ave = 0.0
test.times do |i|
puts "%03d times" % (i + 1)
ave += pi
end
puts "ave: #{ ave / test } s"
perl 5.30
AVE:8.93247789s
java 14.0.1
AVE: 1.4161036380199996s
c
gcc 9.3.0
gcc montecarlo.c -o pi
keine gcc-optimierung
AVE:1.501472s
Optimierung der Ausführungsgeschwindigkeit von gcc-O3
AVE:1.425400s
python 2.7.18
AVE:14.216013s
pypy 7.3.1 with GCC 9.3.0
ave: 0.983056025505
python 3.8.2
AVE:12.485190s
pypy3 7.3.1 with GCC 9.3.0
ave: 1.1475282835960388 s
go 1.13.8
AVE:2.132493
lua 5.3
AVE:6.715329
rust (cargo 1.44.0)
cargo run --release
AVE 0.507196783
cargo run
AVE 16.449156
Nim 1.0.6
nim c -r montecarlo.nim
AVE 7.2063023393
nim c -r -d:release montecarlo.nim
AVE:0.3236947073200001
Rubin hinzugefügt.
Ruby 2.7.0dev (2019-12-25 master e1e1d92277) [aarch64-linux]
ave: 7.5495061204099985 s
Die Python-Quelle wurde behoben.
if _x ** 2 + _y **2 <= 1: ①
↓
if _x * _x + _y * _y <= 1: ②
※python 3.8.Messung von 2
① Wiedererfassung
ave: 11.132939925193787 s
②
ave: 9.153075976371765 s
* Messung von Pypy3
① Wiedererfassung
ave: 1.0760090994834899 s
②
ave: 1.3655683732032775 s
Das?
Eine Rostschleife wurde behoben.
for _test_count in 1..test_max {
for _loot_count in 1..loop_max { ①
↓
for _test_count in 1..=test_max {
for _loot_count in 1..=loop_max { ②
cargo run --Messung freigeben
① Wiedererfassung
AVE:0.5022585
②
AVE:0.51400733
Mit Rost@Wir haben die Quelle der Xoroshiro-Version gemessen, die von tatsuya6502 bereitgestellt wird.
AVE:0.21163946
Auf dieser Ebene wurde ~~ Nim ~~ Rost als der schnellste bewertet. In Bezug auf die Geschwindigkeit
~~ Nim> rost> pypy> C = java> pypy3> go> lua> rubin> perl> python2 serie> python3 serie ~~ Rost (Xoroshiro-Version)> Nim> Rost> Pypy> C = Java> = Pypy3> go> lua> rubin> perl> python2-Serie> python3-Serie
ist geworden. Es ist richtig kompilierte Sprache> Skriptsprache. Natürlich kann meine Codierung schlecht sein und "auf diese Weise wird es schneller". Es ist jedoch unwahrscheinlich, dass sich die Rangfolge signifikant ändert, selbst wenn ein gewisser Einfallsreichtum verwendet wird, um die Rangfolge um einen Schritt zu ändern.
Besonders hervorzuheben ist Python, und durch die Verwendung von pypy wurde bestätigt (möglich), dass es mit einer Geschwindigkeit nahe der C-Sprache funktioniert (natürlich funktioniert die Quelle, wie sie ist, möglicherweise nicht mit pypy, und die Bibliothek wird pypy. Es wird möglicherweise nicht unterstützt. Ich denke jedoch, dass es einen Versuch wert ist, wenn Sie es mit der flexiblen Beschreibung von Python beschleunigen können.
Hinzugefügt am 28. Juni 2020 Der Rubin ist schneller als ich erwartet hatte und ich kann meine Überraschung nicht verbergen. Als ich es vorher versuchte, war es ungefähr c: ruby = 1: 20, also habe ich es auch dieses Mal erwartet, aber ich wurde brillant verraten. Wenn ich @scivola keinen Vorschlag machen würde, würde ich ihn ignorieren. Vielen Dank.
Das mysteriöse Ergebnis dieses Quellfixes ist, dass Python beim Starten mit Python3 schneller ist, beim Starten mit Pypy3 jedoch langsamer. (Bitte um Kommentare von Experten) Übrigens habe ich in der Quelle dieses Artikels kommentiert, um den Unterschied zu zeigen, aber da ich ihn in der tatsächlichen Messquelle ersetzt habe, hat sich die Bewertung des Kommentars nicht verlangsamt. (Ich denke, es gab so etwas im alten Basic ...)
Der Unterschied zwischen Rost und dem Pseudozufallszahlengenerator ist offensichtlich. Laut der von @ tatsuya6502 bereitgestellten Xoroshiro-Versionsquelle wurde festgestellt, dass sich der Pseudozufallszahlengenerator ebenfalls an der richtigen Stelle befindet. Vielen Dank für den Hinweis.
Dieser Artikel wird gelegentlich aktualisiert. Wenn es eine Sprache gibt, die gut aussieht, werde ich sie hinzufügen.
Recommended Posts