SORU
9 Kasım 2011, ÇARŞAMBA


Python: neden * * * daha hızlı ve daha Karekök()?

Benim kodu optimize ederken aşağıdaki anladım:

>>> from timeit import Timer as T
>>> T(lambda : 1234567890 / 4.0).repeat()
[0.22256922721862793, 0.20560789108276367, 0.20530295372009277]
>>> from __future__ import division
>>> T(lambda : 1234567890 / 4).repeat()
[0.14969301223754883, 0.14155197143554688, 0.14141488075256348]
>>> T(lambda : 1234567890 * 0.25).repeat()
[0.13619112968444824, 0.1281130313873291, 0.12830305099487305]

ve ayrıca:

>>> from math import sqrt
>>> T(lambda : sqrt(1234567890)).repeat()
[0.2597470283508301, 0.2498021125793457, 0.24994492530822754]
>>> T(lambda : 1234567890 ** 0.5).repeat()
[0.15409398078918457, 0.14059877395629883, 0.14049601554870605]

Python C uygulanan biçimi ile bir ilgisi yoktur sanırım, ama kimseye niye böyle olduğunu açıklamak ister mi acaba?

CEVAP
9 Kasım 2011, ÇARŞAMBA


Sonuçlar için (biraz) beklenmedik bir nedenle Python sabit ifade kayan nokta çarpma ve üs ilgili kat gibi görünüyor, ama bölünme değil. math.sqrt() tamamen bunun için bayt kodu var ve bir işlev çağrısı içerir çünkü farklı bir canavar.

Üzerinde Python 2.6.5, aşağıdaki kodu:

x1 = 1234567890.0 / 4.0
x2 = 1234567890.0 * 0.25
x3 = 1234567890.0 ** 0.5
x4 = math.sqrt(1234567890.0)

aşağıdaki bytecodes derler:

  # x1 = 1234567890.0 / 4.0
  4           0 LOAD_CONST               1 (1234567890.0)
              3 LOAD_CONST               2 (4.0)
              6 BINARY_DIVIDE       
              7 STORE_FAST               0 (x1)

  # x2 = 1234567890.0 * 0.25
  5          10 LOAD_CONST               5 (308641972.5)
             13 STORE_FAST               1 (x2)

  # x3 = 1234567890.0 ** 0.5
  6          16 LOAD_CONST               6 (35136.418286444619)
             19 STORE_FAST               2 (x3)

  # x4 = math.sqrt(1234567890.0)
  7          22 LOAD_GLOBAL              0 (math)
             25 LOAD_ATTR                1 (sqrt)
             28 LOAD_CONST               1 (1234567890.0)
             31 CALL_FUNCTION            1
             34 STORE_FAST               3 (x4)

Gördüğünüz gibi, çarpma ve üs kodu derlenmiş yapmış oldukları için hiçbir zaman alır. Bölünme zamanı olur bu yana uzun sürer. Kare Kök dört en hesaplama açısından pahalı bir işlem değil sadece, aynı zamanda Diğerleri değil çeşitli giderleri (öznitelik Arama, arama işlevi, vb) ödenmez.

Eğer sabit katlama etkisini ortadan kaldırmak, küçük çarpma ve bölme ayırmak için var:

In [16]: x = 1234567890.0

In [17]: %timeit x / 4.0
10000000 loops, best of 3: 87.8 ns per loop

In [18]: %timeit x * 0.25
10000000 loops, best of 3: 91.6 ns per loop

math.sqrt(x) aslında biraz daha hızlı muhtemelen ikincisi özel bir durum çünkü x ** 0.5, ve bu nedenle daha verimli bir şekilde yapılabilir, genel giderler " diye sordum

In [19]: %timeit x ** 0.5
1000000 loops, best of 3: 211 ns per loop

In [20]: %timeit math.sqrt(x)
10000000 loops, best of 3: 181 ns per loop

2011-11-16 düzenleme:Sürekli ifade katlanır Piton yılanı deliğinden doktoru tarafından yapılır. Kaynak kodu (peephole.c) neden sürekli bölüm katlanmış değil açıklayan aşağıdaki yorum içerir:

    case BINARY_DIVIDE:
        /* Cannot fold this operation statically since
           the result can depend on the run-time presence
           of the -Qnew flag */
        return 0;

-Qnew bayrak "doğru bölüm" PEP 238 tanımlanmış sağlar.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • hockeywebcasts

    hockeywebcas

    31 EKİM 2012
  • Samantha Crain

    Samantha Cra

    30 EKİM 2008
  • TheJoeycool2010

    TheJoeycool2

    12 Temmuz 2010