démarrons l'année par un coup de racket
des benchmarks étonnants
Logiciels / Programmation

marc-andré Membre non connecté
-
- Voir le profil du membre marc-andré
- Inscrit le : 29/09/2015
- Groupes :
il y a quelques mois déjà que je suis devenu monomaniaque avec racket et voici une occasion d'en parler.
en effet, il y a quelques temps, j'ai regardé cette vidéo qui compare python, C et assembleur;
https://www.youtube.com/watch?v=3PcIJKd1PKU&lc=UgyaYKMVHCPz5WxkXNl4AaABAg.9Vs5GdfA40M9WibGRPsuGq
dans un des commentaires posant la question sur rust et haskell, j'avais posé la même question concernant racket;
entretemps, il y a eu un commentaire me proposant une version en common lisp;
du coup, ce matin, je me suis senti obligé de faire une version en racket (scheme);
le problème est de calculer le quantité de nombres premiers dans l'intervalle 1 250001;
cela donne cela
Code RACKET :
#lang racket (require math/number-theory) (time (length (filter prime? (range 1 250001))))
simplement dans DrRacket, soit une ligne de code seulement une fois que l'on a localisé où se trouve le prédicat "prime?" et qu'on a fait le "require"
tous le reste, time, length, filter et range sont built-in dans #lang racket.
comparé aux autres implémentation c'est l'élégance même;
ça fonctionne comme les "pipe" dans le "bash" mais au lieu d'être des strings qui circulent du stdout vers stdin, ce sont des séquences dans le code.
c'est la raison pour laquelle je suis devenu fan de ce langage.
mais chose très surprenante, c'est le résultat obtenu dans le REPL quand je fais RUN de cette ligne de code
cpu time: 458 real time: 457 gc time: 186
22044
les temps sont en millisecondes;
ce qui voudrait dire que racket est 10 fois plus rapide que le C ou l'assembleur?
où alors, c'est leur mesure, dans la vidéo qui sont bidons.
je n'ai pas pris la peine de tester cher moi en C ou en python, mais j'aimerais votre avis sur la question.
récemment, un benchmark plus sérieux donnait ceci:
https://benchmarksgame-team.pages.debian.net/benchmarksgame/box-plot-summary-charts.html
racket y est toujours meilleur que python, mais moins bien que common lisp sbcl et encore moins bien que C.
Édité par marc-andré Le 09/01/2022 à 14h52
HP ProDesk ;
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia

Papoteur Membre non connecté
-
- Voir le profil du membre Papoteur
- Inscrit le : 03/10/2011
- Groupes :
-
Modérateur
-
Équipe Mageia
-
Administrateur
-
Forgeron
Si les temps en C sont plus longs, c'est que l'algorithme utilisé n'est pas bon.
Je l'ai fait en Python
Code BASH :
time python3 premiers.py Nombre de premiers = 22044 real 0m0,307s user 0m0,297s sys 0m0,010s
Il serait meilleur que ton programme en racket

Après, c'est sur un i7.
Yves

marc-andré Membre non connecté
-
- Voir le profil du membre marc-andré
- Inscrit le : 29/09/2015
- Groupes :
Papoteur :
Bonjour,
Si les temps en C sont plus longs, c'est que l'algorithme utilisé n'est pas bon.
Je l'ai fait en Python
Il serait meilleur que ton programme en racket
Après, c'est sur un i7.
Si les temps en C sont plus longs, c'est que l'algorithme utilisé n'est pas bon.
Je l'ai fait en Python
Code BASH :
time python3 premiers.py Nombre de premiers = 22044 real 0m0,307s user 0m0,297s sys 0m0,010s
Il serait meilleur que ton programme en racket

Après, c'est sur un i7.
super
moi, c'est toujours sur mon vieux acer de 2008
tu as regardé la vidéo?
que penses tu de leur implémentation en python, qui met 54 s !?
je pense que cette vidéo est bidon.
et ton programme en python, tu utilises une librairie particulière ou c'est du standard?
Édité par marc-andré Le 05/01/2022 à 20h35
HP ProDesk ;
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia

Yuusha Membre non connecté
-
- Voir le profil du membre Yuusha
- Inscrit le : 04/07/2017
- Groupes :
-
Modérateur
-
Administrateur
-
Forgeron
C'est le temps de programmation pas d'exécution.
Edit : Autant pour moi je n'avais pas vu la fin de la vidéo. En effet c'est étrange.
Édité par Yuusha Le 05/01/2022 à 20h40

Papoteur Membre non connecté
-
- Voir le profil du membre Papoteur
- Inscrit le : 03/10/2011
- Groupes :
-
Modérateur
-
Équipe Mageia
-
Administrateur
-
Forgeron
Le programme que j'ai utilisé inclut l'utilisation d'un import, mais qui est dans les bibliothèques standards. Il est là pour la fonction racine carrée.
Code PYTHON :
from math import *
Yves

marc-andré Membre non connecté
-
- Voir le profil du membre marc-andré
- Inscrit le : 29/09/2015
- Groupes :
Papoteur :
Je crois que le but de la vidéo est de montrer sur un exemple concret des différences entre le résultat pour les différents langages et le coût en développement. Là, l'algorithme n'est pas optimisé, mais c'est le même pour tous les langages.
Le programme que j'ai utilisé inclut l'utilisation d'un import, mais qui est dans les bibliothèques standards. Il est là pour la fonction racine carrée.
Le programme que j'ai utilisé inclut l'utilisation d'un import, mais qui est dans les bibliothèques standards. Il est là pour la fonction racine carrée.
Code PYTHON :
from math import *
salut
bon tu crois à la sincérité de cette vidéo donc.
mais alors, ton résultat, ce n'est pas avec le même style de code écrit dans la vidéo?
moi aussi à la première vision, ça a l'air bien soigné, le sujet intéressant sans plus y réfléchir.
et j'avais oublié cette vidéo
puis, c'est un commentaire qui me proposait une version en common lisp qui m'a fait réagir l'autre jour.
je la reproduit ici :
Code SBCL :
(defun prime-p (n) (let ((boundary (the fixnum (floor n 2)))) (declare (type fixnum n) (type fixnum boundary)) (loop :for i :from 2 :upto boundary :do (when (eq 0 (the fixnum (mod n i))) (return-from prime-p NIL)))) n) (defun main () (let ((num-primes 0)) (declare (type fixnum num-primes)) (loop :for i :from 2 :upto 250001 :when (prime-p i) :do (incf num-primes)) num-primes)) (time (main)) Evaluation took: 10.972 seconds of real time 10.971406 seconds of total run time (10.970791 user, 0.000615 system) 99.99% CPU 19,749,521,754 processor cycles 0 bytes consed 22044
bon, je ne pratique pas le common lisp mais ça m'a l'air être du code valide, et qui reproduit l'algorithme de la vidéo;
et le résultat paraît cohérent avec ceux de la vidéo : 2 fois plus lent qu'en C mais 5 fois plus rapide que python;
c'est juste quand j'ai essayé en racket et le résultat que j'ai obtenu qui m'a étonné : plus rapide qu'en assembleur?
mais il est vrai que c'est pas le même style de programmation;
normalement, en common lisp, on doit pouvoir aussi l'écrire comme en racket et ça doit être plus rapide;
en common lisp si on brasse du code et des datas (pour rien) à la mode impérative, c'est forcément coûteux;
donc en fait, c'est pas tellement le langage qui fait la rapidité, mais le style de programmation;
précisions :
la librairie math/number-theory requise pour le prédicat "prime?" est en fait en typed/racket;
ils disent que l'utiliser dans racket rajoute un overhead;
du coup, ce matin, j'ai essayé tout simplement de changer #lang racket par #lang typed/racket pour voir la différence;
j'ai fait plusieurs run :
le meilleur est a 271 millisecondes et le pire à 299;
donc, avec mon vieux bousin, je fais mieux en typed/racket que ton i7 en python! tralala!
Édité par marc-andré Le 09/01/2022 à 14h59
HP ProDesk ;
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia

marc-andré Membre non connecté
-
- Voir le profil du membre marc-andré
- Inscrit le : 29/09/2015
- Groupes :
pour en avoir le cœur net, autant tester ce code en C chez moi;
j'ai exactement recopié leur code et exécuté sur ma machine;
c'est édifiant ... de lenteur
gcc YT_test.c -o YT_test
[marc@ficus5 bid]$ time ./YT_test
22044
real 0m9,940s
user0m9,937s
sys 0m0,001s
donc leur mesure sont OK, ils ont une machine deux fois plus rapide que la mienne;
mais alors, c'est vraiment un scoop que la programmation fonctionnelle en racket, c'est non seulement élégant, mais en plus, ça tourne 10 fois plus vite qu'en C, même sur ma vieille machine.
HP ProDesk ;
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia

marc-andré Membre non connecté
-
- Voir le profil du membre marc-andré
- Inscrit le : 29/09/2015
- Groupes :
PRIME-P
*
MAIN
*
Evaluation took:
39.707 seconds of real time
39.706059 seconds of total run time (39.703029 user, 0.003030 system)
100.00% CPU
95,297,351,301 processor cycles
0 bytes consed
22044
donc, sur la même machine, la mienne, le même genre de code est 4 fois plus lent en common lisp qu'en C
A+
HP ProDesk ;
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia

Yuusha Membre non connecté
-
- Voir le profil du membre Yuusha
- Inscrit le : 04/07/2017
- Groupes :
-
Modérateur
-
Administrateur
-
Forgeron
marc-andré :
mais alors, c'est vraiment un scoop que la programmation fonctionnelle en racket, c'est non seulement élégant, mais en plus, ça tourne 10 fois plus vite qu'en C, même sur ma vieille machine.
Ça ce n'est pas normal. Soit c'est mal codé, soit c'est mal compilé. Déjà ils n'utilisent pas -O3 à la compilation donc on est forcément plus lent que l'assembleur. Pour faire des maths, à part le Fortran (parce que gfortran est légèrement meilleur que gcc), tu ne devrais rien à voir de plus rapide (excepté l'assembleur bien sûr).

marc-andré Membre non connecté
-
- Voir le profil du membre marc-andré
- Inscrit le : 29/09/2015
- Groupes :
Yuusha :
Ça ce n'est pas normal. Soit c'est mal codé, soit c'est mal compilé. Déjà ils n'utilisent pas -O3 à la compilation donc on est forcément plus lent que l'assembleur. Pour faire des maths, à part le Fortran (parce que gfortran est légèrement meilleur que gcc), tu ne devrais rien à voir de plus rapide (excepté l'assembleur bien sûr).
marc-andré :
mais alors, c'est vraiment un scoop que la programmation fonctionnelle en racket, c'est non seulement élégant, mais en plus, ça tourne 10 fois plus vite qu'en C, même sur ma vieille machine.
Ça ce n'est pas normal. Soit c'est mal codé, soit c'est mal compilé. Déjà ils n'utilisent pas -O3 à la compilation donc on est forcément plus lent que l'assembleur. Pour faire des maths, à part le Fortran (parce que gfortran est légèrement meilleur que gcc), tu ne devrais rien à voir de plus rapide (excepté l'assembleur bien sûr).
Salut
oui, je suis moi même étonné des résultats obtenus.
ce simple test soulève des questions;
Papoteur pourrait nous répondre, car, en python, il obtient aussi un temps beaucoup plus court qu'en C avec le code de la vidéo;
donc, il y a aussi un truc en python;
mais tu peux toujours tester sur ta machine
la version en C que j'ai testé chez moi:
[marc@ficus5 bid]$ cat YT_test.c
Code C :
#include <stdio.h> int IsPrime (int n) { for (int i = 2; i <= n / 2; i++) if (! (n % i)) return 0; return 1; } void main () { int numPrimes = 0; for (int i = 2; i < 250001; i++) numPrimes += IsPrime(i); printf("%d\n", numPrimes); }
ça t'évitera de la retaper si tu veux tester;
pour la version en common lisp elle marche telle que dans sbcl en terminal;
il est dans les dépôts de mageia;
et pour tester la version en racket, c'est pareil, il suffit d'installer DrRacket qui est dans les dépôts et tester mes trois lignes de code et voir le résultat;
maintenant, il y a un challenge:
comment bien écrire ce test en C de sorte qu'il soit plus rapide que 300 ms?
Édité par marc-andré Le 09/01/2022 à 15h01
HP ProDesk ;
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia

Jybz Membre non connecté
-
- Voir le profil du membre Jybz
- Inscrit le : 10/10/2018
- Groupes :
-
Administrateur
-
Forgeron
Code C :
int IsPrime (int n) { for (int i = 2; i <= (n>>1); i++){ if (n % i){ return 1; } } return 0; } int main (void) { int counter; for (int i = 2; i < 250001; i++){ counter+=IsPrime(i); } return counter; }
En appelant le programme dans la console puis en tapant :
Code BASH :
echo ${?}
Téléverser une image : /wiki/hebergement-de-fichiers-sur-mlo
Arch | Machine | OS |
x86_64 | lenovo x250 | mga9 |
armv7hl | bananapro | mga9 |
aarch64 | Raspberry Pi 4B | mga9 |

marc-andré Membre non connecté
-
- Voir le profil du membre marc-andré
- Inscrit le : 29/09/2015
- Groupes :
Jybz :
La marge dans l'optimisation "code" est faible, peut-être faudrait-il revoir l'algorithme.
Code C :
#include <stdio.h> int IsPrime (int n) { for (int i = 2; i <= (n>>1); i++){ if (n % i){ return 1; } } return 0; } void main (void) { for (int i = 2; i < 250001; i++){ printf("%dn", IsPrime(i)); } }
salut!
et ça donne quoi comme temps d'exécution?
Édité par marc-andré Le 08/01/2022 à 11h11
HP ProDesk ;
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia

Jybz Membre non connecté
-
- Voir le profil du membre Jybz
- Inscrit le : 10/10/2018
- Groupes :
-
Administrateur
-
Forgeron
Téléverser une image : /wiki/hebergement-de-fichiers-sur-mlo
Arch | Machine | OS |
x86_64 | lenovo x250 | mga9 |
armv7hl | bananapro | mga9 |
aarch64 | Raspberry Pi 4B | mga9 |

marc-andré Membre non connecté
-
- Voir le profil du membre marc-andré
- Inscrit le : 29/09/2015
- Groupes :
il marche à l'envers, il va sortir avec 1 dès qu'un test est true donc dès que ce n'est pas divisible;
c'est le contraire qu'on veut :
sortir avec 0 dès qu'il y a un diviseur!
HP ProDesk ;
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia
Mageia8 Gnome
Liberté et sécurité sont les arguments classiques pour LINUX. En prime il y a aussi la dignité et la confiance ressentie depuis que je suis sous Mageia

Yuusha Membre non connecté
-
- Voir le profil du membre Yuusha
- Inscrit le : 04/07/2017
- Groupes :
-
Modérateur
-
Administrateur
-
Forgeron
J'ai commencé à l'écrire en C et je pense qu'en utilisant des fonctions en racket et pas en C, tu triches un peu. En effet, on ne fait aucun postulat dans le code C. Or on sait qu'un nombre pair ne peut être premier vu qu'il est divisible par 2.
Voilà le code C réécrit correctement :
Code C :
#include <stdio.h> int main (int argc, char *argv[]) { int counter = 0; int breaker = 0; for (int i=2; i<250001; i++) { breaker = 0; for (int j=2; j<=i/2; j++) { if (!(i % j)) { breaker = 1; break; } } if (breaker==0) { counter++; } } printf("%d\n",counter); return 0; }
J'ai supprimé l'appel à la fonction. Deux if sont plus rapides que les appels surtout lorsqu'il y a 250000 appels.
Nouvelle idée. Deuxième version, plus rapide, j'ai inliné la fonction :
Code C :
#include <stdio.h> inline int IsPrime (int n) { for (int i=2; i<=n/2; i++) { if (!(n % i)) { return 0; } } return 1; } int main (int argc, char *argv[]) { int numPrimes=0; for (int i = 2; i < 250001; i++) { numPrimes+=IsPrime(i); } printf("%d\n", numPrimes); return 0; }
Voici la comparaison de ma seconde version avec différentes optimisations :
- -O0 : real 0m3,860s
user 0m3,860s
sys 0m0,000s - -O1 : real 0m2,995s
user 0m2,995s
sys 0m0,000s - -O2 : real 0m3,012s
user 0m3,012s
sys 0m0,000s - -O3 real 0m3,023s
user 0m3,023s
sys 0m0,000s
Il semble ici que le -O1 soit suffisant. Mais optimisé le code n'est pas négligeable.
Si tu souhaites faire une comparaison correcte, tu dois écrire l'algorithme toi-même pas utiliser une fonction déjà implémentée et optimisée en racket.
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie