I need write std.vector variables into a new TTree. But it seems that in PyRoot calling std.vector methods in such as clear and push_back are very slow, in contract with the speed in C++. Any way to speed up calling std.vector methods or alternative fast way to do the same job?
yes, in C++ the push_back() method is, modulo the memory allocation, basically fully inlined into a straight memory copy of the value into the proper location in the vector. In Python, there’s the unboxing of variables, and then all the calls through (and setup of) the stub functions of the dictionary.
Only thing I can offer today, is PyPy/cppyy with the CINT backend. It’ll still use stub functions (won’t disappear until Cling; we can do w/o stubs with Reflex, but Reflex does not work with ROOT I/O). That’s significantly faster, but cppyy isn’t feature complete yet, so you can’t use it for graphics for example (will crash at some point during the session with high likelihood due to thread conflicts). Still, it should allow you to run the same tree filling code that’ll work under CPython.
Have a look under /afs/.cern.ch/sw/lcg/external/pypy :
[code] cd /afs/.cern.ch/sw/lcg/external/pypy/x86_64-slc5
source ./setup.sh
$ pypy-cint
what kind of objects are in the vector? If they’re TObject deriveds, then their deletion will go through the memory regulator. Otherwise, I wouldn’t expect any difference.
To loop a TChain with 1965152 events, the CPU time spent on “self.InitEvent()” in PyRoot, clearing 37 std vectors for each event, is about 90s. If I did the same clearing in c++ frame, it would take about 1s. It is a dramatic difference.
probably nothing to do with clear() itself, but rather that clear() is completely inline in C++, whereas for Python, you incur the overhead of the stub function (on top of the function itself being out-of-line, which probably doesn’t matter all that much). In particular, clear() for ints and longs does basically nothing: there are no destructors to call, so it’s basically no more than a pointer reset. From gcc’s STL stl_vector.h: void
_M_erase_at_end(pointer __pos)
{
std::_Destroy(__pos, this->_M_impl._M_finish, _M_get_Tp_allocator());
this->_M_impl._M_finish = __pos;
}
with _Destroy() being a no-op for ints (it’s a loop over the elements, calling the dtor on each).
It’s possible to recode specific instances of std::vector to not go through the stubs (i.e. basically build in and hardwire the methods: clear() does not take any arguments after all), but that’s probably not worth it, unless done through a code generator (i.e. in the PyCling world).
yes, TPySelector is not supported yet (for the same reason was why graphics are still trouble). When I first talked about CppyyROOT, I thought you were running directly on TTrees.
Then I tried std.vector.clear without involving TPySelector, but it still crashed:
My scrip “run-vectorClear2.py” is:
from CppyyROOT import (TChain,gSystem,gROOT,TStopwatch)
# from ROOT import (TChain,gSystem,gROOT,TStopwatch)
entries = 2001
from vectorClear2 import vectorClear2
myVecClear = vectorClear2()
for ievt in xrange(entries):
myVecClear.Process(ievt)