2017-08-18 9 views
5

यह प्रेरित है: python: Combined masking in numpyगैर-सीमित मूल्यों को खोजने का सबसे तेज़ तरीका

कार्य उन सभी मूल्यों का एक बूलियन सरणी बनाना है जो परिमित नहीं हैं। उदाहरण के लिए:

>>> arr = np.array([0, 2, np.inf, -np.inf, np.nan]) 
>>> ~np.isfinite(arr) 
array([False, False, True, True, True], dtype=bool) 

मेरे लिए, ऐसा लगता है यह गैर-परिमित मूल्यों को खोजने का सबसे तेज़ तरीका हो सकता है, लेकिन ऐसा लगता है एक तेज़ तरीका नहीं है। विशेष रूप से np.isnan(arr - arr) भी ऐसा ही करना चाहिए:

>>> np.isnan(arr - arr) 
array([False, False, True, True, True], dtype=bool) 

समय यह हम देखते हैं कि यह दोगुनी गति से है!

arr = np.random.rand(100000) 

%timeit ~np.isfinite(arr) 
10000 loops, best of 3: 198 µs per loop 

%timeit np.isnan(arr - arr) 
10000 loops, best of 3: 85.8 µs per loop 

तो मेरे सवाल दोहरा है:

  1. np.isnan(arr - arr) चाल तेजी से "स्पष्ट" ~np.isfinite(arr) संस्करण की तुलना में क्यों है? क्या कोई इनपुट है जिसके लिए यह काम नहीं करता है?

  2. क्या सभी गैर-सीमित मूल्यों को खोजने का कोई तेज़ तरीका है? क्योंकि np.isnan और np.isfinite निर्माण के आधार पर अलग सी कार्यों का उपयोग कर सकते हैं

+2

पर धीमी है: यह एक अस्थायी सरणी से बचने के समय और स्मृति कम हो सकती है दिलचस्प बात यह है कि, मेरी मशीन में (लिनक्स 64 बिट्स, पायथन 3, न्यूपी 1.13.1) "स्पष्ट" विकल्प ~ 77.3 μs और 'इस्नान' विकल्प 135 μs लेता है।यदि मैं 'arr' के आकार को 10000000 तक बढ़ाता हूं तो अंतर भी बड़ा होता है, 12.5ms बनाम 89.8ms। – jdehesa

+0

यह विंडोज 64 बिट, पायथन 2.7 और numpy 1.11.3 पर है। –

+0

@ जोनासएडलर क्या आप समय कोड जोड़ सकते हैं ताकि अन्य आपके परिणाम पुन: पेश कर सकें (या नहीं)? –

उत्तर

3

कि मुश्किल है जवाब देने के लिए। और प्रदर्शन के आधार पर (जो संकलन पर निर्भर हो सकता है, सिस्टम और कैसे NumPy स्वयं बनाया गया है) इन सी कार्यों में समय अलग होगा।


दोनों के लिए ufuncs का उल्लेख एक अंतर्निहित npy_ समारोह (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# 
**/ 

और इन कार्यों संकलन समय स्थिरांक की उपस्थिति के आधार पर परिभाषित कर रहे हैं (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 

तो यह हो सकता है कि आपके मामले में np.isfinite को np.isnan से अधिक (अधिक) काम करना होगा । लेकिन यह समान रूप से संभव है कि किसी अन्य कंप्यूटर पर या किसी अन्य निर्माण के साथ np.isfinite तेज है या दोनों समान रूप से तेज़ हैं।

तो, शायद "सबसे तेज़ तरीका" क्या कठिन नियम नहीं है। यह सिर्फ बहुत से कारकों पर निर्भर करता है। व्यक्तिगत रूप से मैं सिर्फ np.isfinite के साथ जाऊंगा क्योंकि यह तेज हो सकता है (और आपके मामले में भी बहुत धीमा नहीं है) और यह इरादा को अधिक स्पष्ट बनाता है।


बस यदि आप वास्तव में प्रदर्शन को अनुकूलित करने में सक्षम हैं, तो आप हमेशा नकारात्मक जगह पर जा सकते हैं।

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) 

भी ध्यान दें कि np.isnan समाधान ज्यादा अपने कंप्यूटर (विंडोज 10 64 बिट अजगर 3.5 NumPy 1.13.1 एनाकोंडा निर्माण)

संबंधित मुद्दे