Fwd: [eigen] Re: State of the problem with std::vector

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]


grrr, gmail again forgot to reply to list


---------- Forwarded message ----------
From: Benoit Jacob <jacob.benoit.1@xxxxxxxxx>
Date: 2009/1/9
Subject: Re: [eigen] Re: State of the problem with std::vector
To: Alex Stapleton <alex.stapleton@xxxxxxxxx>


Thanks a lot!
I have made the necessary changes in Eigen so that the attached code
(a.cpp, based on your example.txt) works.
I thought I'd attach it as is here so you can have a look if you're
interested while it is still mostly self-contained and closely
resembling your file. Now i'll merge it into Eigen.
Cheers,
Benoit

2009/1/9 Alex Stapleton <alex.stapleton@xxxxxxxxx>:
> I have prepared a little example of the idea I had to work around this
> alignment problem in std::vector. It's in the attached file. I *think*
> this does more or less what you want without being too evil or
> platform specific. Hopefully this illustrates things better than my
> ramblings on IRC.
>
> Tested with gcc version 4.0.1 (Apple Inc. build 5465) and -Wall -ansi -std=c++98
>
> Alex Stapleton
>
>
>
> 2009/1/9 Benoit Jacob <jacob.benoit.1@xxxxxxxxx>:
>> ---------- Forwarded message ----------
>> From: Benoit Jacob <jacob.benoit.1@xxxxxxxxx>
>> Date: 2009/1/9
>> Subject: Re: [eigen] Re: State of the problem with std::vector
>> To: eigen@xxxxxxxxxxxxxxxxxxx
>>
>>
>> I was thinking about doing something dirtier than that:
>>
>> namespace std {
>>
>> namespace foo {
>>
>> #sort-of-include<vector>
>>
>> } //foo
>>
>> template<typename Scalar,....> class vector<Eigen::Matrix<...> > :
>> public foo::std::vector< Eigen::Matrix<...> >
>> {
>> ..
>> };
>>
>> } // std
>>
>> However I haven't really sorted out what #sort-of-include would be. It
>> could be #include preceded and followed by #undef'ing preprocessor
>> symbols.... ok ok it's very ugly, we can forget it.
>>
>> Benoit
>>
>> 2009/1/8 Gael Guennebaud <gael.guennebaud@xxxxxxxxx>:
>>> On Thu, Jan 8, 2009 at 9:36 PM, Benoit Jacob <jacob.benoit.1@xxxxxxxxx> wrote:
>>>> So, another possible solution... is to make a specialization
>>>> std::vector<Vector4f> that inherits what it would normally be, and
>>>> redefines resize().
>>>
>>> how would you do that ? something like that : (neglecting the allocator)
>>>
>>> namespace std {
>>>
>>> template<typename Scalar,....> class vector<Eigen::Matrix<...> > :
>>> public vector< Eigen::Matrix<...> >
>>> {
>>> ..
>>> };
>>>
>>> } // std
>>>
>>> but then we basically have an infinite recursion:
>>>
>>> class A : public A {};
>>>
>>> am I missing something ?
>>>
>>> gael.
>>>
>>>> 2009/1/8 Benoit Jacob <jacob.benoit.1@xxxxxxxxx>:
>>>>> Hi,
>>>>>
>>>>> THE PROBLEM
>>>>>
>>>>> (as discussed since yesterday on IRC)
>>>>>
>>>>> std::vector<value_type> (both GCC and MSVC implementations) has a
>>>>> resize() method that takes a value_type by value.
>>>>>
>>>>> Since attributes don't work on function parameters (with GCC and
>>>>> MSVC), this means that this program,
>>>>>
>>>>> #include <Eigen/Core>
>>>>> #include <vector>
>>>>>
>>>>> int main()
>>>>> {
>>>>>  std::vector <Eigen::Vector4f> v(10);
>>>>>  v.resize(20);
>>>>> }
>>>>>
>>>>> triggers the unaligned-array-assert (unless of course by pure chance
>>>>> (50%) the copied vector happens to be aligned).
>>>>> If we disabled the asserts, it will crash when trying to use aligned
>>>>> SSE insns on this unaligned location.
>>>>>
>>>>> THE ONLY POSSIBLE SOLUTION WE CAN SEE
>>>>> thanks a lot to "alexs" from ##c++ IRC channel...
>>>>>
>>>>> [18:09] <bjacob> ggael: so i got help on ##c++
>>>>> [18:09] <bjacob> the only idea that seems to have a chance of working,
>>>>> [18:09] <bjacob> is to define a separate vector type inheriting Vector4f,
>>>>> [18:10] <bjacob> this vector type has a copy constructor that doesn't
>>>>> use SSE insns
>>>>> [18:10] <bjacob> and a default constructor that doesn't do the
>>>>> unaligned array assert
>>>>> [18:10] <bjacob> and use inheritance and implicit conversions to let
>>>>> the user use std::vector on that vector type
>>>>> [18:11] <bjacob> while using it as std::vector<Vector4f>
>>>>> [18:13] <bjacob> so could make this templated .... template<typename
>>>>> MatrixType> class AllowUnaligned : public MatrixType;
>>>>> [18:13] <bjacob> std::vector <  AllowUnaligned <Vector4f> >
>>>>> [18:14] <ggael> ok, I see
>>>>> [18:17] --> alexs_ a rejoint ce canal (n=alexs@unaffiliated/alexs).
>>>>> [18:17] <alexs_> Looks interesting :)
>>>>> [18:19] <bjacob> ok some backlog pasting....
>>>>> [18:19] <bjacob> http://rafb.net/p/C27reW66.html
>>>>> [18:20] <bjacob> alexs_: ^
>>>>> [18:20] <alexs_> yeah :)
>>>>> [18:20] <bjacob> ggael: http://rafb.net/p/TDr0X549.html
>>>>> [18:25] <alexs_> You could probably use a specialisation of
>>>>> vector<Vector4> that statically sets the value_type to the right
>>>>> thing, to hide it from the user?
>>>>> [18:29] <bjacob> hm. and by the way set an aligned allocator. good idea.
>>>>> [18:30] <bjacob> this will mean inheriting from std::vector, never
>>>>> tried, hope it's easy (don't know what's the best way to preserve the
>>>>> ctors, assignment operators, etc, that don't get inherited)
>>>>> [18:30] <alexs_> composition should work ok
>>>>> [18:30] <alexs_> it's not too many things :)
>>>>> [18:31] <alexs_> operators are not members of vector anyway
>>>>> [18:31] <bjacob> you'd recommend composition (i guess this means
>>>>> having-as-a-member) over inheritance?
>>>>> [18:31] <bjacob> not even assignment operators?
>>>>> [18:31] <alexs_> composition for the things that inheritance doesnt bring in
>>>>> [18:32] <bjacob> oh, i see
>>>>> [18:46] <bjacob> alexs_: by the way it is not just MSVC that doesn't
>>>>> allow align attribute on function parameters
>>>>> [18:46] <bjacob> here, gcc 4.3.2 allows this code to compile but the
>>>>> attribute isn't honored and i get my assertion at runtime saying the
>>>>> object is unaligned
>>>>> [18:48] <alexs_> bjacob: Oh :(
>>>>> [18:49] <alexs_> is it a function parameter if you want aligned arguments?
>>>>> [18:49] <alexs_>     -mpreferred-stack-boundary=num
>>>>> [18:50] <bjacob> hm good idea
>>>>> [18:50] <alexs_> default is 16 bytes
>>>>> [18:50] <bjacob> oh -- so it's not what we want then -- as 16 bytes should be OK
>>>>> [18:51] <alexs_> Unless you use -Os
>>>>> [18:51] <bjacob> ++ -mpreferred-stack-boundary=16 -I
>>>>> kde/kdesupport/eigen2/ a.cpp -o a && ./a
>>>>> [18:51] <bjacob> a.cpp:1: error: -mpreferred-stack-boundary=16 is not
>>>>> between 2 and 12
>>>>> [18:51] <alexs_> Yeah, it is raised to a power of 2
>>>>> [18:51] <bjacob> oops, "++" should be "g++"
>>>>> [18:51] <alexs_> you want 4 :)
>>>>> [18:51] <bjacob> ah ok
>>>>> [18:51] <alexs_> but my man page says that is the default
>>>>> [18:51] <bjacob> yes and with 4 is still get the same problem
>>>>> [18:52] <bjacob> "preferred" is probably not strictly honored
>>>>> [18:52] <alexs_> So it's not aligning them...
>>>>> [18:52] <alexs_> It does say "attempt"
>>>>>
>>>>> Cheers,
>>>>> Benoit
>>>>>
>>>>
>>>> ---
>>>>
>>>>
>>>
>>> ---
>>>
>>>
>>
>
#include <vector>
#include <Eigen/Core>

namespace Eigen{
template<typename aligned_type> class ei_unaligned_type;

template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
class ei_unaligned_type<Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> >
  : public Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>
{
  public:
    typedef Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> aligned_base;
    ei_unaligned_type() : aligned_base(ei_select_matrix_constructor_doing_absolutely_nothing()) {}
    ei_unaligned_type(const aligned_base& other)
    {
      ei_assign_impl<ei_unaligned_type,aligned_base,NoVectorization>::run(*this, other);
    }
};
} // namespace Eigen

namespace std {

  template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols, typename _Alloc>
  class vector<Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>, _Alloc>
    : public vector<Eigen::ei_unaligned_type<Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> >,
                    Eigen::aligned_allocator<Eigen::ei_unaligned_type<Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> > > >
  {
  public:
    typedef Eigen::ei_unaligned_type<Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> > value_type;
    typedef Eigen::aligned_allocator<value_type> allocator_type;
    typedef vector<value_type, allocator_type > unaligned_base;
    typedef typename unaligned_base::size_type size_type;
    typedef typename unaligned_base::iterator iterator;

    explicit vector(const allocator_type& __a = allocator_type()) : unaligned_base(__a) {
    }

    vector(const vector& c) : unaligned_base(c) {
    }

    vector(size_type num, const value_type& val = value_type()) : unaligned_base(num, val) {
    }

    vector(iterator start, iterator end) : unaligned_base(start, end) {
    }

    vector& operator=(const vector& __x) {
      return *this = __x;
    }
  };

} // namespace std

using namespace Eigen;

int main() {
  typedef Vector4f aligned_type;
  typedef ei_unaligned_type<aligned_type> unaligned_type;
  std::cout << " + INIT VECTOR\n";
  std::vector<aligned_type> vec(2);

  std::cout << " + PUSH BACK\n";
  vec.push_back(aligned_type());
  vec.push_back(aligned_type());

  std::cout << " + RESIZE\n";
  vec.resize(5);

  std::cout << " + FETCH REFS\n";
  aligned_type& a = vec[0];
  unaligned_type& b = vec[0];
}




Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/