Mise à jour: Toutes mes excuses pour l'affichage d'un double de steveha's much earlier answer. Parle de volumes sur mes compétences en lecture. Toujours en laissant cette réponse en ligne pour l'instant, juste à cause de mes réflexions sur les effets d'E/S/Buffering/Runtime.
Original post:
Je ne peux pas croire qu'il faut Python plus d'appliquer une expression régulière, et de calculer une racine carrée, qu'il ne faut pour lire une ligne d'entrée et la sortie standard d'un résultat sur la norme sortie (ou toute E/S d'ailleurs).
Comme les E/S à un moment donné proviendront d'un disque dur et iront soit à un autre disque dur, soit à l'œil d'un utilisateur, cela devrait être le facteur limitant.
Les E/S sont généralement tamponnées pour l'accélération. Habituellement, un tampon est rempli en rafales, puis le processeur reste inactif en attendant que le périphérique fournisse plus de données.
Cela conduit à un générateur pour votre application.Ecrire un générateur qui lit l'entrée ligne par ligne et fournit immédiatement un numéro de carré à la demande. Je doute que ce sera plus lent que la vitesse globale d'E/S sur tout matériel moderne raisonnable. Si vous êtes sur un périphérique spécial (comme embedded, uController, Raspberry Pi, etc, faites-le nous savoir)
La seule optimisation que vous pouvez faire est de précompiler l'expression régulière. Comme vous utilisez la même expression rationnelle pour chaque test, faisons l'analyse de l'expression rationnelle une seule fois. Votre exemple dans la question est bon parce que vous faites un re.findall()
. Je suis en train d'élaborer pour d'autres lecteurs.
import sys, re, math
pattern = re.compile(r'\b\d+\b')
def fh_numbers_to_sqrt(fh):
for line in fh:
for i in re.findall(pattern, line):
yield math.sqrt(float(i))
numbers_g = fh_numbers_to_sqrt(sys.stdin)
for num in numbers_g:
print('%.4f' % num)
Cela permet à toutes les opérations mathématiques et expressions rationnelles d'être entrelacées avec les temps d'E/S.
Maintenant, la seule chose que nous ne pouvons pas vraiment optimiser et intégrer est le reverse
. L'algorithme doit attendre jusqu'au dernier élément pour pouvoir inverser.
On pourrait donc changer le code appelant à:
numbers_g = fh_numbers_to_sqrt(sys.stdin)
for num in reverse(list(numbers_g)):
print('%.4f' % num)
et nous espérons que c'est plus rapide ce que vous aviez à l'origine. Encore une fois, la seule raison pour laquelle cela devrait être plus rapide est parce que nous avons caché l'exécution de l'analyse et du calcul de l'expression rationnelle dans l'horloge murale nécessaire pour lire les données de l'entrée standard. Cela devrait toujours être limité aux E/S. En fait, il se peut que le reverse
ne soit pas réellement ajouté à l'exécution globale, car il peut simplement s'intercaler avec l'E/S qui se produit sur la sortie standard. En regardant une horloge murale, cet algorithme pourrait ne pas utiliser de temps du tout. :-)
Pour prouver ou annuler l'ensemble de mon article, vous pouvez mesurer avec time.time()
combien de temps il faut entre le début de votre script et juste avant la ligne Data = re.findall
, et à partir de là jusqu'à la fin. Si j'ai raison, la lecture des données prendra le plus de temps. Si ce n'est pas le cas, il est utile de mesurer également le temps requis pour toutes les recherches d'expressions régulières. Laissez nous savoir. Je suis curieux ...
Par «chiffres», voulez-vous dire nombres? Aussi, pourriez-vous nous montrer quelques exemples d'entrées/sorties? – Volatility
"mais pas assez vite" - Quelle est la taille du fichier sur lequel vous travaillez? À quelle vitesse est-ce? À quelle vitesse avez-vous besoin d'être? – mgilson
Combien d'entrées avez-vous? Avez-vous profilé pour trouver le (s) hotspot (s)? – nneonneo