파이썬 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의 한 칸x 길y의론으로서
마막으로에서.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
'programing' 카테고리의 다른 글
| 동일한 종속 어셈블리의 서로 다른 버전 간에 해결할 수 없는 충돌이 발견되었습니다. (0) | 2023.05.09 |
|---|---|
| 프로세스인지 확인하는 방법.시작()이(가) 성공적입니까? (0) | 2023.05.09 |
| PostgreSQL에서 범주별로 최대 날짜 그룹이 있는 ID를 선택하는 방법은 무엇입니까? (0) | 2023.05.09 |
| MongoDB 나침반: 고유 필드 값 선택 (0) | 2023.05.09 |
| web.config에서 SMTP 설정을 구성하는 방법 (0) | 2023.05.09 |