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

Yuusha Membre non connecté
-
- Voir le profil du membre Yuusha
- Inscrit le : 04/07/2017
- Groupes :
-
Modérateur
-
Administrateur
-
Forgeron
Reprise du message précédent
Bonjour,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.

Yuusha Membre non connecté
-
- Voir le profil du membre Yuusha
- Inscrit le : 04/07/2017
- Groupes :
-
Modérateur
-
Administrateur
-
Forgeron
Code FORTRAN :
program nPremiers implicit none integer :: divisor,counter,i counter=1 do i=3,250000,2 divisor = 3 do if (divisor*divisor > i .OR. modulo(i,divisor)==0) then EXIT end if divisor = divisor+2 end do if (divisor*divisor > i) then counter=counter+1 end if end do print*, counter end program nPremiers
Le résultat :
Code BASH :
time ./fortranPrime 22044 real 0m0,015s user 0m0,015s sys 0m0,000s

Jybz Membre non connecté
-
- Voir le profil du membre Jybz
- Inscrit le : 10/10/2018
- Groupes :
-
Administrateur
-
Forgeron
Normalement avec l'optimisation, la variable dans la condition venant de l'argument devrait ne pas se faire re-vérifier, mais en cas de doute, tu peux la faire à l'extérieur du for.
Code C :
int n2=n>>1; for (int i=2; i<=n2; i++)
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 |

Jybz Membre non connecté
-
- Voir le profil du membre Jybz
- Inscrit le : 10/10/2018
- Groupes :
-
Administrateur
-
Forgeron
Code C :
if((n>2)&&(n&1)){for(...)...}
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 |

Yuusha Membre non connecté
-
- Voir le profil du membre Yuusha
- Inscrit le : 04/07/2017
- Groupes :
-
Modérateur
-
Administrateur
-
Forgeron
Jybz :
La division /2 peut dans certain cas être plus long qu'une rotation de bit à droite >>1
Normalement avec l'optimisation, la variable dans la condition venant de l'argument devrait ne pas se faire re-vérifier, mais en cas de doute, tu peux la faire à l'extérieur du for.
Normalement avec l'optimisation, la variable dans la condition venant de l'argument devrait ne pas se faire re-vérifier, mais en cas de doute, tu peux la faire à l'extérieur du for.
Code C :
int n2=n>>1; for (int i=2; i<=n2; i++)
Je ne maitrise pas du tout le principe des bits donc je ne l'utilise jamais même si je sais que c'est plus rapide.
Jybz :
Pour supprimer les paires :
Code C :
if((n>2)&&(n&1)){for(...)...}
Je pense qu'un for(i=...,...,i+2) comme dans le code en Fortran sera plus rapide que de rajouter une condition if.

Jybz Membre non connecté
-
- Voir le profil du membre Jybz
- Inscrit le : 10/10/2018
- Groupes :
-
Administrateur
-
Forgeron
Yuusha :
Je pense qu'un for(i=...,...,i+2) comme dans le code en Fortran sera plus rapide que de rajouter une condition if.
Jybz :
Pour supprimer les paires :
Code C :
if((n>2)&&(n&1)){for(...)...}
Je pense qu'un for(i=...,...,i+2) comme dans le code en Fortran sera plus rapide que de rajouter une condition if.
oui tu as tout à fais raison. Mais il faut compter 1 et 2 dans les nombres premiers.
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 |

Yuusha Membre non connecté
-
- Voir le profil du membre Yuusha
- Inscrit le : 04/07/2017
- Groupes :
-
Modérateur
-
Administrateur
-
Forgeron
Jybz :
oui tu as tout à fais raison. Mais il faut compter 1 et 2 dans les nombres premiers.
1 n'st pas premier par définition


Papoteur Membre non connecté
-
- Voir le profil du membre Papoteur
- Inscrit le : 03/10/2011
- Groupes :
-
Modérateur
-
Équipe Mageia
-
Administrateur
-
Forgeron
Code PYTHON :
def nbpremiers(n): counter = 1 for i in range(3, n, 2): divisor = 3 while (divisor * divisor < i) and i%divisor != 0 : divisor += 2 if divisor * divisor > i : counter += 1 return counter print("Nombre de premiers =", nbpremiers(250000))
Code TEXT :
time python3 premiers3.py Nombre de premiers = 22044 real 0m0,486s user 0m0,485s sys 0m0,001s
Avantage FORTRAN

C'est plus performant
Édité par Papoteur Le 09/01/2022 à 09h10
Yves

Papoteur Membre non connecté
-
- Voir le profil du membre Papoteur
- Inscrit le : 03/10/2011
- Groupes :
-
Modérateur
-
Équipe Mageia
-
Administrateur
-
Forgeron
L'algorithme qui est mis en œuvre dans le premier cas en Python est :
Philippe Moutou :
la méthode du crible d’Ératosthène, on peut supprimer d’une liste contenant les entiers entre 2 et n tous les multiples de 2, puis supprimer tous les multiples du nombre suivant 2, etc.
Yves

marc-andré Membre non connecté
-
- Voir le profil du membre marc-andré
- Inscrit le : 29/09/2015
- Groupes :
ça met un peu d'animation sur le forum, tout en montrant que l'informatique, c'est pas forcément des problèmes mais que ça peu être fun!
en C, j'aurai cru que le fait de supprimer l'appel de fonction aurait eu plus d'effet; ça améliore un peu, mais pas tant que ça;
en tout cas, ça bouscule les idées reçus sur l'efficacité du C;
on découvre que ça reste le fortran, sur ce genre de calcul, qui reste indétrônable;
on comprend mieux pourquoi les physiciens y sont tellement attaché;
j'ai essayé d'implémenter en racket, la version optimisée en fortran; comme ça il ne restera plus qu'à faire celle en C puisqu'on a celle en python de Papoteur pour avoir une vision d'ensemble, du même algo;
Code RACKET :
#lang racket (time (let ([compteur 1]) (for ([num (in-range 3 250001 2)]) (let ([diviseur 3]) (let boucle () (unless (or (> (* diviseur diviseur) num) (= 0 (remainder num diviseur))) (set! diviseur (+ diviseur 2)) (boucle))) (when (> (* diviseur diviseur) num) (set! compteur (+ compteur 1))))) compteur))
mais, c'est pas génial au niveau exécution, ça reste beaucoup plus lent que la version fonctionnelle du début en 1 seule ligne
j'ai fait plusieurs run, c'est entre 750 et 800 millisecondes;
mais, je ne fais pas appel à une librairie spéciale;
c'est mieux pour la cohérence de la comparaison.
mais je ne pense pas que la différence entre les deux vienne uniquement de cette librairie, du simple prédicat "prime?";
dans l'ensemble, c'est la méthode fonctionnelle qui s'avère être efficace en elle-même.
Édité par marc-andré Le 09/01/2022 à 15h03
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
Le plus rapide semble d'être d'inliner la fonction. En faisant ça, elle va être intégrée dans le main lors de la compilation.

marc-andré Membre non connecté
-
- Voir le profil du membre marc-andré
- Inscrit le : 29/09/2015
- Groupes :
Papoteur :
C'est plus performant que d'établir la liste des nombres premiers et de la dénombrer, mais la différence n'est pas si flagrante.
tu as corrigé, j'avais trouvé bizarre car tu avais un temps plus long avec cette méthode!
en fait, en racket c'est pareil, c'est beaucoup plus efficace de dénombrer la liste des nombres premiers que de les compter comme en fortran;
c'est assez contre intuitif mais c'est ainsi;
ce qui coûte, c'est les assignations et le fait de gérer des variables;
dans la version impérative en racket, on est obligé de gérer, le compteur, le diviseur et d'égrener chaque numéro;
cela donne chaque fois des "let" imbriqués;
et l'assignation c'est "set!" le ! pour indiquer un effet de bord, source de tous les problèmes en informatique
avec la méthode fonctionnelle, il n'y a pas tous ces problèmes, il n'y a pas de source de bug, c'est une seule ligne de code;
c'est le miracle des "continuations"; on ne sait pas ce qui se passe sous le chapeau, la liste produite par "filter" est simplement dénombrée par "length";
c'est pratique à écrire, mais ce qui est surprenant, c'est que ça soit aussi beaucoup plus efficace;
en résumé, sur mon ordi :
la méthode fonctionnelle
en typed/racket : entre 250 et 300 millisecondes;
la même en racket, environ 450 millisecondes;
on voit clairement l'overhead de 50% entre typed ou pas;
et la version impérative optimisée (soit disant) ci dessus, entre 750 et 800;
PS j'ai essayé de mettre le code dans "citation", c'est mieux je pense, mais on perd l'indentation et la coloration syntaxique, du coup, c'est pas très lisible;
j'ai toujours du mal avec ces machins;
c'est quoi le truc à utiliser pour coller du code sur ce service?
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 :
Jybz :
Utiiser [ code]...[ code] au lieu de [ quote][ /quote]
OK mais il n'y a pas une icône pour le faire?
poursuite de l'investigation;
mesure de l'impact du prédicat "prime?" dans la performance;
en fait Yuusha a raison, il est important;
ultime version en racket
Code RACKET :
#lang racket (require math/number-theory) (time (let ([compteur 1]) (for ([num (in-range 3 250001 2)]) (when (prime? num) (set! compteur (+ compteur 1)))) compteur))
et sur plusieurs run, ça se situe entre 300 milliseconde;
donc, la performance vient essentiellement de lui;
mais avoir des librairies efficaces, ça fait partie des critères pour estimer un langage;
ici c'est le cas
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 :
Jybz :
Utiiser [ code]...[ code] au lieu de [ quote][ /quote]
et en plus, ça marche pas!
c'est vraiment une peine ces machins qu'on sait jamais comment s'en servir
et c'est d'autant plus vicieux que j'avais fait une prévisualisation et que ça avait l'air d'être bon et au final rien!
en fait si ça marche, je ne comprends pas ce qui c'est passé
merci et excuses pour ce message
Édité par marc-andré Le 09/01/2022 à 14h36
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
marc-andré :
et en plus, ça marche pas!
c'est vraiment une peine ces machins qu'on sait jamais comment s'en servir
et c'est d'autant plus vicieux que j'avais fait une prévisualisation et que ça avait l'air d'être bon et au final rien!
Jybz :
Utiiser [ code]...[ code] au lieu de [ quote][ /quote]
et en plus, ça marche pas!
c'est vraiment une peine ces machins qu'on sait jamais comment s'en servir
et c'est d'autant plus vicieux que j'avais fait une prévisualisation et que ça avait l'air d'être bon et au final rien!
En fait, il n'y a aucune espace, je les ai rajouté pour ne pas être interpreté.
Oui il y a un bouton, il faut développé la barre-menu tout à droite.
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 |
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie