2014-12-19 11 views
8

मैं अन्य काम के लिए तैयारी में Cython के साथ प्रयोग करना किया गया है बनाम। मैंने एक साधारण परीक्षण मामले की कोशिश की और बड़े कोड आकार के लिए मेरे कोड के तरीके के साथ कुछ अजीब देखा। मैंने एक साधारण न्यूनतम/अधिकतम फ़ंक्शन बनाया जो 2 डी फ्लोट 32 सरणी के न्यूनतम और अधिकतम की गणना करता है और इसे numpy.min(a), numpy.max(a) चलाने के लिए तुलना करता है। 10000 तत्वों की एक सरणी के लिए प्रदर्शन समान था। 1000000 तत्वों की एक सरणी के लिए साइथन ने बहुत खराब प्रदर्शन किया। यहाँ मेरी सरल समय IPython में किया हैCython numpy के प्रदर्शन का आकलन

import numpy 
cimport cython 
cimport numpy 

DTYPE = numpy.float32 
ctypedef numpy.float32_t DTYPE_t 

@cython.boundscheck(False) 
@cython.wraparound(False) 
def minmax_float32(numpy.ndarray[DTYPE_t, ndim=2] arr): 
    cdef DTYPE_t min = arr[0, 0] 
    cdef DTYPE_t max = arr[0, 0] 
    cdef int row_max = arr.shape[0] 
    cdef int col_max = arr.shape[1] 
    cdef int x, y 
    for y in range(row_max): 
     for x in range(col_max): 
      if arr[y, x] < min: 
       min = arr[y, x] 
      if arr[y, x] > max: 
       max = arr[y, x] 

    return min, max 

और: यहाँ मेरी cython कोड है

a = numpy.random.random(10000).reshape((100, 100)).astype(numpy.float32) 
%timeit -r3 -n50 (numpy.min(a), numpy.max(a)) 
# 50 loops, best of 3: 22.2 µs per loop 

%timeit -r3 -n50 minmax_float32(a) 
# 50 loops, best of 3: 23.8 µs per loop 

a = numpy.random.random(1000000).reshape((1000, 1000)).astype(numpy.float32) 
%timeit -r3 -n50 (numpy.min(a), numpy.max(a)) 
# 50 loops, best of 3: 307 µs per loop 

%timeit -r3 -n50 minmax_float32(a) 
# 50 loops, best of 3: 1.22 ms per loop 

307/22.2 
# 13.82882882882883 

1220/23.8 
# 51.26050420168067 

किसी को भी क्यों cython बड़ा इनपुट के लिए इतना समय लगता है के लिए विचार है? और यह वही था जो मैं खेल रहा था, लेकिन अगर आपके पास कोई सुझाव या चाल है तो मुझे उनकी सुनवाई में दिलचस्पी है। अग्रिम में धन्यवाद।

संपादित करें: मैं स्मृति के 8GB के साथ एक मैकबुक 10.10 पर इन परीक्षणों भाग गया। अपने ट्यूटोरियल -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing में उल्लिखित झंडे के साथ मैकपोर्ट्स से जीसीसी के साथ साइथन को संकलित किया।

+0

अगर आप अपने आंतरिक और बाहरी छोरों फ्लिप क्या होता है? – mtrw

+0

अच्छा सवाल, यह ~ 7ms तक चला जाता है। मैंने जो कुछ किया वह दो 'लाइनों' को बदल गया था। – daveydave400

+0

मेरा अनुमान है कि कि संकलक ठीक से autovectorize के लिए संघर्ष कर सकती है - [इस] (https://groups.google.com/d/msg/cython-users/LfBH6M7gNTc/B19uFB5YbYYJ)। –

उत्तर

2

ऐसा लगता है कि NumPy एसएसई निर्देशों का उपयोग करता है जहां min और max के लिए उपलब्ध है, जिसका अर्थ है कि वे शायद आपके हार्डवेयर का लाभ साइथन के मुकाबले ज्यादा हद तक लाभ उठा सकते हैं।

एसएसई: https://github.com/numpy/numpy/blob/master/numpy/core/src/umath/simd.inc.src#L696 में न्यूमपी के min और max में कमी कार्यान्वयन के लिए स्रोत कोड यहां दिया गया है। ध्यान दें कि वे कई डेटाटाइप और संचालन के साथ स्वचालित रूप से कोड उत्पन्न करने के लिए प्रीप्रोसेसर का उपयोग कर रहे हैं।

+0

मैंने numpy स्रोत को देखा था, लेकिन 'loops.c.src' ढूंढने के लिए समाप्त हुआ जिसमें कोई अनुकूलन नहीं है। यह निश्चित रूप से ऐसा लगता है कि इससे कोई फर्क पड़ सकता है। – daveydave400

1

भ्रम से बचने के यह एक अच्छा विचार फ़ंक्शन नाम न्यूनतम और अधिकतम में निर्माण का उपयोग करने के रूप में चर नाम तो fmin और fmax फोन कभी नहीं है पहले।

मूल रूप से यह याद है कि numpy अत्यधिक अनुकूलित है लायक है, आप भी अपनी cython बदलते में की कोशिश कर सकते:

for x in range(col_max): 
     if arr[y, x] < min: 
      min = arr[y, x] 
     if arr[y, x] > max: 
      max = arr[y, x] 

रहे हैं:

for x in range(col_max): 
     val = arr[y, x] 
     if val < fmin: 
      fmin = val 
     if val > fmax: 
      fmax = val 

और परिभाषा जोड़ने: cdef DTYPE_t val

यह 4 से करने के लिए सरणी सूचकांक संचालन की संख्या कम हो जाएगा 1.

के रूप में यह कुछ सुधार दिखा सकते हैं

(fmin, fmax) = (min(fmin, val), max(fmax, val)) 

: 210

तुम भी उपयोग करने का प्रयास कर सकता है।

तुम भी अहस्ताक्षरित ints में एक्स, वाई, row_max और row_min बनाने के लिए और समारोह डेकोरेटर @cython.boundscheck(False) # turn of bounds-checking for entire function

यह tutorial पढ़ने लायक है जोड़कर सीमा जाँच बंद कर सकते हैं।

+0

के साथ मैंने आपके सुझावों का प्रयास किया, लेकिन निष्पादन समय के साथ कुछ भी नहीं हुआ। मेरे पास पहले से ही सीमाओं की जांच बंद हो गई थी और उस ट्यूटोरियल को देखा था (हालांकि ऐसा लगता है कि यह उनकी उपयोगकर्ता मार्गदर्शिका में कॉपी किया गया था जो मैंने किया था)। मैंने 'cdef dTYPE_t max' नहीं किया क्योंकि मुझे सच में यकीन नहीं है कि आप इसका क्या मतलब रखते हैं। वह क्या करेगा? – daveydave400

+0

क्षमा करें टाइपिफ़ को वैल का होना चाहिए था। ऊपर संपादित यह समय के बाद एक नए वैल समय के निर्माण को रोक देगा। –

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