Форум сайта python.su
Здравствуйте. Для проверки скорости и выбора средства для ускорения программы на Python Я пробую реализовать простой пример с двумя вложенными циклами.
Итак, два вложенных цикла от 1 до 10000 чисто на питоне на моей машине выполняются примерно за 4.5-5 секунд. С использованием Cython - 2.7-3.1. Чисто на С - 0.25-0.35.
Вот решил ещё попробовать написать сам с нуля модуль, вот смотрю на эти вещи:
https://docs.python.org/3/extending/extending.html
https://stackoverflow.com/questions/43621948/c-python-module-import-error-undefined-symbol-py-initmodule3-py-initmodu
А вот мой setup.py:
from distutils.core import setup, Extension setup(name='loops_lib', version='1.0', \ ext_modules=[Extension('loops_lib', ['loops_lib_for_python.c'])])
ImportError: loops_lib.cpython-35m-x86_64-linux-gnu.so: undefined symbol: Py_InitModule3
ImportError: dynamic module does not define module export function (PyInit_loops_lib)
#include<Python.h> static PyObject *nested_loops_2(PyObject *self, PyObject *args) { long int count1, count2; unsigned long long int counter; if (!PyArg_ParseTuple(args, "ll", &count1, &count2)) { return NULL; } counter = 0; for (int i=0; i<count1; i++) for (int j=0; j<count1; j++) counter += 1; return Py_BuildValue("llu", counter); } static char nested_loops_2_docs[] = "nested_loops_2( ): Run 2 nested loops and count iterations\n"; //static PyMethodDef nested_loops_2_funcs[] = { // {"nested_loops_2", (PyCFunction)nested_loops_2, // METH_VARARGS, nested_loops_2_docs}, // {NULL, NULL, 0, NULL} //}; static PyMethodDef module_methods[] = { {"nested_loops_2", (PyCFunction) nested_loops_2, METH_VARARGS, nested_loops_2_docs}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef struct_nested_loops_2 = { PyModuleDef_HEAD_INIT, "loops_lib", NULL, -1, module_methods }; //void init_nested_loops_2(void) { // Py_InitModule3("nested_loops_2", module_methods); //} //PyMODINIT_FUNC PyInit_nested_loops_2(void) //{ // return PyModule_Create(&struct_nested_loops_2); //}
Отредактировано Master_Sergius (Июль 19, 2017 18:09:39)
Офлайн
Если тут поменять
PyMODINIT_FUNC PyInit_loops_lib(void)
{
return PyModule_Create(&struct_nested_loops_2);
}
static PyObject *nested_loops_2(PyObject *self, PyObject *args) {
long int count1, count2;
unsigned long long int counter;
if (!PyArg_ParseTuple(args, "ll", &count1, &count2)) {
return NULL;
}
counter = 0;
for (int i=0; i<count1; i++)
for (int j=0; j<count1; j++)
counter += 1;
return Py_BuildValue("K", counter);
}
Офлайн
Да, так работает. А можно узнать где Вы это взяли? Должна же быть где-то нормальная и свежая документация. Что странно, так это то, что оно быстрее даже за чисто С-шный пример (или это Я такой С программер).
Насчёт Cython, loops_cython.pyx:
def nested_loops_2(count1, count2): counter = 0 for index1 in range(count1): for index2 in range(count2): counter += 1 return counter
from distutils.core import setup from Cython.Build import cythonize setup( name = 'nested loops', ext_modules = cythonize("loops_cython.pyx"), )
#!/usr/bin/env python3 import sys from loops_cython import nested_loops_2 print(nested_loops_2(int(sys.argv[1]), int(sys.argv[2])))
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { char *p; long int count1 = strtol(argv[1], &p, 10); long int count2 = strtol(argv[2], &p, 10); unsigned long long int counter = 0; for (int i=0; i<count1; i++) for(int j=0; j<count2; j++) counter++; printf("%llu\n", counter); return 0; }
Офлайн
Master_SergiusИз питоновской документации в основном. Полноценных туториалов не попадалось: чуть там урвал, чуть в другом месте. При этом приходится иметь в виду отличия в апи у разных версий питона.
А можно узнать где Вы это взяли?
cpdef unsigned long long nested_loops_2(long count1, long count2):
cdef long index1, index2
cdef unsigned long long counter = 0
for index1 in range(count1):
for index2 in range(count2):
counter += 1
return counter
static unsigned PY_LONG_LONG __pyx_f_3tst_nested_loops_2(long __pyx_v_count1, long __pyx_v_count2, CYTHON_UNUSED int __pyx_skip_dispatch) {
CYTHON_UNUSED long __pyx_v_index1;
CYTHON_UNUSED long __pyx_v_index2;
unsigned PY_LONG_LONG __pyx_v_counter;
unsigned PY_LONG_LONG __pyx_r;
__Pyx_RefNannyDeclarations
long __pyx_t_1;
long __pyx_t_2;
long __pyx_t_3;
long __pyx_t_4;
__Pyx_RefNannySetupContext("nested_loops_2", 0);
__pyx_v_counter = 0;
__pyx_t_1 = __pyx_v_count1;
for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {
__pyx_v_index1 = __pyx_t_2;
__pyx_t_3 = __pyx_v_count2;
for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
__pyx_v_index2 = __pyx_t_4;
__pyx_v_counter = (__pyx_v_counter + 1);
}
}
__pyx_r = __pyx_v_counter;
goto __pyx_L0;
__pyx_L0:;
__Pyx_RefNannyFinishContext();
return __pyx_r;
}
Офлайн
Да уж, скорость Cython теперь почти такая же, как и у расширения, с которым вот были проблемы. Единственное, что непонятно, как они отрабатывают быстрее за чисто С. Если С за 0.2 делает, то Cython и расширения за 0.1, что-то неверятное )
Офлайн