Boost logo

Boost Users :

Subject: Re: [Boost-users] Efficient "[][]" operator overloading (encapsulating a MultiArray)
From: Mathias Gaunard (mathias.gaunard_at_[hidden])
Date: 2013-04-09 13:50:06


On 09/04/13 16:36, Jiří Vyskočil wrote:
> Hello,
>
> I need to encapsulate a 3D MultiArray inside another class "GridArray".
> The reason is that GridArray will have another implementation not using
> MultiArray and it seems much easier to provide an abstration over
> MultiArray, than to reimplement its interface for the other implementation.
>
> I need to keep the [][][] operator access to the structure. I created a
> class like this, but it is slow:
>
>
> template<class T> class GridArray<T,3> {
> public:
> GridArray(int x, int y, int z):
> _array(boost::extents[x][y][z]) { }
> boost::multi_array<T, 3> _array;
> struct SliceRef {
> struct ColRef {
> SliceRef &_parent;
> int _x, _y;
> ColRef(SliceRef &p, const int x, const int y):
> _parent(p), _x(x), _y(y) {}
> T& operator[](const int z) {
> return _parent._parent._array[_x][_y][z];
> }
> };
> GridArray<T,3> &_parent;
> int _x;
> SliceRef(GridArray<T,3> &p, const int x):
> _parent(p), _x(x) {}
> ColRef operator[](const int y) {
> return ColRef(*this,_x,y);
> }
> };
> SliceRef operator[](const int x){
> return SliceRef(*this,x);
> }
> };
>
>
> I am unable to write a minimal test case - if I compare using
> multi_array directly vs. using this GridArray class in a simple test
> program (compiled with -O2), the performance is the same. But the real
> code shows about 20% slowdown - it's a numerical simulaiton, I create
> several arrays at the beginning and then do computations with them. The
> rest of the code hasn't been touched - I only chanded the constructors
> for the arrays and replaced a header which contained some typedefs with
> a header containing this class.
>
> Do you have any idea what might be going on? Is there a better way to
> write an interface for successive [] operators?

Remember that those are references, so you're actually doing
*(_parent->_parent->array)[_x][_y][z].
Some compilers might not be able to avoid the redundant loads here.
You could put SliceRef by value in ColRef for starters. You can also try
to put GridArray<T,3> by value (or a version which doesn't copy the
underlying data).

Also if you're creating ColRef or SliceRef at every iteration or copying
them around, some compilers might not be able to do so without a cost.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net