Mandelbrot-Benchmark (C, PHP, HHVM, Ruby, Python, PyPy und Kinx)

Mandelbrot Benchmark

PyPy ist jetzt verfügbar, also habe ich es hinzugefügt. Wie ist das Ergebnis? !!

Einführung

Ich habe den Benchmark in diesem Artikel gelesen. [PHP8] JIT kann mit PHP verwendet werden.

Ich vergleiche Mandelbrot mit JIT in PHP8, aber! Dies ist die, die unser Kinx auch mit der "nativen" Methode unterstützen kann! Es ist eine Veranstaltung mit dem Ziel, einen Benchmark aus dem Gefühl von auszuprobieren.

Einen Artikel zu machen bedeutet auch, dass es ein ** Spiel ** war. Oder eher als erwartet. Du hast es geschafft!

Was ist übrigens Kinx? Bitte beachten Sie Folgendes.

Voraussetzungen

Inhalt der Benchmark

Verschiedene Benchmark-Programme werden hier veröffentlicht (https://gist.github.com/dstogov/12323ad13d3240aee8f1)](https://gist.github.com/dstogov/12323ad13d3240aee8f1), aber sie basieren darauf.

Da die Umgebung unterschiedlich ist, wird nicht das gleiche Ergebnis erzielt, sodass wir alle in mehreren Sprachen messen. Die Versionen der verschiedenen Sprachen konnten nicht genau auf den Originalartikel abgestimmt werden, aber ich werde es genauer messen und mit dem Originalartikel vergleichen.

Wie im Originalartikel erwähnt, wird jedoch nur PHP ** betrogen **. Obwohl dies praktisch vermieden wird, beeinträchtigt die E / A-Leistung auch die Messung, sodass ich den Ausgabeteil grob löschen werde. (Fortsetzung des Paradoxons) C geht jedoch ohne Optimierung, da es ohne die Ausgabe überoptimiert zu sein scheint und kein Benchmark ist. Eine Art Handicap. Immer noch schnell.

Über die Messzeit

Nach dem Start der Ausführung wird die Ausführungszeit mit dem in jeder Sprache vorbereiteten Timer gemessen. Daher habe ich festgestellt, dass die Zeit zum Parsen und Kompilieren der Quelle nicht enthalten ist. C kann nicht geholfen werden.

Was mich unwohl gefühlt hat, ist, dass ** HHVM als langsam empfunden wird, aber die endgültige Ausgabe schnell ist **. Insbesondere ist das Ergebnis, dass HHVM wahrnehmungsmäßig langsamer als PHP ist, die Zahlen jedoch besser als PHP sind.

Informationen zur Ausgabe

Es wurde bestätigt, dass die folgenden Formulare alle ausgegeben werden, wenn die Ausgabe ausgeführt wird. Mein Kinx (native) hat auch wie erwartet funktioniert.

                                       *
                                       *
                                       *
                                       *
                                       *
                                      ***
                                     *****
                                     *****
                                      ***
                                       *
                                   *********
                                 *************
                                ***************
                             *********************
                             *********************
                              *******************
                              *******************
                              *******************
                              *******************
                            ***********************
                              *******************
                              *******************
                             *********************
                              *******************
                              *******************
                               *****************
                                ***************
                                 *************
                                   *********
                                       *
                                ***************
                            ***********************
                         * ************************* *
                         *****************************
                      * ******************************* *
                       *********************************
                      ***********************************
                    ***************************************
               *** ***************************************** ***
               *************************************************
                ***********************************************
                 *********************************************
                 *********************************************
                ***********************************************
                ***********************************************
              ***************************************************
               *************************************************
               *************************************************
              ***************************************************
              ***************************************************
         *    ***************************************************    *
       *****  ***************************************************  *****
       ****** *************************************************** ******
      ******* *************************************************** *******
    ***********************************************************************
    ********* *************************************************** *********
       ****** *************************************************** ******
       *****  ***************************************************  *****
              ***************************************************
              ***************************************************
              ***************************************************
              ***************************************************
               *************************************************
               *************************************************
              ***************************************************
                ***********************************************
                ***********************************************
                  *******************************************
                   *****************************************
                 *********************************************
                **** ****************** ****************** ****
                 ***  ****************   ****************  ***
                  *    **************     **************    *
                         ***********       ***********
                         **  *****           *****  **
                          *   *                 *   *

Benchmark

Nun zum Hauptthema der Benchmark. Zuerst aus dem Programmcode.

C

Die Version von gcc.

$ gcc --version
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

C sieht so aus.

mandelbrot.c


#include <stdio.h>
#include <sys/time.h>

#define BAILOUT 16
#define MAX_ITERATIONS 1000

int mandelbrot(double x, double y)
{
        double cr = y - 0.5;
        double ci = x;
        double zi = 0.0;
        double zr = 0.0;
        int i = 0;

        while(1) {
                i ++;
                double temp = zr * zi;
                double zr2 = zr * zr;
                double zi2 = zi * zi;
                zr = zr2 - zi2 + cr;
                zi = temp + temp + ci;
                if (zi2 + zr2 > BAILOUT)
                        return i;
                if (i > MAX_ITERATIONS)
                        return 0;
        }

}

int main (int argc, const char * argv[]) {
        struct timeval aTv;
        gettimeofday(&aTv, NULL);
        long init_time = aTv.tv_sec;
        long init_usec = aTv.tv_usec;

        int x,y;
        for (y = -39; y < 39; y++) {
                //printf("\n");
                for (x = -39; x < 39; x++) {
                        volatile int i = mandelbrot(x/40.0, y/40.0);
                        //if (i==0)
                        //      printf("*");
                        //else
                        //      printf(" ");
                }
        }
        //printf ("\n");

        gettimeofday(&aTv,NULL);
        double query_time = (aTv.tv_sec - init_time) + (double)(aTv.tv_usec - init_usec)/1000000.0;
        printf ("C Elapsed %0.3f\n", query_time);
    return 0;
}

PHP/HHVM

PHP-Version.

$ php --version
PHP 7.2.24-0ubuntu0.18.04.6 (cli) (built: May 26 2020 13:09:11) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.24-0ubuntu0.18.04.6, Copyright (c) 1999-2018, by Zend Technologies

HHVM-Version.

$ hhvm --version
HipHop VM 3.21.0 (rel)
Compiler: 3.21.0+dfsg-2ubuntu2
Repo schema: ebd0a4633a34187463466c1d3bd327c131251849

PHP und HHVM sind der gleiche Quellcode.

mandelbrot.php


<?php
define("BAILOUT",16);
define("MAX_ITERATIONS",1000);

class Mandelbrot
{
    function Mandelbrot()
    {
        $d1 = microtime(1);
        for ($y = -39; $y < 39; $y++) {
            for ($x = -39; $x < 39; $x++) {
                $this->iterate($x/40.0,$y/40.0);
            }
        }
        $d2 = microtime(1);
        $diff = $d2 - $d1;
        printf("PHP Elapsed %0.3f\n", $diff);
    }

    function iterate($x,$y)
    {
        $cr = $y-0.5;
        $ci = $x;
        $zr = 0.0;
        $zi = 0.0;
        $i = 0;
        while (true) {
            $i++;
            $temp = $zr * $zi;
            $zr2 = $zr * $zr;
            $zi2 = $zi * $zi;
            $zr = $zr2 - $zi2 + $cr;
            $zi = $temp + $temp + $ci;
            if ($zi2 + $zr2 > BAILOUT)
                return $i;
            if ($i > MAX_ITERATIONS)
                return 0;
        }

    }


}

$m = new Mandelbrot();
?>

Ruby

Ruby-Version.

$ ruby --version
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]

Ruby-Quellcode.

mandelbrot.rb


BAILOUT = 16
MAX_ITERATIONS = 1000

class Mandelbrot

        def initialize
                #puts "Rendering"
                for y in -39...39 do
                        #puts
                        for x in -39...39 do
                                i = iterate(x/40.0,y/40.0)
                                #if (i == 0)
                                #       print "*"
                                #else
                                #       print " "
                                #end
                        end
                end
        end

        def iterate(x,y)
                cr = y-0.5
                ci = x
                zi = 0.0
                zr = 0.0
                i = 0

                while(1)
                        i += 1
                        temp = zr * zi
                        zr2 = zr * zr
                        zi2 = zi * zi
                        zr = zr2 - zi2 + cr
                        zi = temp + temp + ci
                        return i if (zi2 + zr2 > BAILOUT)
                        return 0 if (i > MAX_ITERATIONS)
                end

        end

end

time = Time.now
Mandelbrot.new
#puts
puts "Ruby Elapsed %f" % (Time.now - time)

Python/PyPy

Python-Version.

$ python --version
Python 2.7.15+

Version von PyPy.

$ pypy --version
Python 2.7.13 (5.10.0+dfsg-3build2, Feb 06 2018, 18:37:50)
[PyPy 5.10.0 with GCC 7.3.0]

Python-Quellcode. PyPy ist das gleiche.

mandelbrot.py


import sys, time
stdout = sys.stdout

BAILOUT = 16
MAX_ITERATIONS = 1000

class Iterator:
  def __init__(self):
    #print 'Rendering...'
    for y in range(-39, 39):
      #stdout.write('\n')
      for x in range(-39, 39):
        i = self.mandelbrot(x/40.0, y/40.0)

        #if i == 0:
          #stdout.write('*')
        #else:
          #stdout.write(' ')

  def mandelbrot(self, x, y):
    cr = y - 0.5
    ci = x
    zi = 0.0
    zr = 0.0
    i = 0

    while True:
      i += 1
      temp = zr * zi
      zr2 = zr * zr
      zi2 = zi * zi
      zr = zr2 - zi2 + cr
      zi = temp + temp + ci

      if zi2 + zr2 > BAILOUT:
        return i
      if i > MAX_ITERATIONS:
        return 0

t = time.time()
Iterator()
print 'Python Elapsed %.02f' % (time.time() - t)

Kinx/Kinx(native)

Kinx-Version.

$ kinx -v
kinx version 0.9.2

In der Version 0.9.2 gab es jedoch einen Fehler, dass Konstantenkonstanten in nativ nicht korrekt weitergegeben wurden, sodass ich eine teilweise feste Version verwendete ... Das Commit ist abgeschlossen.

Quellcode der regulären Kinx-Version.

mandelbrot.kx


const BAILOUT = 16;
const MAX_ITERATIONS = 1000;

function mandelbrot(x, y) {
    var cr = y - 0.5;
    var ci = x;
    var zi = 0.0;
    var zr = 0.0;
    var i = 0;

    while (true) {
        i++;
        var temp = zr * zi;
        var zr2 = zr * zr;
        var zi2 = zi * zi;
        zr = zr2 - zi2 + cr;
        zi = temp + temp + ci;
        if (zi2 + zr2 > BAILOUT)
            return i;
        if (i > MAX_ITERATIONS)
            return 0;
    }
}


var tmr = new SystemTimer();
var x,y;
for (y = -39; y < 39; y++) {
    #System.print("\n");
    for (x = -39; x < 39; x++) {
        var i = mandelbrot(x/40.0, y/40.0);
        #if (i==0)
        #    System.print("*");
        #else
        #    System.print(" ");
    }
}
#System.print("\n");
System.print("Kinx Elapsed %0.3f\n" % tmr.elapsed());

Kinx (nativer) Quellcode. Wenn Sie den Typ aus dem Berechnungsergebnis kennen, müssen Sie ihn nicht schreiben, sondern können dem Argument einfach : dbl hinzufügen.

mandelbrotn.kx


const BAILOUT = 16;
const MAX_ITERATIONS = 1000;

native mandelbrot(x:dbl, y:dbl) {
    var cr = y - 0.5;
    var ci = x;
    var zi = 0.0;
    var zr = 0.0;
    var i = 0;

    while (true) {
        i++;
        var temp = zr * zi;
        var zr2 = zr * zr;
        var zi2 = zi * zi;
        zr = zr2 - zi2 + cr;
        zi = temp + temp + ci;
        if (zi2 + zr2 > BAILOUT)
            return i;
        if (i > MAX_ITERATIONS)
            return 0;
    }
}


var tmr = new SystemTimer();
var x,y;
for (y = -39; y < 39; y++) {
    #System.print("\n");
    for (x = -39; x < 39; x++) {
        var i = mandelbrot(x/40.0, y/40.0);
        #if (i==0)
        #    System.print("*");
        #else
        #    System.print(" ");
    }
}
#System.print("\n");
System.print("Kinx(native) Elapsed %0.3f\n" % tmr.elapsed());

Ergebnis

Das Ergebnis wird angezeigt. Der Durchschnitt von 10 mal. In der Reihenfolge der Geschwindigkeit neu anordnen.

Es tut mir leid, es gab ein Problem mit dem Messprogramm und ich habe erneut gemessen.

Sprache Ausführung Messzeit(Sekunden,10 mal durchschnittlich) time(real),10 mal durchschnittlich
C 7.4.0 0.018 0.046
PyPy 5.10.0 0.020 0.122
Kinx(native) 0.9.2 0.048 0.107
HHVM 3.21.0 0.068 0.552
PHP 7.2.24 0.182 0.241
Ruby 2.5.1 0.365 0.492
Kinx 0.9.2 0.393 0.457
Python 2.7.15 0.564 0.601

Hurra! ** Erfahrung langsamer als PHP ** Schneller als HHVM. Außerdem bin ich einfach glücklich, weil die reguläre Version ** so schnell war wie die Ruby-VM, die ich für schnell hielt **.

Oder besser gesagt, ** PyPy ist ungewöhnlich schnell **. Ich fühlte einen Unterschied. Toll.

Die wahrgenommene Langsamkeit von HHVM ist ebenfalls in der Tabelle gezeigt. Die Kompilierungszeit ist wahrscheinlich lang. Dies ist aufgrund der Sprachspezifikationen unvermeidlich. Kinx (native) sieht auch eine Strafe für die Kompilierungszeit.

Vergleichen wir es nun mit dem Ergebnis von Originalartikel. In diesem Benchmark wird die Ausgabe ebenfalls unterdrückt, es gibt jedoch einen großen Unterschied in der Umgebung. Ich fand die rationalen Trends ähnlich ... aber nur HHVM ist seltsam. Es sollte standardmäßig JIT aktiviert sein, vergleichen Sie es also mit JIT on. Im Gegenteil, das Ergebnis der JIT-Off-Version des Originalartikels ist zu langsam und ich bin mir nicht sicher, was richtig ist. Andere sind in der Regel umweltfreundlich ** etwa doppelt so schnell wie jetzt.

Sprache Ausführung Messzeit(Sekunden,10 mal durchschnittlich) Ergebnis des Originalartikels Originalartikelversion
C 7.4.0 0.018 0.022 4.9.2
PyPy 5.10.0 0.020
Kinx(native) 0.9.2 0.048
HHVM 3.21.0 0.068 0.030 3.5.0
PHP 7.2.24 0.182 0.281 7
Ruby 2.5.1 0.365 0.684 2.1.5
Kinx 0.9.2 0.393
Python 2.7.15 0.564 1.128 2.7.8

abschließend

Bänken macht Spaß, wenn es ein Spiel ist. Native ist schwer zu bekommen, aber dies ist eines der Merkmale (Individualität) von Kinx, deshalb möchte ich mich gut darum kümmern. Geben wir unser Bestes.

Bis zum nächsten Mal.


P.S. Dies ist übrigens das Skript, das für die Messung verwendet wird. Ich habe versucht, den kürzlich implementierten Prozess zu verwenden. Die obigen Zahlen sind die Zahlen, die anstelle von "Durchschnitt" erscheinen.

mandbench.kx


using Process;

var count = 10;
var command = [$$[1], $$[2]];
var r = [];
var re = /[0-9]+\.[0-9]+/;

for (var i = 0; i < count; ++i) {
    var result = "";
    var [r1, w1] = new Pipe();
    var p1 = new Process(command, { out: w1 }).run();
    w1.close();
    while (p1.isAlive() || r1.peek() > 0) {
        var buf = r1.read();
        if (buf.length() < 0) {
            System.println("Error...");
            return 1;
        } else if (buf.length() > 0) {
            result += buf;
        } else {
            // System.println("no input...");
        }
    }

    re.reset(result);
    if (re.find()) {
        r.push(Double.parseDouble(re.group[0].string));
    }
}
var total = r.reduce(&(r, e) => r + e);
System.println("total  : %8.3f" % total);
System.println("count  : %8d" % r.length());
System.println("average: %8.3f" % (total / r.length()));

Recommended Posts

Mandelbrot-Benchmark (C, PHP, HHVM, Ruby, Python, PyPy und Kinx)
Ruby, Python und Map
Python und Ruby teilen sich
C-Sprache, Java, Python-Benchmarks mit Primfaktorisierung
[Ruby vs Python] Benchmark-Vergleich zwischen Rails und Flask
Lösen mit Ruby und Python AtCoder ARC 059 C Minimum-Quadrat-Methode
Python auf Ruby und wütend Ruby auf Python
Java VS PHP VS Python VS Ruby
Python und Ruby Slice Memo
Über Perl, Python, PHP, Ruby
Ruby- und Python-Syntax ~ branch ~
Lösen mit Ruby und Python AtCoder ABC011 C Dynamische Planungsmethode
Lösen mit Ruby und Python AtCoder ARC067 C Primfaktorisierung
Lösen mit Ruby, Perl, Java und Python AtCoder ABC 065 C-te Potenz
Mehrstufige Auswahl (Go / C # / Ruby / Python)
Scraping mit Node, Ruby und Python
Dynamischer Proxy mit Python, Ruby, PHP
Rufen Sie popcount von Ruby / Python / C # auf
Lösen mit Ruby und Python AtCoder ABC057 C Zerlegung des Primfaktors Bit vollständige Suche
Lösen mit Ruby, Perl, Java und Python AtCoder ARC 098 C Kumulative Summe
Lösen mit Ruby, Perl, Java und Python AtCoder CADDi 2018 C Primfaktorisierung
Lösen mit Ruby und Python AtCoder Tenka1 Programmer Contest C Kumulative Summe
Lösen mit Ruby und Python AtCoder ABC172 C Kumulative Summen-Dichotomie
Lösen mit Ruby, Perl, Java und Python AtCoder ABC 047 C Regulärer Ausdruck
Vergleich der Deserialisierungsleistung von msgpack (C ++ / Python / Ruby)
Vermeiden Sie verschachtelte Schleifen in PHP und Python
Unterschiede zwischen Ruby und Python im Umfang
Verwirklichen Sie den PHP / Python-Generator mit Golang / Ruby
PHP / Python / Ruby-Beispiel für die Pfad-API
Implementieren Sie den FIR-Filter in Python und C.
Unterschiede in der Beziehung zwischen PHP und Python schließlich und beenden
Schreiben Sie die O_SYNC-Datei in C und Python
[Grundlegende Grammatik] Unterschiede zwischen Ruby / Python / PHP
Mit Ruby (Rails) verschlüsseln und mit Python entschlüsseln
Socket-Kommunikation in C-Sprache und Python
Einfaches Web-Scraping mit Python und Ruby
Unterschied zwischen Ruby und Python (grundlegende Syntax)
RaspberryPi L Chika mit Python und C #
Kommunikation verschlüsselter Daten zwischen Python und C #
Unterschiede in der Zeichenfolgenverarbeitung zwischen Python, Ruby, JS und PHP (Kombination und Variablenerweiterung)
Lösen mit Ruby, Perl, Java und Python AtCoder ARC 086 C Hash-Sortierung
Lösen mit Ruby und Python AtCoder CODE FESTIVAL 2016 qual C B Priority Queue
Lösen mit Ruby, Perl, Java und Python AtCoder ARC 066 C Iterativer Square Hash