2014-04-28 10 views
7

के साथ साइथन में एक अंडारे घोषित करने के लिए कैसे करें यदि यह फ्लोट और डबल दोनों को संभालने में सक्षम होना चाहिए तो साइथन में एक numpy सरणी घोषित करने का सबसे अच्छा तरीका क्या है?एक सामान्य फ्लोटिंग पॉइंट प्रकार

मुझे लगता है कि डेटाटाइप महत्वपूर्ण है क्योंकि मेमोरी व्यू के साथ यह संभव नहीं होगा, लेकिन एक अंडारे के लिए यह एक सामान्य फ्लोट प्रकार देने का कोई तरीका है जो अभी भी साइथन की तेज़ी से लाभान्वित होगा?

def F(np.ndarray A): 
    A += 10 

मैंने देखा है वहाँ भी है कि:

def F(np.ndarray[np.float32_t, ndim=2] A): 
    A += 10 

लेकिन वह फिर प्रकार के लिए एक सा आकार दे देंगे

तो यह है कि मैं क्या आमतौर पर ऐसा होता है। मैंने बिट आकार (32 या 64) के आधार पर फ़ंक्शन के अंदर मेमोरी व्यू बनाने की लाइनों के साथ भी सोचा है।

किसी भी सोचा था कि अत्यधिक सराहना कर रहे हैं


आप floating प्रकार पर टिप के लिए बहुत बहुत धन्यवाद। मैं इसे इस

import numpy as np 
cimport numpy as np 
import cython 
cimport cython 
from libc.math cimport sqrt, abs 
from cython cimport floating 

@cython.boundscheck(False) 
@cython.wraparound(False) 
@cython.nonecheck(False) 
def Rot_Matrix(np.ndarray[floating, ndim=3] Fit_X, 
       np.ndarray[floating, ndim=3] Ref_X, 
       weight = None): 
    cdef: 
     unsigned int t, T = Fit_X.shape[0] 
     unsigned int n, N = Fit_X.shape[1] 
     np.ndarray[floating, ndim=3] Rot = np.empty((T,3,3)) 

    return Rot 

तरह की कोशिश की है जब मैं अब np.float32 मैं त्रुटि मिलती है के दो सरणियों के साथ फ़ंक्शन को कॉल

ValueError: Buffer dtype mismatch, expected 'float' but got 'double'

मैं ब्रेक में प्रकार परिभाषा का उपयोग नहीं करते Rot के लिए तो यह np.ndarray[floating, ndim=3] Rot = np.empty((T,3,3)) पढ़ता है तो मुझे वापस ndarray मिलता है और यह ठीक काम करता है। क्या आपके पास एक संकेतक होगा जो मैं गलत कर रहा हूं?

This goes inside your code.

from cython cimport floating 

def cythonfloating_memoryview(floating[:, :] array): 
    cdef int i, j 

    for i in range(array.shape[0]): 
     for j in range(array.shape[1]): 
      array[i, j] += 10 
बेशक

, वहाँ इस करने के तरीके का भार हैं::

+0

मुझे संदेह है कि आप देशी आकारों के मूल प्रकारों को मिश्रित कर सकते हैं, यह प्रदर्शन को उड़ा देगा। – CoDEmanX

+0

तो क्या आप इसे पहले उदाहरण में करते हुए छोड़ देंगे? क्या यह आयामों की संख्या घोषित करने में मदद करेगा? – Magellan88

+0

@ Magellan88 मैंने अभी आपके पोस्ट में अपडेट देखा है। मैंने अपनी प्रतिक्रिया अपडेट की है। – Veedrac

उत्तर

12

खैर यह वास्तव में जुड़े हुए प्रकार समर्थन के साथ वास्तव में आसान है

Name this fuzed.pyx. There's no need to compile or run cython on it; it's handled by pyximport . Don't use pyximport for production code, though, as you should typically only ship .c files.

from cython cimport floating 
from numpy import float32_t, float64_t, ndarray 

ctypedef fused myfloating: 
    float32_t 
    float64_t 

def cythonfloating_memoryview(floating[:, :] array): 
    # ... 

def cythonfloating_buffer(ndarray[floating, ndim=2] array): 
    # ... 

def myfloating_memoryview(myfloating[:, :] array): 
    # ... 

def myfloating_buffer(ndarray[myfloating, ndim=2] array): 
    # ... 

और यहाँ एक है छोटी परीक्षा स्क्रिप्ट:

Name this test.py and run it as a normal Python script:

import pyximport 
pyximport.install() 

import fuzed 
import numpy 

functions = [ 
    fuzed.cythonfloating_memoryview, 
    fuzed.cythonfloating_buffer, 
    fuzed.myfloating_memoryview, 
    fuzed.myfloating_buffer, 
] 

for function in functions: 
    floats_32 = numpy.zeros((100, 100), "float32") 
    doubles_32 = numpy.zeros((100, 100), "float64") 

    function(floats_32) 
    function(doubles_32) 

    print(repr(floats_32)) 
    print(repr(doubles_32)) 

यह ध्यान देने योग्य है कि में जुड़े प्रकार संकलन में विशेषज्ञता प्राप्त कर रहे हैं, और एक विशेष समारोह मंगलाचरण के लिए निरंतर कर रहे हैं लायक है। आपके द्वारा बनाई गई खाली नम्पी सरणी हमेशा double प्रकार का है, लेकिन आप इसे 32-बिट फ्लोट या 64-बिट फ्लोट पर असाइन करते हैं। यहाँ आप क्या करना चाहिए:

from cython cimport floating 
import numpy 

def do_some_things(floating[:] input): 
    cdef floating[:] output 

    if floating is float: 
     output = numpy.empty(10, dtype="float32") 
    elif floating is double: 
     output = numpy.empty(10, dtype="float64") 
    else: 
     raise ValueError("Unknown floating type.") 

    return output 

और कुछ परीक्षण बात साबित करने के:

import pyximport 
pyximport.install() 
#>>> (None, None) 

import floatingtest 
import numpy 

floatingtest.do_some_things(numpy.empty(10, dtype="float32")) 
#>>> <MemoryView of 'ndarray' at 0x7f0a514b3d88> 
floatingtest.do_some_things(numpy.empty(10, dtype="float32")).itemsize 
#>>> 4 

floatingtest.do_some_things(numpy.empty(10, dtype="float64")) 
#>>> <MemoryView of 'ndarray' at 0x7f0a514b3d88> 
floatingtest.do_some_things(numpy.empty(10, dtype="float64")).itemsize 
#>>> 8 
+0

हाय, टेस्ट स्क्रिप्ट के लिए धन्यवाद, मुझे सच में यकीन नहीं है कि इसका उपयोग कैसे करें। मैंने इसे test.o फ़ाइल में संकलित करने में कामयाब रहा है लेकिन आयात करने के लिए वहां कोई फ़ंक्शन नहीं है। मैंने 'परीक्षण आयात कार्यों' से सूची आयात करने की कोशिश की है लेकिन यह काम नहीं करेगा। मुझे उम्मीद है कि – Magellan88

+1

पर एक प्रश्न का बेवकूफ नहीं है टेस्ट स्क्रिप्ट सिर्फ एक पायथन फ़ाइल है; 'fuzed' कोड के दूसरे ब्लॉक का नाम है। मैं स्पष्ट करने के लिए उत्तर अद्यतन कर दूंगा। – Veedrac

2

इनकार प्रकार केवल समारोह घोषणाओं में इस्तेमाल किया जा सकता। मैं सबसे अच्छा अनुरूपता सी ++ में टेम्पलेट्स के साथ आ सकता हूं।

एक समारोह है कि float32/64 के साथ इस्तेमाल किया जा सकता

from cython import floating, numeric 
cimport cython 

def func_float(floating a): 
    print cython.typeof(a) 

करना हालांकि आप केवल एक समारोह है कि पहले से ही समारोह घोषणा में प्रदर्शित में Fused Types इस्तेमाल किया जा सकता बनाने के लिए।

+0

AFAICT यह सच नहीं है ... फिर भी आपके पास मुझसे अधिक वोट हैं। \ * रोष \ *;) – Veedrac

+0

हाँ मुझे थोड़ी देर बाद एहसास हुआ कि मुझे संकलन त्रुटियां मिली हैं क्योंकि साइथन केवल फ़्यूज्ड घोषणाओं में उपयोग किए गए फ़्यूज्ड प्रकारों को संभालता है। 'def f (numeric a): cdef floating v' का परिणाम संकलन त्रुटि के साथ-साथ' def f (double a) होगा: cdef फ़्लोटिंग v' –

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