Thật khó để trả lời vì np.isnan
và np.isfinite
có thể sử dụng các hàm C khác nhau tùy thuộc vào bản dựng. Và tùy thuộc vào hiệu suất (mà cũng có thể phụ thuộc vào trình biên dịch, hệ thống và làm thế nào NumPy chính nó được xây dựng) của các chức năng C thời gian sẽ khác nhau.
Các ufuncs cho cả tham khảo một built-in npy_
func (source (1.11.3)):
/**begin repeat1
* #kind = isnan, isinf, isfinite, signbit, copysign, nextafter, spacing#
* #func = npy_isnan, npy_isinf, npy_isfinite, npy_signbit, npy_copysign, nextafter, spacing#
**/
Và các chức năng này được xác định dựa trên sự hiện diện của hằng số thời gian biên dịch (source (1.11.3)):
/* use builtins to avoid function calls in tight loops
* only available if npy_config.h is available (= numpys own build) */
#if HAVE___BUILTIN_ISNAN
#define npy_isnan(x) __builtin_isnan(x)
#else
#ifndef NPY_HAVE_DECL_ISNAN
#define npy_isnan(x) ((x) != (x))
#else
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define npy_isnan(x) _isnan((x))
#else
#define npy_isnan(x) isnan(x)
#endif
#endif
#endif
/* only available if npy_config.h is available (= numpys own build) */
#if HAVE___BUILTIN_ISFINITE
#define npy_isfinite(x) __builtin_isfinite(x)
#else
#ifndef NPY_HAVE_DECL_ISFINITE
#ifdef _MSC_VER
#define npy_isfinite(x) _finite((x))
#else
#define npy_isfinite(x) !npy_isnan((x) + (-x))
#endif
#else
#define npy_isfinite(x) isfinite((x))
#endif
#endif
Vì vậy, nó có thể chỉ là trong trường hợp của bạn, np.isfinite
phải làm (nhiều) công việc nhiều hơn np.isnan
. Nhưng cũng có khả năng là trên một máy tính khác hoặc với một máy xây dựng khác, np.isfinite
nhanh hơn hoặc cả hai đều nhanh như nhau.
Vì vậy, có lẽ không phải là một quy tắc cứng "cách nhanh nhất" là gì. Điều đó chỉ phụ thuộc vào quá nhiều yếu tố. Cá nhân tôi sẽ chỉ đi với np.isfinite
vì nó có thể được nhanh hơn (và không quá chậm hơn ngay cả trong trường hợp của bạn) và nó làm cho ý định rõ ràng hơn nhiều.
Chỉ trong trường hợp bạn thực sự đang tối ưu hóa hiệu suất, bạn luôn có thể thực hiện việc phủ nhận tại chỗ. Điều đó có thể làm giảm thời gian và bộ nhớ bằng cách tránh một mảng tạm thời:
import numpy as np
arr = np.random.rand(1000000)
def isnotfinite(arr):
res = np.isfinite(arr)
np.bitwise_not(res, out=res) # in-place
return res
np.testing.assert_array_equal(~np.isfinite(arr), isnotfinite(arr))
np.testing.assert_array_equal(~np.isfinite(arr), np.isnan(arr - arr))
%timeit ~np.isfinite(arr)
# 3.73 ms ± 4.16 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit isnotfinite(arr)
# 2.41 ms ± 29.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit np.isnan(arr - arr)
# 12.5 ms ± 772 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
cũng Lưu ý rằng giải pháp np.isnan
là nhiều chậm hơn trên máy tính của tôi (Windows 10 64bit Python 3.5 NumPy 1.13.1 Anaconda xây dựng)
Thật thú vị, trong máy của tôi (Linux 64 bit, Python 3, NumPy 1.13.1) tùy chọn "hiển nhiên" mất ~ 77,3 µs và tùy chọn 'isnan' 135 µs.Nếu tôi tăng kích thước của 'arr' lên 10000000, sự khác biệt thậm chí còn lớn hơn, 12.5ms so với 89.8ms. – jdehesa
Đây là trên các cửa sổ 64 bit, python 2.7 và vón cục 1.11.3. –
@JonasAdler Bạn có thể thêm mã thời gian để người khác có thể tạo lại (hoặc không) kết quả của bạn không? –