Pourquoi mon calcul est-il tellement plus rapide en C # que Python
Ci-dessous est un simple morceau de processus codés dans C#
et Python
respectivement (pour ceux d'entre vous curieux de connaître le processus, c'est la solution pour le Problème N ° 5 de Projet Euler).
Ma question est, le C#
code ci-dessous ne prend que 9 secondes pour effectuer une itération, tandis que l'achèvement de Python
code 283 secondes (pour être exact, 283 secondes sur Python 3.4.3 - 64 bits et 329 secondes sur Python 2.7.9 - 32 bits).
Jusqu'à présent, j'ai codé des processus similaires à la fois dans C#
et Python
et le temps d'exécution des différences ont été comparables. Cette fois, cependant, il y a une extrême différence entre le temps écoulé.
Je pense, une partie de cette différence surviennent à partir de la liste type de variable du langage python (je soupçonne, python convertit une partie des variables en double), mais ce qui est encore difficile à expliquer.
Ce que je fais mal?
Mon système: Windows 7 64 bits,
C# VS Express 2012 (9 secondes)
Python 3.4.3 64 bits (283 secondes)
Python 2.7.9 32 bits (329 secondes)
c-sharp code:
using System;
namespace bug_vcs {
class Program {
public static void Main(string[] args) {
DateTime t0 = DateTime.Now;
int maxNumber = 20;
bool found = false;
long start = maxNumber;
while (!found) {
found = true;
int i = 2;
while ((i < maxNumber + 1) && found) {
if (start % i != 0) {
found = false;
}
i++;
}
start++;
}
Console.WriteLine("{0:d}", start - 1);
Console.WriteLine("time elapsed = {0:f} sec.", (DateTime.Now - t0).Seconds);
Console.ReadLine();
}
}
}
et le code python:
from datetime import datetime
t0 = datetime.now()
max_number = 20
found = False
start = max_number
while not found:
found = True
i = 2
while ((i < max_number + 1) and found):
if (start % i) != 0:
found = False
i += 1
start += 1
print("number {0:d}\n".format(start - 1))
print("time elapsed = {0:f} sec.\n".format((datetime.now() - t0).seconds))
source d'informationauteur ssd
Vous devez vous connecter pour publier un commentaire.
TL;DR: Longue haleine post c'est moi en essayant de défendre Python (mon choix de la langue) à l'encontre de C#. Dans cet exemple, le C# est plus performante, mais prend toujours plus de lignes de code pour faire la même quantité de travail, mais la performance finale avantage est que C# est ~5x plus rapide qu'une approche similaire en Python quand codé correctement. Le résultat final est que vous devez utiliser la langue qui vous convient.
Quand je lance l'exemple en C#, il a fallu environ 3 secondes sur ma machine, et m'a donné un résultat de 232,792,560. Il pourrait être optimisé en utilisant le fait bien connu que vous ne pouvez avoir qu'un nombre divisible par les nombres de 1 à 20 si le nombre est un multiple de 20, et, par conséquent, vous n'avez pas besoin d'incrémenter de 1, mais au lieu de 20. Que seul l'optimisation faite le code à exécuter ~10x plus rapide que dans une simple 353 millisecondes.
Quand je lance l'exemple Python, j'ai renoncé à attendre et essayé d'écrire ma propre version à l'aide de itertools, qui n'a pas eu beaucoup plus de succès, et a été prise à peu près aussi long que votre exemple. Puis, je suis tombé sur une version acceptable de itertools, si je prends en compte le fait que seuls les multiples de mes plus grand nombre pourrait être divisible par tous les nombres du plus petit au plus grand. En tant que tel, le raffiné Python(3.6) le code est ici avec un décorateur fonction de synchronisation qui imprime le nombre de secondes qu'il a fallu pour exécuter:
Cela m'a aussi rappelé une question j'ai récemment eu à répondre sur CodeFights pour le plus petit Commun Multiple en utilisant le Plus grand Commun Dénominateur de la fonction en Python. Ce code est comme suit:
Comme dans la plupart des tâches de programmation, parfois, l'approche la plus simple n'est pas toujours le plus rapide. Malheureusement, il m'est resté hors de la tentative en Python cette fois. Cela dit, la beauté en Python, c'est la simplicité de l'obtention d'une performance de l'exécution, où il a pris 10 lignes de C#, j'ai été en mesure de retourner la réponse correcte en (potentiellement) une ligne d'expression lambda, et 300 fois plus rapide que mon optimisation simples sur C#. Je ne suis pas spécialiste en C#, mais la mise en œuvre de la même approche, voici le code que j'ai utilisé et de son résultat (environ 5x plus rapide que Python):
Pour la plupart des tâches de niveau supérieur, cependant, j'ai l'habitude de voir Python faisant exceptionnellement bien en comparaison à un .NET mise en œuvre, bien que je ne peut pas justifier les revendications en ce moment, à part de dire le Python Demandes de la bibliothèque m'a donné autant qu'un double à triple retour de performance par rapport à un C# WebRequest écrit de la même manière. C'était également le cas lors de l'écriture de Sélénium processus, comme j'ai pu lire des éléments de texte en Python en 100 millisecondes ou moins, mais chaque élément de récupération a pris C# >1 seconde pour revenir. Cela dit, je préfère le C# de la mise en œuvre en raison de son approche orientée-objet, où Python Sélénium mise en œuvre va fonctionnel, ce qui devient très difficile à lire parfois.
Essayer python JIT Implémentations comme pypy et numba ou cython si vous voulez vite que C, mais sacrifier un peu de lisibilité du code.
e.g dans pypy
e.g en cython
Cython Source:
Python (et tous les langages de script, y compris matlab) n'est pas destiné à être directedly utilisé à grande échelle de calcul numérique. Pour avoir un compatible résultat respecté les programmes, éviter les boucles à tout prix, et de convertir de la formule de matrice de formats (qui a besoin d'un peu de mathématique, de la compréhension et des compétences), de sorte que nous pouvons de pousser autant que possible à l'arrière-plan de la bibliothèque C fournis par numpy, scipy, etc.
De nouveau, NE PAS écrire des boucles de calcul numérique en pythonchaque fois qu'une matrice équivalente possible!