Trouble optimizing Boost.python integration
Hi, I'm trying to compare different python-C wrapping techniques to see which would be faster and also more suited to game development. I'm using Stackless Python 2.6.2 and boost 1.39.0. I implemented a simple Vec3 (3D vector) class in C++ and wrapped it with boost:python. All it does is multiplications and additions, so it implements just two operators. The thing is, it proves to be kind of slow compared to Cython/Pyrex code that does the same. I think it should run faster than Cython code. (Note: Cython is not an abbreviation for C/Python API) I compiled the python library from boost, in release mode, and then linked the vec3 module, provided below, to the compiled boost_python library. (I used -O2 when compiling the vec3 module) The testing goes like this: each "tick", 10000 objects update their position, according to their velocity and timedelta since last "tick", and I'm measuring the average time a tick takes to complete. On my machine doing this with Cython takes ~0.026 sec/tick, while doing it with boost.python takes like 0.052 sec/tick (The overhead introduced by python's iterating through the list of objects each tick is about 0.01 sec) During one tick, for each object, python runs this: "self.position += self.velocity * time_delta", where position and velocity are instances of Vec3. I was hoping for results better than with Cython, by using Boost. Am I doing something wrong? Source code: vec3.cpp ========== #include <boost/python.hpp> using namespace boost::python; class Vec3 { float x, y, z; public: Vec3(float x, float y, float z); Vec3 &operator*=(float scalar); Vec3 operator*(float scalar) const; Vec3 &operator+=(const Vec3 &who); // that `const Vec3` is REALLY needed, unless you want error monsoon to come down }; // === boost:python wrapper === // publish just += and * to python BOOST_PYTHON_MODULE(vec3) { class_<Vec3>("Vec3", init<float, float, float>()) .def(self += self) .def(self * float()) ; } // === implementation === Vec3::Vec3(float x, float y, float z) { this->x = x; this->y = y; this->z = z; } Vec3 & Vec3::operator*=(float scalar) { this->x *= scalar; this->y *= scalar; thiz->z *= scalar;a } Vec3 Vec3::operator*(float scalar) const { return Vec3(*this) *= scalar; } Vec3 & Vec3::operator+=(const Vec3 &who) { this->x += who.x; this->y += who.y; this->z += who.z; return *this; }
On Tuesday 25 August 2009 23:48:02 Dan Sanduleac wrote:
The thing is, it proves to be kind of slow compared to Cython/Pyrex code that does the same. I think it should run faster than Cython code.
I think this is because your vectors are too small. I think for such small objects, the implementation of vector operations is much faster than the overhead of BPL's argument/return type conversion, and the latter accounts for the slowdown. HTH, Hans
2009/8/25 Dan Sanduleac <sanduleac.dan@gmail.com>
Hi,
I'm trying to compare different python-C wrapping techniques to see which would be faster and also more suited to game development.
If your project does not use multiple inheritance, I may suggest you also try with PyBindGen: http://code.google.com/p/pybindgen/ Yes, me being the pybindgen author, I am biased, but still... I am curious to comparisons of pybindgen performance to other python wrapping tools. Regards, -- Gustavo J. A. M. Carneiro INESC Porto, Telecommunications and Multimedia Unit "The universe is always one step beyond logic." -- Frank Herbert
On 09/08/2009 10:51 AM, Gustavo Carneiro wrote:
2009/8/25 Dan Sanduleac <sanduleac.dan@gmail.com <mailto:sanduleac.dan@gmail.com>>
Hi,
I'm trying to compare different python-C wrapping techniques to see which would be faster and also more suited to game development.
If your project does not use multiple inheritance, I may suggest you also try with PyBindGen: http://code.google.com/p/pybindgen/
Yes, me being the pybindgen author, I am biased, but still... I am curious to comparisons of pybindgen performance to other python wrapping tools.
That's a strange line of argument. Didn't the original poster ask for advice ? It's your turn to do your homework and show why using PyBindGen is the better choice, instead of inviting people to use it and report back to you whether it was any good. :-) Stefan -- ...ich hab' noch einen Koffer in Berlin...
2009/9/8 Stefan Seefeld <seefeld@sympatico.ca>
On 09/08/2009 10:51 AM, Gustavo Carneiro wrote:
2009/8/25 Dan Sanduleac <sanduleac.dan@gmail.com <mailto: sanduleac.dan@gmail.com>>
Hi,
I'm trying to compare different python-C wrapping techniques to see which would be faster and also more suited to game development.
If your project does not use multiple inheritance, I may suggest you also try with PyBindGen: http://code.google.com/p/pybindgen/
Yes, me being the pybindgen author, I am biased, but still... I am curious to comparisons of pybindgen performance to other python wrapping tools.
That's a strange line of argument. Didn't the original poster ask for advice ? It's your turn to do your homework and show why using PyBindGen is the better choice, instead of inviting people to use it and report back to you whether it was any good.
Hm.. but each person knows best the environment they work for. It would be presumptuous of me to tell him pybindgen is the better choice. I don't have the full benchmarking setup, but here's how to wrap that example (attached). I had to add a default Vec3 constructor, since pybindgen does not like very much classes without default constructors. You generate the module with: python vec3-gen.py > vec3module.cc Compile with something like: g++ -O2 -fPIC -shared -I /usr/include/python2.6 vec3module.cc vec3.cpp -o vec3.so As for the benchmarking stuff, I leave to the original poster. -- Gustavo J. A. M. Carneiro INESC Porto, Telecommunications and Multimedia Unit "The universe is always one step beyond logic." -- Frank Herbert
participants (4)
-
Dan Sanduleac -
Gustavo Carneiro -
Hans Meine -
Stefan Seefeld