I need to call a Python function from my C code. It works perfectly, but when I want to do parallelization, it breaks down. Please see the following minimal C code:
#include <Python.h>
#include <stdio.h>
int main(void)
{
double Z = 1.;
double k = 1.;
double l = 1.;
double eta = -Z/k;
Py_Initialize();
PyObject* pName = PyString_FromString("mpmath");
PyObject* pModule = PyImport_Import(pName);
PyObject* pFunc = PyObject_GetAttrString(pModule, "coulombf");
PyObject* pl = PyFloat_FromDouble(l);
PyObject* peta = PyFloat_FromDouble(eta);
int i;
#pragma omp parallel for private(i)
for(i=0; i<10000; i++)
{
double r = 0.01*i;
PyObject* prho = PyFloat_FromDouble(k*r);
PyObject* pArgs = PyTuple_Pack(3, pl, peta, prho);
PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
double value = PyFloat_AsDouble(pValue);
printf("r=%.2f\tf=%.6f\n",r,value);
}
Py_Finalize();
return 0;
}
Let's name this file as testPython.c
, you can compile it with gcc -fopenmp testPython.c -o testPython -I/usr/include/python2.7 -L/usr/lib64/python2.7/config -lpython2.7
.
Now run it with ./testPython
, you with see such error: Fatal Python error: GC object already tracked
. (Sometimes, the error info differs.)
But if you compile it leaving -fopenmp
out, the program works perfectly.
How can I overcome this problem? Thanks!
Edit:
As answered by Natecat, John Bollinger, and Olaf, multithreading is unlikely to speed up the process much, but multiprocessing can really speed up the computation. The pure python script is as simple as following:
import numpy
from mpmath import coulombf
from multiprocessing import Pool
Z = 1.
k = 1.
l = 1.
eta = -Z/k
def coulombF(r):
return coulombf(l,eta,k*r)
pool = Pool(12)
result = pool.map_async(coulombF, numpy.arange(0.,100.,0.01))
print(result.get())
But how do I do it in C? I haven't found the way yet.