Я использую ctypes, чтобы попытаться ускорить мой код.
Моя проблема похожа на ту, которая описана в этом уроке: https://cvstuff.wordpress.com/2014/11/27/wraping-c-code-with-python-ctypes-memory-and-pointers/
Как указано в уроке, я должен освободитьпамять после использования функции C.Вот мой код C
//C functions
double* getStuff(double *R_list, int items){
double results[items];
double* results_p;
for(int i = 0; i < items; i++){
res = calculation ; \\do some calculation
results[i] = res; }
results_p = results;
printf("C allocated address %p \n", results_p);
return results_p; }
void free_mem(double *a){
printf("freeing address: %p\n", a);
free(a); }
, который я компилирую с gcc -shared -Wl,-lgsl,-soname, simps -o libsimps.so -fPIC simps.c
И python:
//Python
from ctypes import *
import numpy as np
mydll = CDLL("libsimps.so")
mydll.getStuff.restype = POINTER(c_double)
mydll.getStuff.argtypes = [POINTER(c_double),c_int]
mydll.free_mem.restype = None
mydll.free_mem.argtypes = [POINTER(c_double)]
R = np.logspace(np.log10(0.011),1, 100, dtype = float) #input
tracers = c_int(len(R))
R_c = R.ctypes.data_as(POINTER(c_double))
for_list = mydll.getStuff(R_c,tracers)
print 'Python allocated', hex(for_list)
for_list_py = np.array(np.fromiter(for_list, dtype=np.float64, count=len(R)))
mydll.free_mem(for_list)
До последней строки код делает то, что я хочуэто и for_list_py
значения являются правильными.Однако, когда я пытаюсь освободить память, я получаю ошибку сегментации , и при ближайшем рассмотрении адрес, связанный с for_list
-> hex(for_list)
, отличается от адреса, выделенного для results_p
в C-частикод.
Как указано в этом вопросе, Python ctypes: как освободить память?Ошибка неверного указателя , for_list
вернет тот же адрес, если для mydll.getStuff.restype
установлено значение c_void_p
.Но затем я изо всех сил пытаюсь поместить фактические значения, которые я хочу, в for_list_py
.Вот что я пробовал: cast (for_list, POINTER (c_double)) for_list_py = np.array (np.fromiter (for_list, dtype = np.float64, count = len (R))) mydll.free_mem (for_list) , где, похоже, операция приведения превращает for_list в целое число. Я довольно плохо знаком с C и очень растерялся.Нужно ли освободить этот кусок памяти?Если это так, как мне это сделать, сохраняя при этом вывод в виде массива?Спасибо!
Редактировать: Похоже, что адрес, выделенный в C, и адрес, который я пытаюсь освободить, совпадают, хотя я все еще получаю ошибку сегментации.
C allocated address 0x7ffe559a3960
freeing address: 0x7ffe559a3960
Segmentation fault
Если я получу print for_list
Я получу <__main__.LP_c_double object at 0x7fe2fc93ab00>
Заключение
Просто чтобы все знали, я боролся сc_types для немного.
В итоге я выбрал SWIG вместо c_types.Я обнаружил, что код в целом работает быстрее (по сравнению с представленной здесь версией).Я нашел эту документацию по работе с освобождением памяти в SWIG очень полезной https://scipy -cookbook.readthedocs.io / items / SWIG_Memory_Deallocation.html , а также тот факт, что SWIG дает вам очень простой способ справиться сnumpy n-мерных массивов.