programing

파이썬 3에서 x**4.0이 x**4보다 빠른 이유는 무엇입니까?

easyjava 2023. 5. 9. 23:11
반응형

파이썬 3에서 x**4.0이 x**4보다 빠른 이유는 무엇입니까?

이유는x**4.0보다 빠른.x**4저는 Cython 3.5.2를 사용하고 있습니다.

$ python -m timeit "for x in range(100):" " x**4.0"
  10000 loops, best of 3: 24.2 usec per loop

$ python -m timeit "for x in range(100):" " x**4"
  10000 loops, best of 3: 30.6 usec per loop

어떻게 작동하는지 보려고 올린 검정력을 바꾸려고 했는데, 예를 들어 x를 10이나 16의 검정력으로 올리면 30에서 35로 껑충 뛰지만, 10.0을 플로트로 올리면 24.1~4 정도만 움직입니다.

플로트 변환과 2의 파워와 관련이 있을 것 같은데, 잘 모르겠습니다.

두 가지 경우 모두 2의 거듭제곱이 더 빠르다는 것을 알게 되었습니다. 통역사/컴퓨터에게는 이러한 계산이 더 네이티브/쉽기 때문인 것 같습니다.하지만 여전히, 부유물은 거의 움직이지 않습니다. 2.0 => 24.1~4 & 128.0 => 24.1~4 그렇지만 2 => 29 & 128 => 62


타이거호크T3 pointed out that it doesn't happen outside of the loop. I checked and the situation only occurs (from what I've seen) when the 기초 is getting raised. Any idea about that?

이유는x**4.0 보다 빠른.x**4파이썬* 3에서?

파이썬 3int객체는 임의의 크기를 지원하도록 설계된 완전한 날개를 가진 객체입니다. 그 때문에, 그들은 C 레벨에서 그렇게 처리됩니다. (모든 변수가 다음과 같이 선언되는 방법 참조)PyLongObject *타이프로 치다long_pow) 또한 이것은 당신이 그것들을 가지고 놀 필요가 있기 때문에 그것들의 지수화를 훨씬까다롭고 지루하게 만듭니다.ob_digit수행하기 위해 사용하는 값을 나타내는 배열. (용감한 사람을 위한 소스. -- 참조: 자세한 내용은 파이썬에서 정수에 대한 메모리 할당 이해PyLongObjects.)

파이썬float반대로 물체는 C로 변환될 수 있습니다.double를 사용하여 type을 입력하고 이러한 기본 유형을 사용하여 작업을 수행할 수 있습니다.는 관련 에지 사례를 확인한 후 Python이 플랫폼(C's)을 사용하여 실제 지수를 처리할 수 있기 때문에 매우 좋습니다.

/* Now iv and iw are finite, iw is nonzero, and iv is
 * positive and not equal to 1.0.  We finally allow
 * the platform pow to step in and do the rest.
 */
errno = 0;
PyFPE_START_PROTECT("pow", return NULL)
ix = pow(iv, iw); 

어디에iv그리고.iw우리의 오리지널PyFloatObject완전히doubles.

가치 있는 일: 파이썬2.7.13나에게는 하나의 요소입니다.2~3더 빠르고 역방향 동작을 보여줍니다.

이전의 사실도 파이썬 2와 3의 차이를 설명하기 때문에 흥미롭기 때문에 이 의견도 다뤄야겠다고 생각했습니다.

Python 2에서는 이전 버전을 사용합니다.int와 다른 객체intPython 3의 개체(모두)int3.x의 객체는PyLongObjecttype). Python 2에서는 객체의 값에 따라 구분됩니다(또는 접미사를 사용하는 경우).L/l):

# Python 2
type(30)  # <type 'int'>
type(30L) # <type 'long'>

<type 'int'>여기 보시는 바와 같이 동일한 작업을 수행합니다. 안전하게 C로 변환됩니다.long 그것에 대해 지수화가 수행될 때 (Theint_pow또한 컴파일러가 레지스터에 저장할 수 있으면 레지스터에 저장하여 차이를 만들 수 있음을 암시합니다.)

static PyObject *
int_pow(PyIntObject *v, PyIntObject *w, PyIntObject *z)
{
    register long iv, iw, iz=0, ix, temp, prev;
/* Snipped for brevity */    

이것은 좋은 속도 이득을 허용합니다.

얼마나 느리는지 보기<type 'long'>는 와비서는 s와 <type 'int'>s, 만약 당신이 그것을 포장했다면.x에 이름을 대다.long2를 합니다(으로 Python 2를 하도록 강제함long_powPython 3)에서처럼 속도 이득이 사라집니다.

# <type 'int'>
(python2) ➜ python -m timeit "for x in range(1000):" " x**2"       
10000 loops, best of 3: 116 usec per loop
# <type 'long'> 
(python2) ➜ python -m timeit "for x in range(1000):" " long(x)**2"
100 loops, best of 3: 2.12 msec per loop

하나의 스니펫이 다음을 변환하지만, 주의하십시오.intlong다른 하나는 그렇지 않지만(@pydsinger가 지적한 바와 같이), 이 출연진은 속도 저하의 원인이 되지 않습니다.의 .long_pow (으로 사용하는 ). (문을 단독으로 사용하는 시간)long(x)을 확인합니다.

[...] 고리 밖에서는 그런 일이 일어나지 않습니다. [...] 그것에 대해 아는 것이 있나요?

이것은 여러분을 위해 상수를 접는 CPython의 피프홀 옵티마이저입니다.두 경우 모두 정확한 시간을 얻을 수 있습니다. 왜냐하면 지수화의 결과를 찾기 위한 실제 계산은 없고 값만 로드되기 때문입니다.

dis.dis(compile('4 ** 4', '', 'exec'))
  1           0 LOAD_CONST               2 (256)
              3 POP_TOP
              4 LOAD_CONST               1 (None)
              7 RETURN_VALUE

동일한 가 다에대동바코생다성니됩에 됩니다.'4 ** 4.'유일한 차이점은LOAD_CONST플로트를 적재합니다.256.0 도의대에 256:

dis.dis(compile('4 ** 4.', '', 'exec'))
  1           0 LOAD_CONST               3 (256.0)
              2 POP_TOP
              4 LOAD_CONST               2 (None)
              6 RETURN_VALUE

그래서 시간은 똑같습니다.


*위의 모든 내용은 Python의 레퍼런스 구현인 Cython에만 적용됩니다.다른 구현의 성능은 다를 수 있습니다.

우리가 바이트코드를 보면, 우리는 그 표현들이 완전히 동일하다는 것을 알 수 있습니다.은 유한차은다음같과변될유다니의 가 될 입니다.BINARY_POWER그래서 가장 확실한 이유는int라인 아래의 부동 소수점 번호로 변환됩니다.

>>> def func(n):
...    return n**4
... 
>>> def func1(n):
...    return n**4.0
... 
>>> from dis import dis
>>> dis(func)
  2           0 LOAD_FAST                0 (n)
              3 LOAD_CONST               1 (4)
              6 BINARY_POWER
              7 RETURN_VALUE
>>> dis(func1)
  2           0 LOAD_FAST                0 (n)
              3 LOAD_CONST               1 (4.0)
              6 BINARY_POWER
              7 RETURN_VALUE

업데이트: CPython 소스 코드에서 Objects/abstract.c를 살펴보겠습니다.

PyObject *
PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
{
    return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()");
}

PyNumber_Power 출들ternary_op여기에 붙이기에는 너무 길기 때문에, 여기 링크가 있습니다.

그것은 그것을 부릅니다.nb_power의 한 칸xy의론으로서

마막으로에서.float_pow()Objects/floatobject.c의 686행에서 우리는 인수가 C로 변환되는 것을 봅니다.double실제 작업 직전:

static PyObject *
float_pow(PyObject *v, PyObject *w, PyObject *z)
{
    double iv, iw, ix;
    int negate_result = 0;

    if ((PyObject *)z != Py_None) {
        PyErr_SetString(PyExc_TypeError, "pow() 3rd argument not "
            "allowed unless all arguments are integers");
        return NULL;
    }

    CONVERT_TO_DOUBLE(v, iv);
    CONVERT_TO_DOUBLE(w, iw);
    ...

하나가 정확하기 때문에 다른 하나는 근사치입니다.

>>> 334453647687345435634784453567231654765 ** 4.0
1.2512490121794596e+154
>>> 334453647687345435634784453567231654765 ** 4
125124901217945966595797084130108863452053981325370920366144
719991392270482919860036990488994139314813986665699000071678
41534843695972182197917378267300625

언급URL : https://stackoverflow.com/questions/42355194/why-is-x4-0-faster-than-x4-in-python-3

반응형