![](/img/trans.png)
[英]Passing Numpy arrays to a C function for input and output
[英]Passing a set of NumPy arrays into C function for input and output
假設我們有一個C函數,它接受一組一個或多個輸入數組,處理它們,並將其輸出寫入一組輸出數組。 簽名如下所示( count
表示要處理的數組元素的數量):
void compute (int count, float** input, float** output)
我想通過ctypes從Python調用此函數,並使用它將轉換應用於一組NumPy數組。 對於定義為的單輸入/單輸出功能
void compute (int count, float* input, float* output)
以下作品:
import ctypes
import numpy
from numpy.ctypeslib import ndpointer
lib = ctypes.cdll.LoadLibrary('./block.so')
fun = lib.compute
fun.restype = None
fun.argtypes = [ctypes.c_int,
ndpointer(ctypes.c_float),
ndpointer(ctypes.c_float)]
data = numpy.ones(1000).astype(numpy.float32)
output = numpy.zeros(1000).astype(numpy.float32)
fun(1000, data, output)
但是,我不知道如何為多個輸入(和/或輸出)創建相應的指針數組。 有任何想法嗎?
編輯 :所以人們一直想知道如何compute
知道有多少數組指針預期(如count
是指每個數組元素的個數)。 事實上,這是硬編碼的; 給定的compute
精確地知道預期的輸入和輸出數量。 驗證input
和output
指向正確數量的輸入和輸出是調用者的工作。 這是一個compute
帶有2個輸入並寫入1個輸出數組的示例:
virtual void compute (int count, float** input, float** output) {
float* input0 = input[0];
float* input1 = input[1];
float* output0 = output[0];
for (int i=0; i<count; i++) {
float fTemp0 = (float)input1[i];
fRec0[0] = ((0.09090909090909091f * fTemp0) + (0.9090909090909091f * fRec0[1]));
float fTemp1 = (float)input0[i];
fRec1[0] = ((0.09090909090909091f * fTemp1) + (0.9090909090909091f * fRec1[1]));
output0[i] = (float)((fTemp0 * fRec1[0]) - (fTemp1 * fRec0[0]));
// post processing
fRec1[1] = fRec1[0];
fRec0[1] = fRec0[0];
}
}
我無法影響compute
的簽名和實現。 我可以驗證(來自Python!)需要多少輸入和輸出。 關鍵問題是如何為函數提供正確的argtypes
,以及如何在NumPy(指向NumPy數組的指針數組)中生成適當的數據結構。
要使用Numpy數組專門執行此操作,您可以使用:
import numpy as np
import ctypes
count = 5
size = 1000
#create some arrays
arrays = [np.arange(size,dtype="float32") for ii in range(count)]
#get ctypes handles
ctypes_arrays = [np.ctypeslib.as_ctypes(array) for array in arrays]
#Pack into pointer array
pointer_ar = (ctypes.POINTER(C.c_float) * count)(*ctypes_arrays)
ctypes.CDLL("./libfoo.so").foo(ctypes.c_int(count), pointer_ar, ctypes.c_int(size))
事物的C面可能是這樣的:
# function to multiply all arrays by 2
void foo(int count, float** array, int size)
{
int ii,jj;
for (ii=0;ii<count;ii++){
for (jj=0;jj<size;jj++)
array[ii][jj] *= 2;
}
}
在C中, float**
指向float*
指針的表/數組中的第一個元素。
據推測,每個float*
指向float
值的表/數組中的第一個元素。
您的函數聲明有1個計數,但不清楚這個計數適用於什么:
void compute (int count, float** input, float** output)
count
x count
大小? count
-sized float*
of float*
以某種方式終止,例如用nan
? float*
每個count
元素數組(合理的假設)? 請澄清你的問題,我會澄清我的答案:-)
假設最后一個API解釋,這是我的示例計算函數:
/* null-terminated array of float*, each points to count-sized array
*/
extern void compute(int count, float** in, float** out)
{
while (*in)
{
for (int i=0; i<count; i++)
{
(*out)[i] = (*in)[i]*42;
}
in++; out++;
}
}
測試計算函數的測試代碼:
#include <stdio.h>
extern void compute(int count, float** in, float** out);
int main(int argc, char** argv)
{
#define COUNT 3
float ina[COUNT] = { 1.5, 0.5, 3.0 };
float inb[COUNT] = { 0.1, -0.2, -10.0 };
float outa[COUNT];
float outb[COUNT];
float* in[] = {ina, inb, (float*)0};
float* out[] = {outa, outb, (float*)0};
compute(COUNT, in, out);
for (int row=0; row<2; row++)
for (int c=0; c<COUNT; c++)
printf("%d %d %f %f\n", row, c, in[row][c], out[row][c]);
return 0;
}
以及如何通過Python中的ctypes使用相同的count
== 10 float
子數組和size 2
float*
數組,包含1個真正的子數組和NULL終結符:
import ctypes
innertype = ctypes.ARRAY(ctypes.c_float, 10)
outertype = ctypes.ARRAY(ctypes.POINTER(ctypes.c_float), 2)
in1 = innertype(*range(10))
in_ = outertype(in1, None)
out1 = innertype(*range(10))
out = outertype(out1, None)
ctypes.CDLL("./compute.so").compute(10, in_, out)
for i in range(10): print in_[0][i], out[0][i]
這里介紹了ctypes的Numpy接口http://www.scipy.org/Cookbook/Ctypes#head-4ee0c35d45f89ef959a7d77b94c1c973101a562f,arr.ctypes.shape [:] arr.ctypes.strides [:]和arr.ctypes.data是你的意思需要; 您可以將其直接提供給您的compute
。
這是一個例子:
In [55]: a = numpy.array([[0.0]*10]*2, dtype=numpy.float32)
In [56]: ctypes.cast(a.ctypes.data, ctypes.POINTER(ctypes.c_float))[0]
Out[56]: 0.0
In [57]: ctypes.cast(a.ctypes.data, ctypes.POINTER(ctypes.c_float))[0] = 1234
In [58]: a
Out[58]:
array([[ 1234., 0., 0., 0., 0., 0., 0., 0.,
0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0.]], dtype=float32)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.