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

Référence de Mandelbrot

--Cible ... C, PHP, HHVM, Ruby, Python, PyPy et notre Kinx

PyPy est maintenant disponible, alors je l'ai ajouté. Quel est le résultat? !!

introduction

J'ai lu le benchmark dans cet article [PHP8] JIT peut être utilisé avec PHP.

Je compare Mandelbrot avec JIT en PHP8, mais! , C'est celui que notre Kinx peut également bouger avec la méthode native! C'est un événement dans le but d'essayer une référence à partir du sentiment de.

Faire un article signifie aussi que c'était un ** jeu **. Ou plutôt que prévu. Tu l'as fait!

Au fait, qu'est-ce que Kinx? Veuillez vous référer à ce qui suit.

Conditions préalables

Contenu du benchmark

Divers programmes de référence sont publiés ici (https://gist.github.com/dstogov/12323ad13d3240aee8f1)](https://gist.github.com/dstogov/12323ad13d3240aee8f1), mais ils sont basés sur cela.

Comme l'environnement est différent, le même résultat ne sera pas obtenu, nous allons donc tout mesurer dans plusieurs langues. Les versions des différentes langues ne peuvent pas correspondre exactement à l'article original, mais je vais le mesurer de plus près et le comparer avec l'article original.

Cependant, comme mentionné dans l 'article original, seul PHP est ** triché **. Tout en évitant cela, en pratique, les performances d'E / S interfèrent également avec la mesure, je vais donc supprimer grossièrement la partie de sortie. Cependant (continuant le paradoxe), C passe sans optimisation car sans la sortie, il semble être sur-optimisé et pas un benchmark. Une sorte de handicap. Toujours rapide.

À propos du temps de mesure

Après le début de l'exécution, le temps d'exécution est mesuré à l'aide du temporisateur préparé dans chaque langue. Donc, j'ai remarqué que cela n'inclut pas le temps d'analyser et de compiler la source. C ne peut pas être aidé.

Ce qui m'a mis mal à l'aise, c'est que ** HHVM est perçu comme lent, mais la sortie finale est rapide **. Plus précisément, le résultat est que HHVM est perceptivement plus lent que PHP, mais les chiffres sont meilleurs que PHP.

À propos de la sortie

Il a été confirmé que les formulaires suivants sont tous émis lors de la sortie. Mon Kinx (natif) a également fonctionné comme prévu.

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

référence

Maintenant, le sujet principal du benchmark. D'abord à partir du code du programme.

C

La version de 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 ressemble à ceci.

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

Version PHP.

$ 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

Version HHVM.

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

PHP et HHVM sont le même code source.

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

Version rubis.

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

Code source Ruby.

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

Version Python.

$ python --version
Python 2.7.15+

Version de 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]

Code source Python. PyPy est le même.

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)

Version Kinx.

$ kinx -v
kinx version 0.9.2

Cependant, il y avait un bogue dans la version 0.9.2 qui faisait que les constantes const n'étaient pas propagées correctement en natif, donc j'en ai utilisé une partiellement corrigée ... Le commit est terminé.

Code source de la version régulière de Kinx.

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

Code source Kinx (natif). Si vous connaissez le type à partir du résultat du calcul, vous n'avez pas besoin de l'écrire, vous pouvez donc simplement ajouter : dbl à l'argument.

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

résultat

Le résultat s'affiche. La moyenne de 10 fois. Réorganiser par ordre de vitesse.

Je suis désolé, il y a eu un problème avec le programme de mesure et j'ai mesuré à nouveau.

Langue version Temps de mesure(Secondes,10 fois la moyenne) time(real),10 fois la moyenne
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

Hourra! ** Expérience plus lente que PHP ** Plus rapide que HHVM. De plus, je suis tout simplement content parce que la version régulière était ** aussi rapide que la VM Ruby que je pensais rapide **.

Ou plutôt, ** PyPy est exceptionnellement rapide **. J'ai senti une différence. Génial.

La lenteur perçue de HHVM est également indiquée dans le tableau. Le temps de compilation est probablement long. C'est inévitable en raison des spécifications linguistiques. Kinx (natif) voit également une pénalité pour le temps de compilation.

Maintenant, comparons-le avec le résultat de Article original. Dans ce benchmark, la sortie est également supprimée, mais il y a une grande différence dans l'environnement. Je pensais que les tendances rationnelles étaient similaires ... mais seul HHVM est étrange. Il devrait être JIT activé par défaut, alors comparez-le avec JIT activé. Au contraire, le résultat de la version JIT off de l'article original est trop lent et je ne suis pas sûr de ce qui est correct. D'autres sont généralement environ deux fois plus rapides sur le plan environnemental ** qu'aujourd'hui.

Langue version Temps de mesure(Secondes,10 fois la moyenne) Résultat de l'article original Version originale de l'article
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

en conclusion

Le banc est amusant, quand c'est un jeu. «Native» est difficile à trouver, mais c'est l'une des caractéristiques (individualité) de Kinx, donc je veux en prendre bien soin. Faisons de notre mieux.

À la prochaine.


P.S. Au fait, c'est le script utilisé pour la mesure. J'ai essayé d'utiliser le [Process] récemment implémenté (https://qiita.com/Kray-G/items/e44c39ddb2e17659a0a4). Les nombres ci-dessus sont les nombres qui apparaissent dans «moyenne».

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 et Kinx)
Ruby, Python et carte
Python et Ruby se séparent
Benchmarks langage C, Java, Python avec factorisation prime
[Ruby vs Python] Comparaison de référence entre Rails et Flask
Résolution avec Ruby et Python AtCoder ARC 059 C Méthode du carré minimum
Python sur Ruby et Ruby en colère sur Python
Java VS PHP VS Python VS Ruby
Mémo tranche python et rubis
À propos de Perl, Python, PHP, Ruby
Syntaxe Ruby et Python ~ branch ~
Résolution avec Ruby et Python AtCoder ABC011 C Méthode de planification dynamique
Résolution avec Ruby et Python AtCoder ARC067 C factorisation premier
Résolution avec Ruby, Perl, Java et Python AtCoder ABC 065 C-th power
Sélection en plusieurs étapes (Go / C # / Ruby / Python)
Scraping avec Node, Ruby et Python
Proxy dynamique avec python, ruby, PHP
Appeler popcount depuis Ruby / Python / C #
Résolution avec Ruby et Python AtCoder ABC057 C Décomposition du facteur premier Recherche complète de bits
Résolution avec Ruby, Perl, Java et Python AtCoder ARC 098 C Somme cumulative
Résolution avec Ruby, Perl, Java et Python AtCoder CADDi 2018 C factorisation premier
Résolution avec Ruby et Python AtCoder Tenka1 Programmer Contest C Somme cumulative
Résolution avec Ruby et Python AtCoder ABC172 C Dichotomie de somme cumulée
Résolution avec Ruby, Perl, Java et Python AtCoder ABC 047 C Expression régulière
Comparaison des performances de désérialisation de msgpack (C ++ / Python / Ruby)
Évitez les boucles imbriquées en PHP et Python
Différences entre Ruby et Python dans la portée
Réaliser un générateur PHP / Python avec Golang / Ruby
Exemple PHP / Python / Ruby frappant l'API Path
Implémenter le filtre FIR en langage Python et C
Différences dans la relation entre PHP et Python enfin et quitter
Ecrire le fichier O_SYNC en C et Python
[Grammaire de base] Différences entre Ruby / Python / PHP
Crypter avec Ruby (Rails) et décrypter avec Python
Communication socket par langage C et Python
Scraping Web facile avec Python et Ruby
Différence entre Ruby et Python (syntaxe de base)
RaspberryPi L Chika avec Python et C #
Communication de données chiffrées entre Python et C #
Différences dans le traitement des chaînes entre Python, Ruby, JS et PHP (combinaison et expansion de variables)
Résolution avec Ruby, Perl, Java et Python AtCoder ARC 086 C Hash Sorting
Résolution avec Ruby et Python AtCoder CODE FESTIVAL 2016 qual C B Priority Queue
Résolution avec Ruby, Perl, Java et Python AtCoder ARC 066 C Hash carré itératif