473,548 Members | 2,716 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Accessing =?utf-8?b?X19zbG90c19 f?= from C

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_GetAt trString' call is far slower
than any of the subsequent calculations I perform in C.

Using the 'PyObject_GetAt trString' 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,a ttr_one=1.0):
self.attr_one = attr_one
import weave
def test_loop(myobj ects):

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=P yObject_GetAttr String(myobject ,"attr_one") ;

// more computations involving attr_one; just print for now...
double attr_one = PyFloat_AsDoubl e(attr_one_obj) ;
printf("%f\\n", attr_one);
}
}
"""
weave.inline(co de,['myobjects','ro ws','cols'],local_dict=loc als(),verbose=1 )
test_list = [[MyObject(0.0),M yObject(1.0)],[MyObject(2.0),M yObject(3.0)]]

test_loop(test_ list)
Sep 10 '08 #1
10 1592
[ You can use the capi-sig for questions like this; see
http://mail.python.org/mailman/listinfo/capi-sig ]

Chris <ce****@users.s ourceforge.netw rites:
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_GetAt trString' call is far slower
than any of the subsequent calculations I perform in C.
PyObject_GetAtt rString is convenient, but it creates a Python string
only so it can intern it (and in most cases throw away the freshly
created version). For maximum efficiency, pre-create the string
object using PyString_Intern FromString, and use that with
PyObject_GetAtt r.
Sep 11 '08 #2
Hrvoje Niksic <hniksic <atxemacs.orgwr ites:
....
[ You can use the capi-sig for questions like this; see
http://mail.python.org/mailman/listinfo/capi-sig ]
Thanks, I had no idea about that.
PyObject_GetAtt rString is convenient, but it creates a Python string
only so it can intern it (and in most cases throw away the freshly
created version). For maximum efficiency, pre-create the string
object using PyString_Intern FromString, and use that with
PyObject_GetAtt r.
Yes, we'd thought of that too, but it doesn't seem to be an important
factor compared to the actual attribute lookup.

Thanks for the advice,
Chris

Sep 11 '08 #3
On Sep 10, 7:41 am, Chris <ceb...@users.s ourceforge.netw rote:
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_GetAt trString' call is far slower
than any of the subsequent calculations I perform in C.

Using the 'PyObject_GetAt trString' 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.
You can determine the offset the of the slot in the object structure
by
querying the member descriptor of the type object.

descr = GetAttrString(c ls,"varname");
offset = descr->d_member->offset;
slotvar = (PyObject*)(((c har*)obj)+offse t)

There might be some macros to simplify this.

Use at your own risk.
Carl Banks
Sep 11 '08 #4
Carl Banks <pavloveviden ce <atgmail.comwri tes:
....
You can determine the offset the of the slot in the object structure
by
querying the member descriptor of the type object.
That sounds like just the kind of thing we were looking for - thanks!
descr = GetAttrString(c ls,"varname");
offset = descr->d_member->offset;
slotvar = (PyObject*)(((c har*)obj)+offse t)
Unfortunately, I am inexperienced at this kind of thing, so I wasn't
able to get something working. Maybe someone could tell me what's
wrong with the code below (it gives the error "'struct _object' has no
member named 'd_member'")?

PyObject *descr = PyObject_GetAtt rString(x,"attr _one");
int offset = descr->d_member->offset;
PyObject* slotvar = (PyObject*)(((c har*)obj)+offse t);

where x is the class and attr_one is a slot (the full example is
appended to this message). I guessed the type of offset; I'm not sure
what it should be.

I couldn't find any information about d_member on the web.

There might be some macros to simplify this.
Sorry to say that I also have no idea about where to find such macros!
Maybe I should continue this thread on capi-sig?
Thanks for your help,
Chris
class MyObject(object ):

__slots__ = ['attr_one']

def __init__(self,a ttr_one=1.0):
self.attr_one = attr_one

import weave
def test():

x = MyObject

code = """
PyObject *descr = PyObject_GetAtt rString(x,"attr _one");
int offset = descr->d_member->offset;
//PyObject* slotvar = (PyObject*)(((c har*)obj)+offse t);
"""
weave.inline(co de,['x'],local_dict=loc als(),verbose=1 )

test()
Sep 12 '08 #5
Hrvoje Niksic <hniksic <atxemacs.orgwr ites:
....
Chris <ceball <atusers.source forge.netwrites :
PyObject_GetAtt rString is convenient, but it creates a Python string
only so it can intern it (and in most cases throw away the freshly
created version). For maximum efficiency, pre-create the string
object using PyString_Intern FromString, and use that with
PyObject_GetAtt r.
Yes, we'd thought of that too, but it doesn't seem to be an
important factor compared to the actual attribute lookup.

I'd like to see your test code.
Thanks for your interest in this. My test code is a whole function
that's part of a big simulator, unfortunately! I need to use the data
structures created by the simulator as part of the testing. While the
source is freely available*, that doesn't make it easy for others to
run the tests...

In my experience, as long as you're
accessing simple slots, you should notice a difference.
(I'm not sure what you mean by a 'simple slot'. The slot we're
accessing is a numpy array.)

Sorry I wasn't clear before - we do notice a difference, but not as
big a difference as when we access the attributes (arrays) from a
pre-built list. Below are timings from running the simulator
(i.e. calling the function in question many times) using the three
approaches (GetAttrString, GetAttr, and instead using a list and
GetItem; times outside parentheses are from a stopwatch; times in
parentheses are from Python's cProfile module):
- GetAttrString: 55 seconds (58 seconds)
inside the loop:
PyObject *weights_obj = PyObject_GetAtt rString(obj,"at tr_one");
- GetAttr: 46 seconds (46 seconds)
outside the loop:
PyObject *name = PyString_FromSt ring("attr_one" );

inside the loop:
PyObject *obj = PyObject_GetAtt r(obj,name);
- PyList_GetItem: 35 seconds (37 seconds)
So, of course, you are right to say that we should notice a
difference! But speed is critical for us here.

Incidentally, what we have is a simulator written entirely in Python,
but we also provide optimized C versions of some parts of it. These C
parts must be entirely optional.

Here is a test program that shows a 4.6 time speedup simply by
switching from PyObject_GetAtt rString to PyObject_GetAtt r:
Thanks for the illustration. While I didn't run your code myself,
I did try to study it. Illustrations like that are very helpful.
Chris
* from http://topographica.org/

Sep 12 '08 #6
Chris <ce****@users.s ourceforge.netw rites:
>In my experience, as long as you're
accessing simple slots, you should notice a difference.

(I'm not sure what you mean by a 'simple slot'.
I mean a slot defined by __slots__ = slot1, slot2, slot3, ..., without
descriptors or specific __getattribute_ _ code on top of that.
- GetAttr: 46 seconds (46 seconds)
outside the loop:
PyObject *name = PyString_FromSt ring("attr_one" );
I think you should be using PyString_Intern FromString, but it will
probably still be slower than PyList_GET_ITEM , which is still much
simpler. The next optimization is the one proposed by Carl, which
should yield speed comparable to PyList_GET_ITEM . See my response in
that subthread for details.
Sep 12 '08 #7
Chris <ce****@users.s ourceforge.netw rites:
>descr = GetAttrString(c ls,"varname");
offset = descr->d_member->offset;
slotvar = (PyObject*)(((c har*)obj)+offse t)

Unfortunately, I am inexperienced at this kind of thing, so I wasn't
able to get something working. Maybe someone could tell me what's
wrong with the code below (it gives the error "'struct _object' has no
member named 'd_member'")?
You are getting that error because Carl forgot to cast the descriptor
to the appropriate C type, in this case PyMemberDescrOb ject. The last
line is also incorrect, I think. Try something like this:

PyObject *descr = PyObject_GetAtt rString(x,"attr _one");
int offset = ((PyMemberDescr Object *) descr)->d_member->offset;
PyObject *slotvar = *(PyObject **)(((char *) obj) + offset);
Sep 12 '08 #8
Hrvoje Niksic <hn*****@xemacs .orgwrites:
Chris <ce****@users.s ourceforge.netw rites:
>>descr = GetAttrString(c ls,"varname");
offset = descr->d_member->offset;
slotvar = (PyObject*)(((c har*)obj)+offse t)

Unfortunatel y, I am inexperienced at this kind of thing, so I wasn't
able to get something working. Maybe someone could tell me what's
wrong with the code below (it gives the error "'struct _object' has no
member named 'd_member'")?

You are getting that error because Carl forgot to cast the descriptor
to the appropriate C type, in this case PyMemberDescrOb ject. The last
line is also incorrect, I think. Try something like this:

PyObject *descr = PyObject_GetAtt rString(x,"attr _one");
Also note that x should be your object's type, i.e. o->ob_type cast to
PyObject *. The complete incantation would be:

// outside the loop
PyObject *descr = PyObject_GetAtt rString((PyObje ct *) obj->ob_type,
"attr_one") ;
if (!descr)
return NULL;
int offset = ((PyMemberDescr Object *) descr)->d_member->offset;
Py_DECREF(descr );

// inside the loop
PyObject *value = *(PyObject **)((char *)obj + offset);
if (!value) {
PyErr_SetString (PyExc_Attribut eError, "attribute missing");
return NULL;
}
// Remember to Py_INCREF(value ) before using it and Py_DECREF it after
// using it. Otherwise if the object changes its slot to something
// else, you might be using a dead object.

With this code, accessing the value is practically free once the
offset is calculated. Here is a bench3 function updated to use this
strategy:

static PyObject *
bench3(PyObject *ignored, PyObject *obj)
{
PyObject *descr = PyObject_GetAtt rString((PyObje ct *) obj->ob_type,
"abcdef");
if (!descr)
return NULL;

// Here you should also assert that PyObject_TypeCh eck(descr,
// PyMemberDescr_T ype) holds true. Since PyMemberDescr_T ype is static,
// you'll have to get it by stashing away ob_type of a value known to be
// the descriptor. This is left as excercise to the reader.

int offset = ((PyMemberDescr Object *) descr)->d_member->offset;
Py_DECREF(descr );

int i;
PyObject *volatile attr; // 'volatile' for benchmarking, prevents gcc
// from optimizing away the loop
for (i = 0; i < 1000000; i++) {
attr = *(PyObject **)((char *)obj + offset);
}
Py_INCREF(attr) ;
return attr; // to prove that we retrieved the correct value
}
>>t0 = time.time(); attr.bench3(o); t1 = time.time()
1
>>t1-t0
0.0007159709930 4199219 # for 1,000,000 iterations, as cheap as it gets
Sep 12 '08 #9
On Sep 12, 10:01*am, Hrvoje Niksic <hnik...@xemacs .orgwrote:
Chris <ceb...@users.s ourceforge.netw rites:
descr = GetAttrString(c ls,"varname");
offset = descr->d_member->offset;
slotvar = (PyObject*)(((c har*)obj)+offse t)
Unfortunately, I am inexperienced at this kind of thing, so I wasn't
able to get something working. Maybe someone could tell me what's
wrong with the code below (it gives the error "'struct _object' has no
member named 'd_member'")?

You are getting that error because Carl forgot to cast the descriptor
to the appropriate C type, in this case PyMemberDescrOb ject. *The last
line is also incorrect, I think.
Yep, was in too much of a hurry to waste too much time showing how to
do something slightly dubious.

The offsetof() macro would help for the third line (in fact, it's the
recommended standard way since there are some C implmentions,
somewhere, that the pointer artithmetic method fails).
Carl Banks
Sep 12 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
2240
by: George Grodentzik | last post by:
I created a typed dataset from which I am trying to access the data. When I use the following code to access a row string name =dataset.person.firstName I receive an error System.IndexOutOfRangeException as if there are no rows. Yet when I dump the data to a file I receive (sample of file) <?xml version="1.0" standalone="yes"?><Dataset1...
4
15182
by: Bradley Grant | last post by:
Does anyone out there know of where I could find some C# example programs for accessing USB Devices. There just does not seem to be much out there on this subject. Even after doing a Google, Yahoo, Lycos search engines. Any feed back would be appreciate. Bradley
6
1748
by: Charlie | last post by:
Hi: The code to add items to shopping cart is a seperate class file so I don't have to keep repeating it. If I want to be able to access session data in this class, which class should I base it on? Thanks, Charlie
0
1049
by: Remco | last post by:
I am having troubles accessing an asp.net mobile web application. When I run the page on my wap-enabled mobile phone (or with an wap emulator like www.wapsilon.com), I get an error message saying: Wrong mime-type, I got text/html; charset=utf-8, but I want text/vnd.wap.wml. When I make an simple .asp file (with Response.ContentType =...
0
2249
by: Joergen Bech | last post by:
Fairly new to ASP.NET 1.1. Getting the error below when running application on a web server outside of my control, but only the first time I run it: 1. After a long period of inactivity (or updating the code-behind dll) accessing any aspx page in the application causes the application to run for the first time. Some of the initialization...
5
3040
by: Daniel Corbett | last post by:
I am trying to save a file dynamically created in a webpage. I get the following headers, but cannot figure out how to save the attachment. I am basically trying to replicate what internet explorer would do in this case. The headers I am getting are: Headers {Content-Disposition: attachment; filename="dynamic_file.mdb" Connection:...
0
1494
by: Doug Caldwell | last post by:
Hi! ** Accessing the USGS Web Service Using Python ** I am trying to access the US Geological Survey's gazetteer SOAP web service using Python to find the locations of all the places with the name 'Alexandria.' I tried to keep this simple by putting a soap message in a string and sending the request using httplib. I am receiving the...
4
1965
by: SteveT | last post by:
I am wanting to populate several treeviews, one for the <TRs> group and one for the <TGsgroup. Is there a simplier way to populate the Treeview than the one I did below? It seems difficult to get to the correct DataSet values. <?xml version="1.0" encoding="utf-8" ?> <TestSample> <TRs> <TR1>
1
1123
by: Christian Heimes | last post by:
Peter Robinson schrieb: As John already said: UTF-8 ain't unicode. UTF-8 is an encoding similar to ASCII or Latin-1 but different in its inner workings. A single character may be encoded by up to 6 bytes. I highly recommend Joel's article on unicode: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About...
1
5955
Plater
by: Plater | last post by:
I have a webservice that claims the following: SOAP 1.1 The following is a sample SOAP 1.1 request and response. The placeholders shown need to be replaced with actual values. POST /testdb/UnitReporting.asmx HTTP/1.1 Host: localhost Content-Type: text/xml; charset=utf-8 Content-Length: length SOAPAction:...
0
7444
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7954
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7467
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7805
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6039
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
3497
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3478
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1932
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
755
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.