Fwd: [eigen] Re: State of the problem with std::vector |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen@xxxxxxxxxxxxxxxxxxx
- Subject: Fwd: [eigen] Re: State of the problem with std::vector
- From: "Benoit Jacob" <jacob.benoit.1@xxxxxxxxx>
- Date: Fri, 9 Jan 2009 23:34:56 +0100
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to :subject:in-reply-to:mime-version:content-type:references; bh=8E6V+tc1ZbYSog6L3fqtWtgEK3xrBR4pQE1mOBUmlVU=; b=C3VkoP3L/LYiKRQaVrIEovMOaUTCn1MAcBaIUo7UntmKmR50HoZC/SAhIm2dikkEJn NVO54OPOmbsYU7pOm3UzvZiWxBTSQWB9TArOt83PeCkvZEih/H0t5HMKvSuk0NSZFR+r UHrznS1mecjBmQzKUi1zqb79oA7ixKbb4gWqI=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:in-reply-to:mime-version :content-type:references; b=qpAOAY/ZbzI5qprEnzYmYqdyQHyAzokiuN+eAsezg26rh/V5l2Uf+IcgNhovOcvw0J OAKcB3sgrCeDuuabs5K8d6qZ6TjGOuSHnYmxD1SkPSW5zh8w5kxdRl0slJC4OGDjaoOd Pqvg+ud2cmTq7HmL7z4eOH3W6KCe4w0XPjkUc=
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];
}