2014-04-28 3 views
7

Was ist der beste Weg, um ein numpy Array in Cython zu deklarieren, wenn es in der Lage sein sollte, sowohl float als auch double zu behandeln?Wie deklariert man ein NDarray in Cython mit einem allgemeinen Gleitkommatyp

Ich denke, dass es mit einer Speicheransicht nicht möglich sein wird, da dort der Datentyp entscheidend ist, aber für ein ndarray gibt es eine Möglichkeit, es einen allgemeinen Float-Typ zu geben, der immer noch von der Schnelligkeit von Cython profitieren würde?

so ist es das, was ich würde usualy tun:

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

Ich habe gesehen, dass es auch ist:

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

aber das wird wieder ein wenig Größe für die Art geben. Ich habe auch daran gedacht, eine Speicheransicht innerhalb der Funktion abhängig von der Bitgröße (32 oder 64) zu erstellen.

Jeder Gedanke für die Spitze so viel Danke sehr geschätzt


auf dem floating Typ. Ich habe es versucht, wie diese

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 

, wenn ich jetzt die Funktion mit zwei Reihen von np.float32 nenne ich den Fehler

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

Wenn ich nicht das die Typdefinition in den Bremsen für Rot so liest es np.ndarray[floating, ndim=3] Rot = np.empty((T,3,3)) dann bekomme ich Ndray zurück und es funktioniert gut. Hättest du zufällig einen Zeiger für mich, was ich falsch mache?

+0

Ich bezweifle, dass Sie native Typen unterschiedlicher Größen mischen können, würde es die Leistung blasen. – CoDEmanX

+0

Sie würden es also einfach so lassen wie im ersten Beispiel? Würde es helfen, die Anzahl der Dimensionen zu deklarieren? – Magellan88

+0

@ Magellan88 Ich habe gerade das Update auf Ihren Post gesehen. Ich habe meine Antwort aktualisiert. – Veedrac

Antwort

12

Gut, das ist eigentlich sehr einfach, mit verschmolzenen Typen Unterstützung:

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 

Natürlich gibt es viele Möglichkeiten dies zu tun:

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): 
    # ... 

und hier ist ein kleines Testskript:

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)) 

Es ist erwähnenswert, dass verschmolzenen Typen bei der Kompilierung spezialisiert sind, und sind konstant für einen bestimmten Funktionsaufruf. Das leere Numpy-Array, das Sie erstellen, hat immer den Typ double, aber Sie weisen es entweder einem 32-Bit-Float oder einem 64-Bit-Float zu. Hier ist, was Sie tun sollten:

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 

und einige Tests auf den Punkt zu beweisen:

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

hi, danke für das Testskript, ich bin mir nicht sicher, wie man es benutzt. Ich habe es geschafft, es in eine test.o Datei zu kompilieren, aber es gibt keine Funktion zum Importieren. Ich habe versucht, die Liste zu importieren, indem ich 'von den Testimportfunktionen' tue, aber das funktioniert nicht. Ich hoffe, dass eine Frage nicht zu dumm ist – Magellan88

+1

Das Testskript ist nur eine Python-Datei; 'fuzed' ist der Name des zweiten Codeblocks. Ich werde die Antwort aktualisieren, um zu klären. – Veedrac

2

Fused-Typen können nur in Funktionsdeklarationen verwendet werden. Die beste Analogie, die ich mir vorstellen kann, sind Templates in C++.

Um eine Funktion zu erstellen, die mit float32/64 tun verwendet werden können

from cython import floating, numeric 
cimport cython 

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

jedoch nur Fused Types in einer Funktion verwendet werden, können die bereits in der Funktionsdeklaration erscheinen.

+0

AFAICT dies ist nicht wahr ... noch haben Sie mehr Stimmen als ich. \ * crities \ *;) – Veedrac

+0

yeah Ich habe später bemerkt, dass ich Kompilierungsfehler bekommen habe, weil Cython nur die fusionierten Typen behandelt, die in der Funktionsdeklaration verwendet werden. 'def f (numerisch a): cdef floating v' führt zu einem Kompilierungsfehler sowie' def f (double a): cdef floating v' –

Verwandte Themen