Cython не может предоставить конструктор python range
для std::vector
напрямую.Он должен сначала создать буфер range
как объект python, а затем преобразовать / заполнить его в std::vector
.(В основном звоните __Pyx_PyObject_Call
, а затем __pyx_convert_vector_from_py_double
).Следовательно, переписать функцию createobj
следующим образом:
cpdef createobjNEW(int num):
cdef Obj* obj
cdef cpp_vector[Obj*] pool
pool.reserve(num)
cdef int i, j, cnt = 1000
for i in range(num):
obj=new Obj()
obj.pxlmead.reserve(cnt)
obj.pxlstd.reserve(cnt)
for j in range(cnt):
obj.lind[0].push_back(j)
obj.pxlmead.push_back(j)
obj.pxlstd.push_back(j)
obj.pxlcnt=cnt
obj.bandcnt=<int>sqrt(10000)
pool.push_back(obj)
Время:
На моей машине с Python 2.7 с вышеупомянутыми изменениями я получаю
In[0]: %timeit pcreateobj(10000) # python version
1 loop, best of 3: 468 ms per loop
In[0]: %timeit createobj(10000) # original cython version
1 loop, best of 3: 3.74 s per loop
In[1]: %timeit createobjNEW(10000) # modified cython function
1 loop, best of 3: 1.07 s per loop
Обратите внимание, что способ создания std::map
с pair[int,cpp_list[int]]
в cython не такой оптимальный / легкий, как создание списков в python.Вместо этого вы должны использовать вектор:
ctypedef cpp_map[int,cpp_vector[int]] coordslind
С этим изменением я получу
In[2]: %timeit createobjNEW(10000)
1 loop, best of 3: 257 ms per loop
По крайней мере, по скорости это приведет вас к земле C ++.Дальнейшая оптимизация / настройка производительности для этой функции связана с C ++, и Cython ничего не может сделать.Например, вы можете разместить в стеке свой экземпляр Obj
и иметь cpp_vector[Obj]
вместо cpp_vectorpool[Obj*]
.В моей машине это приводит к тому, что время выполнения функции увеличивается почти вдвое (114 ms
).
Также обратите внимание, что в Python 3 range
s являются генераторами и не создаютфактический список значений, тогда как в C ++ вы создаете векторы вручную.