meta-traits issue

19 views
Skip to first unread message

Bob Carpenter

unread,
Oct 27, 2012, 6:12:54 PM10/27/12
to stan...@googlegroups.com
1. This is only going to affect behavior that's
not yet documented in the manual -- vectorizing matrices,
for instance, m ~ normal(0,1) to give a whole matrix
m a unit normal distirbution.

2. The failing part of the test is here:

and here's the test from:

test/meta/traits_test.cpp, line 227:
-------------------------
const Matrix<double,1,Dynamic> d(c);
VectorView<const Matrix<double,Dynamic,1> > dv(d);
for (size_t n = 0; n < 10; ++n)
EXPECT_FLOAT_EQ(d[n], dv[n]);
--------------------------

I'm pretty sure the problem is the way the VectorView
templates are getting instantiated. Here is the
basic class:


template<typename T,
bool is_vec = stan::is_vector<T>::value>
class VectorView

and here are its specializations:

template<typename T>
class VectorView<T*,false>

template<typename T>
class VectorView<T,true>

template<typename T>
class VectorView<T*,true>

template<typename T>
class VectorView<const T,true>

The only one that matches the call in the test should
be the last one, but the behavior looks like the basic
class might be getting instantiated.

Also, I think trying to instantiate VectorView<double*>
would lead to a conflict betwene the first and third
template specialization.


Also, the basic class's definition seems wrong, because
it doesn't actually pay attention to the is_vec
declaration and treats everything as a scalar ptr.

stan/meta/traits.hpp, line 171
-------------------------------
template<typename T,
bool is_vec = stan::is_vector<T>::value>
class VectorView {
private:
T* x_;
public:
VectorView(T& x) : x_(&x) { }
typename scalar_type<T>::type& operator[](int /*i*/) {
return *x_;
}
};
---------------

The is_vec gets a default, but isn't used in the class definition.
Instead, the operator[] definition assumes T is not a vector.

I think the problem might go away if we change the basic class so
that its operator[] definition is:

typename scalar_type<T>::type& operator[](int i) {
if (is_vec) return x_[i];
else return *x_;
}

AND

add Matrix<T,Dynamic,Dynamic> to the is_vector type. Or
maybe better, an is_vector<T> || is_matrix<T> so we can
keep the types separate.

The (is_vec) value is known statically, so should get optimized away
in the two instances of the template (is_vec = TRUE, is_vec = FALSE).

Alternatively, I think it could be rewritten. As is, there
are probably unexpected consequences of the definitions such
as the fact that const types are always assumed to be vectors.

Is the behavior we want just this?

scalar-like: double, var

vector-like: double*, var*,
vector<double>, vector<var>,
Matrix<double,R,C>, Matrix<var,R,C>

Reference types T& should behave like the unreferenced type T.
Usually in this kind of setup, so do pointers, but here the
decision was made to treat pointers as arrays.

But we should be able to fix this problem by simply defining
vector views for all these types:

basic, def for scalars:

template <typename T> VectorView

vector-like def:

template <typename T> VectorView<T*>

template <typename T> VectorView<vector<T> >

template <typename T, int R, int C> VectorView<Matrix<T,R,C> >

Of course, we really only need two definitions for vector view,
one for scalars and one for vectors. We could instead have a bunch
of factory functions that return VectorView instances rather than
definining a bunch of VectorView template classes with redundant
definitions.

Daniel -- if this is all too much to digest, we can talk on Monday.

- Bob

Daniel Lee

unread,
Nov 2, 2012, 6:34:32 PM11/2/12
to stan...@googlegroups.com
Ben, could you run the meta traits tests?

Bob and I committed 07f07f6012d5. There are a couple ways we think the tests could fail. If one of the tests fail, I think that's enough information to figure out what's happening on a linux box.



Daniel





- Bob

--



Ben Goodrich

unread,
Nov 2, 2012, 9:15:21 PM11/2/12
to stan...@googlegroups.com
On Friday, November 2, 2012 6:34:34 PM UTC-4, Daniel Lee wrote:
Ben, could you run the meta traits tests?

Bob and I committed 07f07f6012d5. There are a couple ways we think the tests could fail. If one of the tests fail, I think that's enough information to figure out what's happening on a linux box.

Was segfaulting one of those ways?

Running main() from gtest_main.cc
[==========] Running 21 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 21 tests from MetaTraits
[ RUN      ] MetaTraits.isConstant
[       OK ] MetaTraits.isConstant (0 ms)
[ RUN      ] MetaTraits.is_vector
[       OK ] MetaTraits.is_vector (0 ms)
[ RUN      ] MetaTraits.isConstantStruct
[       OK ] MetaTraits.isConstantStruct (0 ms)
[ RUN      ] MetaTraits.length
[       OK ] MetaTraits.length (0 ms)
[ RUN      ] MetaTraits.VectorView_double
[       OK ] MetaTraits.VectorView_double (0 ms)
[ RUN      ] MetaTraits.VectorView_var
[       OK ] MetaTraits.VectorView_var (0 ms)
[ RUN      ] MetaTraits.VectorView_vector_double
[       OK ] MetaTraits.VectorView_vector_double (0 ms)
[ RUN      ] MetaTraits.VectorView_vector_var
[       OK ] MetaTraits.VectorView_vector_var (0 ms)
[ RUN      ] MetaTraits.VectorView_matrix_double
[       OK ] MetaTraits.VectorView_matrix_double (0 ms)
[ RUN      ] MetaTraits.VectorView_matrix_var
Segmentation fault
make: *** [runtest/test/meta/traits] Error 139


Ben
 

Ben Goodrich

unread,
Nov 3, 2012, 12:18:33 AM11/3/12
to stan...@googlegroups.com
On Friday, November 2, 2012 9:15:21 PM UTC-4, Ben Goodrich wrote:
On Friday, November 2, 2012 6:34:34 PM UTC-4, Daniel Lee wrote:
Ben, could you run the meta traits tests?

Bob and I committed 07f07f6012d5. There are a couple ways we think the tests could fail. If one of the tests fail, I think that's enough information to figure out what's happening on a linux box.

Was segfaulting one of those ways?

Upon further review (and less optimization), you've got

Program received signal SIGSEGV, Segmentation fault.
0x000000000041b09d in stan::agrad::var::val (this=0x7fffffffdae8) at src/stan/agrad/agrad.hpp:415
415             return vi_->val_;
(gdb) bt
#0  0x000000000041b09d in stan::agrad::var::val (this=0x7fffffffdae8) at src/stan/agrad/agrad.hpp:415
#1  0x000000000040fc70 in MetaTraits_VectorView_matrix_var_Test::TestBody (this=0x69c430) at src/test/meta/traits_test.cpp:274
#2  0x0000000000458e83 in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void> (object=0x69c430, method=..., location=0x469b54 "the test body")
    at lib/gtest_1.6.0/src/gtest.cc:2090
#3  0x0000000000448c17 in testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void> (object=0x69c430, method=..., location=0x469b54 "the test body")
    at lib/gtest_1.6.0/src/gtest.cc:2126
#4  0x0000000000435727 in testing::Test::Run (this=0x69c430) at lib/gtest_1.6.0/src/gtest.cc:2161
#5  0x00000000004364bc in testing::TestInfo::Run (this=0x69b000) at lib/gtest_1.6.0/src/gtest.cc:2338
#6  0x0000000000436c25 in testing::TestCase::Run (this=0x69a440) at lib/gtest_1.6.0/src/gtest.cc:2445
#7  0x000000000043c5c7 in testing::internal::UnitTestImpl::RunAllTests (this=0x69a140) at lib/gtest_1.6.0/src/gtest.cc:4237
#8  0x0000000000454ec3 in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x69a140, method=..., 
    location=0x46a27f "auxiliary test code (environments or event listeners)") at lib/gtest_1.6.0/src/gtest.cc:2090
#9  0x000000000044af97 in testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x69a140, method=..., 
    location=0x46a27f "auxiliary test code (environments or event listeners)") at lib/gtest_1.6.0/src/gtest.cc:2126
#10 0x000000000043c2c2 in testing::UnitTest::Run (this=0x699dc0) at lib/gtest_1.6.0/src/gtest.cc:3872
#11 0x0000000000405e5f in main (argc=1, argv=0x7fffffffe2d8) at lib/gtest_1.6.0/src/gtest_main.cc:38
(gdb) f 1
#1  0x000000000040fc70 in MetaTraits_VectorView_matrix_var_Test::TestBody (this=0x69c430) at src/test/meta/traits_test.cpp:274
274         EXPECT_FLOAT_EQ(d[n].val(), dv[n].val());
(gdb) print n
$1 = 0
(gdb) print dv[n]
$2 = {vi_ = 0x0}
(gdb) print d[n]
$3 = (Eigen::DenseCoeffsBase<Eigen::Matrix<stan::agrad::var, 1, -1, 1, 1, -1>, 1>::Scalar &) @0x6ac5f0: {vi_ = 0x69cad8}
(gdb) print d[n].val()
$4 = 10
(gdb) print dv[n].val()
Attempt to take address of value not located in memory.


Ben

Daniel Lee

unread,
Nov 3, 2012, 1:03:50 PM11/3/12
to stan...@googlegroups.com
Ben, thanks. Can you run the test again?

If it works, I think the root cause is an error in the test specification and we can fix the issue.



--
 
 

Ben Goodrich

unread,
Nov 3, 2012, 2:54:00 PM11/3/12
to stan...@googlegroups.com
It is working now.

Daniel Lee

unread,
Nov 3, 2012, 10:11:02 PM11/3/12
to stan...@googlegroups.com
Thanks. This was an issue with the test and not the code.

I think the issue is that the template parameter did not match the type of the parameter passed in. VectorView was instantiated with Matrix<var, Dynamic, 1>, but the matrix passed in was Matrix<var, 1, Dynamic>. In Windows and Mac, this works fine, but not in Linux.




--
 
 

Reply all
Reply to author
Forward
0 new messages