Extending & Embedding Python Using C - Pi |
Written by Mike James | |||
Monday, 02 October 2023 | |||
Page 1 of 2 Discover what goes into coding a Python extension module and see how fast C is when compared to Python by using it to compute Pi. Extending & Embedding Python Using CBy Mike JamesBuy from Amazon. ContentsPreface
<ASIN:B0CK3X93KF> In chapter but not in this extract
Computing Pi – How Fast?As a second simple example, we can use a very simple computation to demonstrate the potential speed advantages that a C extension module offers. You can compute pi using the very simple series: pi = 4*(1-1/3+1/5-1/7 ... ) This is very easy to implement, we just need to generate the odd integers, but to get pi to a reasonable number of digits you have to compute a lot of terms. In other words, this series is very slow to converge. The simple-minded approach is to write something like: import time def myPi(m,n): pi=0 for k in range(m,n+1): s= 1 if k%2 else -1 pi += s / (2 * k - 1) return 4*pi This computes the sum from m to n. A main program to make use of this function is: if __name__ == '__main__': N=10000000 t1=time.perf_counter() pi=myPi(1,N) t2=time.perf_counter() print((t2-t1)*1000) print(pi) If you try this out you will find that it gives pi to about five digits, which is not good for so many terms, but it is a good example to convert to a C extension. The details of initializing the module follow the usual steps and the function is a fairly obvious translation of the Python: #define PY_SSIZE_T_CLEAN #include <Python.h> static PyObject * Pi(PyObject *self, PyObject *args) { int m, n; double pi,s; if (!PyArg_ParseTuple(args, "ii", &m, &n)) return NULL; pi=0; for(int k=m;k<n;k++){ s=1; if(k%2==0)s=-1; pi=pi+s/(2*k-1); } return PyFloat_FromDouble(4*pi); } static PyMethodDef AddMethods[] = { {"myPi", Pi, METH_VARARGS, "Compute Pi"}, {NULL, NULL, 0, NULL} // sentinel }; static struct PyModuleDef addmodule = { PyModuleDef_HEAD_INIT, "Pi", "C library to compute Pi", -1, AddMethods }; PyMODINIT_FUNC PyInit_Pi(void) { return PyModule_Create(&addmodule); } The only real changes are to the names used for the module and function. Task.json also needs to be updated. The args for Windows is: "args": [ "/Zi", "/EHsc", "/nologo", "/IC:/Users/user/AppData/Local/Programs /Python/Python311/include", "${file}", "/link /dll /OUT:Pi.pyd /LIBPATH:C:/Users/user/AppData/Local/ Programs/Python/Python311/libs" For Linux it is: "args": [ With these changes the module should compile. If not go back to the instructions in chapters 2 and 3. |
|||
Last Updated ( Monday, 02 October 2023 ) |