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

  • andyabc45

    andyabc45

    1 Mayıs 2011
  • Associated Press

    Associated P

    18 EYLÜL 2006
  • UniqueApps

    UniqueApps

    4 Ocak 2009