Dieses Mal verwende ich ctypes, um meine eigene C-Funktion von Python aus aufzurufen. Ich hatte keinen japanischen Artikel darüber, wie man eine Variable vom Typ "double **" als Argument einer C-Funktion angibt und das Ergebnis als Typ "double **" an Python zurückgibt, also suchte ich kurz. Um genau zu sein, handelt es sich nicht um einen mehrdimensionalen Array-Austausch, sondern um einen variablen Austausch vom Typ "Double **" (leise).
Bereiten Sie zunächst die folgende selbst erstellte Funktion vor. Dieses Mal werden wir allen Elementen der Argumentmatrix n hinzufügen.
libadd.c
#include <stdio.h>
void add_matrix(double **matrix, int row, int col, int n) {
int i, j;
for(i=0; i<row; i++){
for(j=0; j<col; j++){
matrix[i][j] = matrix[i][j] + n;
}
}
}
Und kompiliere wie folgt.
$ gcc -cpp -fPIC -shared libadd.c -lm -o libadd.so -O3
Sie müssen "libadd.so" mit der Option -shared erstellen.
Dann Python-Seite,
test.py
from ctypes import *
import ctypes.util
from numpy.ctypeslib import ndpointer
import numpy as np
from numpy.random import *
#Die Libadd, die Sie gerade erstellt haben.Geben Sie diese Datei an
lib = np.ctypeslib.load_library("libadd.so",".")
#Mach es richtig
row = 20
col = 5
n = 5
matrix = rand(row, col)
#Bereiten Sie den Zeigertyp des Doppelzeigers vor
_DOUBLE_PP = ndpointer(dtype=np.uintp, ndim=1, flags='C')
#add_matrix()Geben Sie den Typ des Funktionsarguments an(ctypes)
lib.add_matrix.argtypes = [_DOUBLE_PP, c_int32, c_int32, c_int32]
#add_matrix()Gibt den Wertetyp an, der von der Funktion zurückgegeben wird(Diesmal kein Rückgabewert)
lib.add_matrix.restype = None
#Magie
tp = np.uintp
mpp = (matrix.__array_interface__['data'][0] + np.arange(matrix.shape[0])*matrix.strides[0]).astype(tp)
#int-Typ ist auch c-Typ c_In int-Typ konvertieren und übergeben
n = ctypes.c_int(n)
row = ctypes.c_int(row)
col = ctypes.c_int(col)
print("before:", matrix)
lib.add_matrix(mpp, row, col, n)
print("after:", matrix)
Ich werde es so vorbereiten. Hier sind einige Dinge, auf die Sie achten sollten (wo ich süchtig bin):
Ich dachte auch, dass _DOUBLE_PP mit POINTER (POINTER (c_double)) verwendet werden könnte, aber es wurde nicht mit Bezug auf die C-Seite übergeben. (Bitte sagen Sie mir, ob es eine andere gute Methode gibt.)
Das Ausführungsergebnis ist wie folgt.
Ausführungsergebnis
$ python test.py
before: [[ 0.38897722 0.46313741 0.84976397 0.64423638 0.95435434]
[ 0.60333226 0.37742093 0.3465723 0.77567722 0.74132703]
[ 0.87302221 0.43188915 0.1211892 0.03272387 0.16480218]
[ 0.60387532 0.37643299 0.72456328 0.67993591 0.6592758 ]
[ 0.63544435 0.7261329 0.16825874 0.11123031 0.97664729]
[ 0.58328763 0.85650723 0.77429203 0.12418374 0.44881621]
[ 0.25106831 0.22417529 0.22837031 0.17608283 0.49529552]
[ 0.75357385 0.3937937 0.99262338 0.23625638 0.37777575]
[ 0.887013 0.85391559 0.32386967 0.30482811 0.67282479]
[ 0.96701627 0.23598535 0.29455679 0.37472803 0.28614415]
[ 0.82208389 0.87058549 0.21354254 0.18766391 0.13951804]
[ 0.22836767 0.4051488 0.79205244 0.17489158 0.83368298]
[ 0.99464033 0.91165387 0.48920652 0.69251231 0.3369773 ]
[ 0.39567888 0.08322727 0.50138724 0.00972839 0.53206287]
[ 0.4981778 0.81622292 0.73376253 0.19702753 0.56725497]
[ 0.37709128 0.8219189 0.59531858 0.60284025 0.75683106]
[ 0.11898215 0.93335749 0.39432259 0.9733907 0.355181 ]
[ 0.54600745 0.36843876 0.52919308 0.22250149 0.66595212]
[ 0.33897066 0.68039774 0.89937153 0.77007464 0.57667845]
[ 0.08015923 0.42939639 0.82431951 0.05494513 0.89979669]]
after: [[ 5.38897722 5.46313741 5.84976397 5.64423638 5.95435434]
[ 5.60333226 5.37742093 5.3465723 5.77567722 5.74132703]
[ 5.87302221 5.43188915 5.1211892 5.03272387 5.16480218]
[ 5.60387532 5.37643299 5.72456328 5.67993591 5.6592758 ]
[ 5.63544435 5.7261329 5.16825874 5.11123031 5.97664729]
[ 5.58328763 5.85650723 5.77429203 5.12418374 5.44881621]
[ 5.25106831 5.22417529 5.22837031 5.17608283 5.49529552]
[ 5.75357385 5.3937937 5.99262338 5.23625638 5.37777575]
[ 5.887013 5.85391559 5.32386967 5.30482811 5.67282479]
[ 5.96701627 5.23598535 5.29455679 5.37472803 5.28614415]
[ 5.82208389 5.87058549 5.21354254 5.18766391 5.13951804]
[ 5.22836767 5.4051488 5.79205244 5.17489158 5.83368298]
[ 5.99464033 5.91165387 5.48920652 5.69251231 5.3369773 ]
[ 5.39567888 5.08322727 5.50138724 5.00972839 5.53206287]
[ 5.4981778 5.81622292 5.73376253 5.19702753 5.56725497]
[ 5.37709128 5.8219189 5.59531858 5.60284025 5.75683106]
[ 5.11898215 5.93335749 5.39432259 5.9733907 5.355181 ]
[ 5.54600745 5.36843876 5.52919308 5.22250149 5.66595212]
[ 5.33897066 5.68039774 5.89937153 5.77007464 5.57667845]
[ 5.08015923 5.42939639 5.82431951 5.05494513 5.89979669]]
Machen wir das! Toll! Selbst wenn Sie dies tun, wird es je nach Inhalt des Prozesses erheblich schneller sein.
Ich habe das Gefühl, dass ich gelesen habe, dass dies mich von GIL befreien wird, daher würde ich gerne Multithreading, Multiverarbeitung oder Hybrid-Parallel verwenden, aber ... es funktioniert bisher nicht.
Recommended Posts