Bu performanstan estetiğini ayırmak önemlidir. Bazen çirkin kod hızlıdır. Aslında, buradaki durum budur. Boş bir dizi oluştururken ve daha sonra dilimlere değerler atamak güzel görünmese de, hızlıdır.
import numpy as np
import timeit
import itertools as IT
import pandas as pd
def using_empty(x):
x = np.asarray(x)
result = np.empty(x.shape + (2,))
result[..., 0] = x
result[..., 1] = np.log(x)
return result
def using_concat(x):
x = np.asarray(x)
return np.concatenate([x, np.log(x)], axis=-1).reshape(x.shape+(2,), order='F')
def using_stack(x):
x = np.asarray(x)
return np.stack([x, np.log(x)], axis=x.ndim)
def using_ufunc(x):
return np.array([x, np.log(x)])
using_ufunc = np.vectorize(using_ufunc, otypes=[np.ndarray])
tests = [np.arange(600),
np.arange(600).reshape(20,30),
np.arange(960).reshape(8,15,8)]
# check that all implementations return the same result
for x in tests:
assert np.allclose(using_empty(x), using_concat(x))
assert np.allclose(using_empty(x), using_stack(x))
timing = []
funcs = ['using_empty', 'using_concat', 'using_stack', 'using_ufunc']
for test, func in IT.product(tests, funcs):
timing.append(timeit.timeit(
'{}(test)'.format(func),
setup='from __main__ import test, {}'.format(func), number=1000))
timing = pd.DataFrame(np.array(timing).reshape(-1, len(funcs)), columns=funcs)
print(timing)
verimleri, benim makinede aşağıdaki sürümüyle gelen timeit sonuçları:
using_empty using_concat using_stack using_ufunc
0 0.024754 0.025182 0.030244 2.414580
1 0.025766 0.027692 0.031970 2.408344
2 0.037502 0.039644 0.044032 3.907487
Yani using_empty
(seçenekler tests
uygulanan Test edilen) en hızlı olduğunu. np.stack
böylece
np.stack([x, np.log(x)], axis=x.ndim)
, ne istediğinizi tam olarak yaptığı
Not makul güzel görünüyor, ama aynı zamanda test edilen üç seçenekten en yavaş olduğunu.
In [236]: x = np.arange(6)
In [237]: using_ufunc(x)
Out[237]:
array([array([ 0., -inf]), array([ 1., 0.]),
array([ 2. , 0.69314718]),
array([ 3. , 1.09861229]),
array([ 4. , 1.38629436]), array([ 5. , 1.60943791])], dtype=object)
arzu edilen sonuç ile aynı değildir:
ben gibi
In [240]: using_empty(x)
Out[240]:
array([[ 0. , -inf],
[ 1. , 0. ],
[ 2. , 0.69314718],
[ 3. , 1.09861229],
[ 4. , 1.38629436],
[ 5. , 1.60943791]])
In [238]: using_ufunc(x).shape
Out[238]: (6,)
In [239]: using_empty(x).shape
Out[239]: (6, 2)
'yığın boyunca daha yavaş olmak üzere
using_ufunc
nesne d_type bir dizi dönerNot 'aslında en iyi. Genellikle hızım için Python kodumu optimize etmiyorum :) –
Bunu yapmak için başka bir yol olarak '@ ufunc' dekoratörünü ekleyebilir misiniz? –
'@ ufunc' dekoratörüne aşina değilim. [Bu] 'a atıfta bulunuyorsunuz (https://mail.python.org/pipermail/python-dev/2013-June/126864.html)? – unutbu