C
Chris
Hi,
I'd like to be able to access an attribute of a particular Python
object as fast as possible from some C code.
I wondered if using __slots__ to store the attribute would allow me to
do this in a faster way.
The reason I'd like to do this is because I need to access the
attribute inside a loop within some C code, and I find that the
attribute lookup using the 'PyObject_GetAttrString' call is far slower
than any of the subsequent calculations I perform in C.
Using the 'PyObject_GetAttrString' function to get the attribute, I
find it is slightly faster when the attribute is a slot than when it
isn't, but that the attribute lookup remains the performance-limiting
factor.
Additionally, if I instead build a list of the attributes first and
pass that to the C code, using the 'PyList_GetItem' function to access
each item, the performance improves significantly. I'd rather be able
to access the information from C, instead of building the list
externally.
As far as I can tell, nothing is documented about accessing __slot__
members in a special way from C, but perhaps someone knows how to do
it anyway?
To be more specific, below is an example of what I'm talking about. I
use SciPy's weave to inline C code, but I assume that doesn't make any
difference to my problem.
Thanks for any suggestions,
Chris
class MyObject(object):
__slots__ = ['attr_one']
def __init__(self,attr_one=1.0):
self.attr_one = attr_one
import weave
def test_loop(myobjects):
rows,cols = len(myobjects),len(myobjects[0])
code = """
for (int r=0; r<rows; ++r) {
PyObject *myobjects_row = PyList_GetItem(myobjects,r);
for (int l=0; l<cols; ++l) {
PyObject *myobject = PyList_GetItem(myobjects_row,l);
// any faster way when attr_one is a slot?
PyObject *attr_one_obj=PyObject_GetAttrString(myobject,"attr_one");
// more computations involving attr_one; just print for now...
double attr_one = PyFloat_AsDouble(attr_one_obj);
printf("%f\\n",attr_one);
}
}
"""
weave.inline(code,['myobjects','rows','cols'],local_dict=locals(),verbose=1)
test_list = [[MyObject(0.0),MyObject(1.0)],[MyObject(2.0),MyObject(3.0)]]
test_loop(test_list)
I'd like to be able to access an attribute of a particular Python
object as fast as possible from some C code.
I wondered if using __slots__ to store the attribute would allow me to
do this in a faster way.
The reason I'd like to do this is because I need to access the
attribute inside a loop within some C code, and I find that the
attribute lookup using the 'PyObject_GetAttrString' call is far slower
than any of the subsequent calculations I perform in C.
Using the 'PyObject_GetAttrString' function to get the attribute, I
find it is slightly faster when the attribute is a slot than when it
isn't, but that the attribute lookup remains the performance-limiting
factor.
Additionally, if I instead build a list of the attributes first and
pass that to the C code, using the 'PyList_GetItem' function to access
each item, the performance improves significantly. I'd rather be able
to access the information from C, instead of building the list
externally.
As far as I can tell, nothing is documented about accessing __slot__
members in a special way from C, but perhaps someone knows how to do
it anyway?
To be more specific, below is an example of what I'm talking about. I
use SciPy's weave to inline C code, but I assume that doesn't make any
difference to my problem.
Thanks for any suggestions,
Chris
class MyObject(object):
__slots__ = ['attr_one']
def __init__(self,attr_one=1.0):
self.attr_one = attr_one
import weave
def test_loop(myobjects):
rows,cols = len(myobjects),len(myobjects[0])
code = """
for (int r=0; r<rows; ++r) {
PyObject *myobjects_row = PyList_GetItem(myobjects,r);
for (int l=0; l<cols; ++l) {
PyObject *myobject = PyList_GetItem(myobjects_row,l);
// any faster way when attr_one is a slot?
PyObject *attr_one_obj=PyObject_GetAttrString(myobject,"attr_one");
// more computations involving attr_one; just print for now...
double attr_one = PyFloat_AsDouble(attr_one_obj);
printf("%f\\n",attr_one);
}
}
"""
weave.inline(code,['myobjects','rows','cols'],local_dict=locals(),verbose=1)
test_list = [[MyObject(0.0),MyObject(1.0)],[MyObject(2.0),MyObject(3.0)]]
test_loop(test_list)