Cython mit Arrays variabler Länge

Oct 06 2020

Dynamisch wachsende Arrays sind eine Art Array. Sie sind sehr nützlich, wenn Sie die genaue Größe des Arrays zur Entwurfszeit nicht kennen. Zuerst müssen Sie eine anfängliche Anzahl von Elementen definieren. ( Wikipedia )

Ich habe eine Python-Lösung geschrieben und in Cython konvertiert . Cython kann verwendet werden, um die Geschwindigkeit von verschachtelten for-Schleifen in Python zu verbessern. Wo mein Cython-Code etwas schneller ist. Meine Cython-Lösung ist offensichtlich nicht die schnellste. Ich versuche, eine verschachtelte for-Schleife ähnlich der in meinem Python-Code so schnell wie möglich in Cython auszuführen.

Es würde helfen, etwas Erfahrung in C zu haben, was ich nicht tue. Das Hauptproblem, auf das ich gestoßen bin, ist, dass Cython andere Gültigkeitsregeln als Python hat. Da C und Python unterschiedliche Gültigkeitsregeln haben. Mit anderen Worten, wir können keinen neuen Vektor in der Schleife erstellen und ihn demselben Namen zuweisen.

Meine Lösung funktioniert, ist aber zu langsam. Kann jemand den obigen Cython-Code verbessern, indem er einen C-ähnlichen Ansatz verwendet?

Python

import numpy as np

my_list = [1,2,3]
n = 10
a = 0.5

Estimate_1_list = []
Estimate_2_list = []

for l in my_list:

    # Resizable matrices
    a_mat = np.zeros((l,n+1),float)
    b_mat = np.zeros((l,n+1),float)
    
    for i  in range(n):
        t = i*a
        
        for j in range(l):
            
            # Fill matrices
            a_mat[j,i+1] = a_mat[j,i+1] + np.random.random()
            
            b_mat[j,i+1] = a_mat[j,i+1]/(2*t+3)
    
    # Append values of interest to use at different values of matrix size
    Estimate_1_list.append(np.mean(a_mat[:,n]))
    Estimate_2_list.append(np.std(a_mat[:,n]))   
results = [Estimate_1_list,Estimate_2_list]

Cython

import cython
# Load cython extension
%load_ext Cython

%%cython
import numpy as np

def my_function(list my_list, int n, int a ):
cdef list Estimate_1_list = []
cdef list Estimate_2_list = []
cdef int l,i,t,j
for l in my_list:

    # Resizable matrices (could I use memory view?)
    a_mat = np.zeros((l,n+1),float)
    b_mat = np.zeros((l,n+1),float)

    for i  in range(n):
        t = i*a

        for j in range(l):

            # Fill matrices
            a_mat[j,i+1] = a_mat[j,i+1] + np.random.random()

            b_mat[j,i+1] = a_mat[j,i+1]/(2*t+3)

    # Append values of interest to use at different values of matrix size
    Estimate_1_list.append(np.mean(a_mat[:,n]))
    Estimate_2_list.append(np.std(a_mat[:,n]))  
    
# Return results 
results = [Estimate_1_list,Estimate_2_list]
return results

Tests

# Test cython to show that the function is running
my_list = [1,2,3]
n = 10
a = 0.5
my_function(my_list, n, a)

[[0.13545224609230933, 0.6603542545719762, 0.6632002117071227],
 [0.0, 0.19967544614685195, 0.22125180486616808]]

Antworten

Reinderien Oct 10 2020 at 00:25

Nullen

Dies:

a_mat = np.zeros

ist nicht der richtige Anruf für Ihren Zweck. Sie möchten np.emptystattdessen, weil es Ihnen eigentlich egal ist, wie die Anfangswerte lauten, da Sie direkt danach eine umfassende Initialisierungsschleife durchführen.

Darüber hinaus: Da Sie random()zu jedem Element von hinzufügen a_mat, initialisieren Sie einfach a_mateinen einzelnen Aufruf von random()mit der richtigen Form, anstatt elementweise hinzufügen zu müssen.

Vektorisierung

Sie haben eine äußere Dimension ( ldurch my_list), eine zweite Dimension ( l) und eine dritte Dimension ( n + 1). Die zweite Dimension ist variabel; der erste und der dritte sind konstant. Dies bedeutet, dass Sie dies effizienter darstellen können, wenn Sie Ihre Abmessungen so neu anordnen, dass sich die festen im Innenraum befinden. Mit anderen Worten, wenn Sie hatten

len(my_list) = 3
l = 1, 2, 3
n = 10

dann können Sie dies tatsächlich als eine einzelne dreidimensionale Matrix der Dimensionen 6 * 3 * 10 darstellen, wobei 6 == len(my_list) * (len(my_list) - 1). Ich denke, es ist möglich, all dies ohne eine einzige forSchleife zu tun , was ideal für vektorisierte Leistung ist.