Question

Je construis un modèle en Python (3.3.1) pour un contrat assez simple mais délicat avec des flux de trésorerie à long terme.Le modèle complet est assez complexe en termes de temps consommé et j'ai donc décidé d'essayer de le profiler.Cependant, j'obtiens des réponses différentes avec et sans profilage.

J'ai réduit le code à l'exemple suivant :

def generate_cashflows( income ):
    contingent_expense = [1000.0]
    income_cf = [income]
    outgo_cf = [ -0.001 * contingent_expense[0] ]
    bank = [ income_cf[0] + outgo_cf[0] ]

    for t in range(1, 20):
        contingent_expense.append(1000.0)
        income_cf.append( income )
        outgo_cf.append( -contingent_expense[t] * 0.001 )
        bank.append(    bank[t-1] * (1+0.05)**(1/12)
                + income_cf[t]
                + outgo_cf[t]
                )
    return bank[-1]

print(str(generate_cashflows(0)))

Sortir:

calum@calum:~/pricing/model$ ./scratch.py 
-20.793337746348953
calum@calum:~/pricing/model$ python -m cProfile scratch.py
-20.0
     80 function calls in 0.000 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.000    0.000 scratch.py:5(<module>)
    1    0.000    0.000    0.000    0.000 scratch.py:5(generate_cashflows)
   76    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    1    0.000    0.000    0.000    0.000 {range}


calum@calum:~/pricing/model$ 

Existe-t-il une explication simple pour laquelle cela génère une réponse différente à chaque fois ?J'ai lu le manuel mais je n'y vois rien d'évident.

Était-ce utile?

La solution

Tout d'abord, j'ai essayé de reproduire avec python3, et j'ai exécuté "python3 scratch.py" et "python3 -m cProfile scratch.py" tous deux impriment -20.7933...sur ma machine.

La raison pour laquelle -20.0 est renvoyé sur python 2.x est que l'opérateur de division "/" fonctionnait différemment dans python2.x (http://legacy.python.org/dev/peps/pep-0238/)

En python2, 1/12 == 0

En python3, 1/12 == 0,08333333....

Cela signifie qu'en python2 la ligne

 bank.append(    bank[t-1] * (1+0.05)**(1/12)

simplifie à

 bank.append(    bank[t-1] * (1+0.05)**(0)

ou

 bank.append(    bank[t-1] * 1

Ce n'est probablement pas ce que vous vouliez.L'interprétation python3 est probablement correcte et l'interprétation python2 est assez inutile.En remarque, changer (1/12) en (1.0/12) entraîne une sortie identique sur python2 et python3, et fera en sorte que votre code renvoie la même sortie avec ou sans profilage, mais cela traite le symptôme et non la cause. .

Ma meilleure hypothèse quant à la raison pour laquelle vous obtenez les différentes sorties avec et sans profilage est que vous utilisez python3 sans profilage et python2 avec profilage.Utiliser la même version de Python lorsque vous exécutez votre code avec et sans profilage est essentiel pour obtenir des résultats significatifs.

Le fait que vous utilisiez ./scratch.py ​​indique que vous avez probablement une ligne comme

#!/usr/bin/python3

en haut de scratch.py ​​(bien qu'il ne soit pas inclus dans le code fourni).Quand tu cours

./scratch.py

/usr/bin/python3 est utilisé pour exécuter le fichier

Quand tu cours

python -m cProfile scratch.py

votre interpréteur python par défaut est utilisé pour exécuter le fichier (qui, je suppose, est python2)

Si vous exécutez "python" depuis la ligne de commande (sans aucun autre argument), vous verrez probablement que l'interpréteur par défaut est 2.X.

Ainsi, pour que votre code renvoie une sortie identique avec et sans profilage, il devrait être aussi simple que de spécifier python3 lors du profilage :

 python3 -m cProfile scratch.py
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top