Использование объектов Python в C++
Я пишу код, который вычисляет изображения нелинейных карт с использованием методов анализа интервалов, применяет сумму Минковского и повторяет для произвольного числа итераций.
Я написал рабочий код на Python, однако я хотел бы иметь возможность реализовать некоторые из более интенсивных итерационных / рекурсивных частей алгоритма в C++, чтобы получить выгоду от увеличенной скорости. Я использовал Cython в прошлом с отличными результатами, но я хотел бы попрактиковаться в C++.
Кроме того, мои объекты достаточно сложны, поэтому я бы предпочел избежать их реализации в C++ (детка!).
Итак, мои вопросы:
1) Предотвращает ли использование объектов Python в C++ какое-либо улучшение эффективности?
2) Если нет, возможно ли использовать Cython для переноса функции C++, которая повторяет / рекурсирует объект python?
Чтобы быть более конкретным, у меня есть рекурсивный алгоритм, который рекурсивно обрабатывает левый и правый дочерние элементы BST (хотя это довольно сильно модифицированный BST, поэтому я бы не стал увязать в деталях его реализации в C++), однако время выполнения довольно запредельное, поэтому я бы хотел написать его на C++.
1 ответ
Да. Вы получите ускорение по сравнению с чистым питоном, но не на уровне увеличения, которое вы получите, если будете использовать чистый C/C++
, Если вы хотите обрабатывать объекты Python, вам нужно сделать это через Python C/API
; это увеличивает накладные расходы на выполнение, цену, которую вы должны заплатить за разрешение взаимодействовать с Python.
Обратите внимание, что это сопряжено с большой сложностью, поскольку вам необходимо ознакомиться с API и узнать, что функции делают со ссылками на объекты, как создавать списки, упаковать Tuples и так далее. Вы можете пропустить все это, если вы просто создадите пару public
Cythoncdef
функции, которые обертывают методы на ваших объектах. Это создает все CPython
код, который обрабатывает это для вас.
Небольшой пример, в котором глупый объект оборачивается и внедряется, может выглядеть следующим образом (обратите внимание, я использую.c
за это,c++
имеет аналогичные шаги):
class PyClass(object):
def __init__(self):
self.data = []
def add(self, val):
self.data.append(val)
def __str__(self):
return "Data: " + str(self.data)
cdef public object createPyClass():
return PyClass()
cdef public void addData(object p, int val):
p.add(val)
cdef public char* printCls(object p):
return bytes(str(p), encoding = 'utf-8')
Компилирование сcython pycls.pyx
(использование--cplus
за c++
) будет генерировать .c
а также .h
файл, содержащий объявления источника и функции соответственно. Все, что вам нужно сделать сейчас, это создать main.c
файл, который запускает Python, и вы готовы вызывать эти функции:
#include "Python.h" // Python.h always gets included first.
#include "pycls.h" // Include your header file.
int main(int argc, char *argv[])
{
Py_Initialize(); // initialize Python
PyInit_pycls(); // initialize module (initpycls(); in Py2)
PyObject *obj = createPyClass();
for(int i=0; i<10; i++){
addData(obj, i);
}
printf("%s\n", printCls(obj));
Py_Finalize();
return 0;
}
Компилируя это с правильными флагами (которые вы можете получить отpython3.5-config
изpython-config
[Py2]):
gcc pycls.c main.c -L$(python3.5-config --cflags) -I$(python3.5-config --ldflags) -std=c99
Создадим ваш исполняемый файл, который взаимодействует с вашим объектом:
./a.out
Data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Все это делается с помощьюCython
вместе сpublic
Ключевое слово, которое генерирует .h
заголовочный файл В качестве альтернативы вы можете просто скомпилировать модуль Python с помощью Cython и создать заголовок / обработать дополнительный шаблон самостоятельно. Так как я не думаю, что вы хотите быть ошеломленным C-API
обучение, это не должен быть путь.
Как пишет @freakish в своем комментарии, было бы идеально извлечь данные (numpy
имеетC-API
вы можете использовать для этого) и работать над этим в чистом виде C++
, Как правило, если вы работаете ваши петли в C/C++
и выполняйте тяжелую работу там, вы получите хорошие ускорения.