Appeler des fonctions du langage C depuis Python pour échanger des tableaux multidimensionnels

introduction

Cette fois, j'utilise ctypes pour appeler ma propre fonction C depuis Python. Je n'avais pas d'article japonais sur la façon de donner une variable de type «double **» comme argument d'une fonction C et de renvoyer le résultat à Python sous forme de type «double **», j'ai donc cherché brièvement. Donc, pour être précis, ce n'est pas un échange de tableaux multidimensionnels, mais un échange de variables de type «double **» (silencieux).

code

Tout d'abord, préparez la fonction personnalisée suivante. Cette fois, nous ajouterons n à tous les éléments de la matrice d'arguments.

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;
      }
  }
}

Et compilez comme suit.


$ gcc -cpp -fPIC -shared libadd.c -lm -o libadd.so -O3

Vous devez créer libadd.so avec l'option -shared.

Puis côté Python,

test.py



from ctypes import *
import ctypes.util  
from numpy.ctypeslib import ndpointer 
import numpy as np
from numpy.random import *

#Le libadd que vous venez de créer.spécifier un fichier
lib = np.ctypeslib.load_library("libadd.so",".")

#Faites-le correctement
row = 20
col = 5
n = 5
matrix = rand(row, col)

#Préparer le type de pointeur du double pointeur
_DOUBLE_PP = ndpointer(dtype=np.uintp, ndim=1, flags='C')
#add_matrix()Spécifiez le type d'argument de fonction(ctypes) 
lib.add_matrix.argtypes = [_DOUBLE_PP, c_int32, c_int32, c_int32]
#add_matrix()Spécifie le type de valeur renvoyée par la fonction(Aucune valeur de retour cette fois)
lib.add_matrix.restype = None

#la magie
tp = np.uintp
mpp = (matrix.__array_interface__['data'][0] + np.arange(matrix.shape[0])*matrix.strides[0]).astype(tp)

#le type int est aussi le type c c_Convertir en type int et passer
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)

Je vais le préparer comme ça. Voici quelques points à surveiller (là où je suis accro):

Aussi, je pensais que _DOUBLE_PP pouvait être utilisé avec POINTER (POINTER (c_double)), mais il n'a pas été passé par référence au côté C. (Veuillez me dire s'il existe une autre bonne méthode.)

Le résultat de l'exécution est le suivant.

Résultat d'exécution



$ 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]]

Faisons le! Génial! Même si vous faites cela, ce sera considérablement plus rapide en fonction du contenu du processus.

J'ai l'impression d'avoir lu que cela me libérera de GIL, alors j'aimerais utiliser le multi-threading, le multi-processing ou le parallèle hybride, mais ... ça ne marche pas jusqu'à présent.

référence

Recommended Posts

Appeler des fonctions du langage C depuis Python pour échanger des tableaux multidimensionnels
Appeler le langage C depuis Python (python.h)
Langage C pour voir et se souvenir de la partie 2 Appeler le langage C à partir de la chaîne Python (argument)
Langage C pour voir et se souvenir de la partie 1 Appeler le langage C depuis Python (bonjour le monde)
Langage C pour voir et se souvenir de la partie 4 Appelez le langage C depuis Python (argument) double
Langage C pour voir et se souvenir de la partie 5 Appel du langage C à partir du tableau Python (argument)
[Python] Comment appeler une fonction de c depuis python (édition ctypes)
Langage C pour voir et se souvenir de la partie 3 Appelez le langage C depuis Python (argument) c = a + b
Appelez Matlab depuis Python pour optimiser
Appeler C depuis Python avec DragonFFI
Appeler popcount depuis Ruby / Python / C #
Introduction à Protobuf-c (langage C ⇔ Python)
Python pour passer d'une autre langue
Aller au langage pour voir et se souvenir de la partie 8 Appeler le langage GO à partir de Python
Appeler C / C ++ depuis Python sur Mac
Appelez votre propre bibliothèque partagée en langage C à partir de Python à l'aide de ctypes
Générer un langage C à partir d'une expression S avec Python
Utilisation des fonctions C ++ de python avec pybind11
Écriture de journaux dans un fichier CSV (Python, langage C)
Comment appeler l'API Cloud à partir de GCP Cloud Functions
[Python] Précautions lors de l'affectation de valeurs à des tableaux multidimensionnels
Appel de scripts Python à partir de Python intégré en C ++ / C ++
Je veux créer du code C ++ à partir de code Python!
Un moyen simple d'appeler Java depuis Python
Changements de Python 3.0 à Python 3.5
Changements de Python 2 à Python 3.0
Introduction au langage Python
Essayez de créer un module Python en langage C
Appeler CPLEX depuis Python (DO cplex)
Publier de Python vers Slack
Flirter de PHP à Python
Anaconda mis à jour de 4.2.0 à 4.3.0 (python3.5 mis à jour vers python3.6)
Étude de Python Hour3: Fonctions
Passer de python2.7 à python3.6 (centos7)
Connectez-vous à sqlite depuis python
Utilisez un langage de script pour une vie C ++ confortable-OpenCV-Port Python vers C ++ -
Transmettez les données OpenCV de la bibliothèque C ++ d'origine à Python
Comment appeler Python ou Julia à partir de Ruby (implémentation expérimentale)
Porté du langage R de "Sazae-san's Janken Data Analysis" vers Python
[Python] Hit Keras depuis TensorFlow et TensorFlow depuis c ++ pour accélérer l'exécution.
Publier un message d'IBM Cloud Functions sur Slack en Python
Comment se connecter à Cloud Firestore à partir de Google Cloud Functions avec du code Python
Appelez dlm depuis python pour exécuter un modèle de régression à coefficient variable dans le temps
Passer la liste de Python vers C ++ par référence dans pybind11
[Il n'est pas trop tard pour apprendre Python à partir de 2020] Partie 3 Python Language Basic (1)
Publication de Python sur la chronologie Facebook
[Lambda] [Python] Publier sur Twitter depuis Lambda!
Connectez-vous à la base de données utf8mb4 à partir de python
Python (de la première fois à l'exécution)
Publier une image de Python sur Tumblr
10 fonctions du "langage avec batterie" python
Conseils pour appeler Python à partir de C
Exécuter du code Python à partir de l'interface graphique C #
Comment envelopper C en Python
Exécutez des scripts Python de manière synchrone à partir de C #
Appelez python de nim avec Nimpy
Comment accéder à wikipedia depuis python
N'a pas changé de Python 2 à 3