Re: [eigen] Alignment of derived matrix class

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


Gael, thanks for your suggestions!

I have verified the following:

1)  the code that breaks assertion is even the most simple variant (so this has nothing to do with inheritance):

* Eigen::Matrix<double, 6, 1> servo_real_kartez_pos;

2) for 100% right variant of macro is used:
#define EIGEN_ALIGN_128 __attribute__((aligned(16)))
(added #error to all the other variants).

3) my code works just fine with -DEIGEN_DONT_ALIGN switch.

4) alignment attribute is honored by QCC compiler (which uses gcc-4.3.1 as a backend),
which I have verified with the following result of a test program attached:

# ../a.out
aligned: 8047b50
notaligned: 8047b98
In function nonaligned -- align.cc:24 (reinterpret_cast<std::size_t>(array) & 0xf) ==0 -- assertion failed
Abort (core dumped)

I will appreciate any idea... It looks like QCC compiler does align the data only when it wants (?!).

Piotr

On Fri, Mar 5, 2010 at 09:35, Gael Guennebaud <gael.guennebaud@xxxxxxxxx> wrote:

Hi Piotr,

this sounds really strange to me. To help to understand the cause of the issue have you tried, or could you try the following:

replace B servo_real_kartez_pos; by each of the following:

* Eigen::Matrix<double, 6, 1> servo_real_kartez_pos;
* A servo_real_kartez_pos;
* EIGEN_ALIGN_128 B servo_real_kartez_pos;

Check that sizeof(B)==sizeof(Eigen::Matrix<double, 6, 1>)

gael


On Fri, Mar 5, 2010 at 12:45 AM, Piotr Trojanek <piotr.trojanek@xxxxxxxxx> wrote:
Dear Eigen experts,

while porting some robotics matrix code to Eigen2 I have encountered the following problem
on QNX platform, but I do not think it is QNX specific.

I have the following class hierarchy, which I have created using guidelines from:
http://www.ros.org/wiki/eigen#Creating_typedefs_for_Eigen_types

// Base class (with not copy-pasted robot-specific methods)
class A : public Eigen::Matrix<double, 6, 1> {
public:
    // Copy constructor from any Eigen matrix type
    template<typename OtherDerived>
    A(const Eigen::MatrixBase<OtherDerived>& other)
        : BaseClass(other)
    {}

    // Reuse assignment operators from base class
    using BaseClass::operator=;

    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

// Derived class type, which will hold additional methods
class B : public A {
public:
    template<typename OtherDerived>
    B(const Eigen::MatrixBase<OtherDerived>& other)
        : Ft_v_vector(other)
    {}

    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

When I run this code on Linux - it works just fine.
When I run this on QNX - it fails with Unalligned Array Assert. The backtrace is here:

#0  0xb033dad1 in SignalKill () from /usr/qnx641/target/qnx6/x86/lib/libc.so.3
#1  0xb032c82e in raise () from /usr/qnx641/target/qnx6/x86/lib/libc.so.3
#2  0xb032ab08 in abort () from /usr/qnx641/target/qnx6/x86/lib/libc.so.3
#3  0xb032ad29 in __assert () from /usr/qnx641/target/qnx6/x86/lib/libc.so.3
#4  0x080534ec in ei_matrix_array (this=0x7f42db4) at /opt/qnx641/target/qnx6/mrlib/include/eigen2/Eigen/src/Core/MatrixStorage.h:43
#5  0x0805350f in ei_matrix_storage (this=0x7f42db4) at /opt/qnx641/target/qnx6/mrlib/include/eigen2/Eigen/src/Core/MatrixStorage.h:79
#6  0x0809936f in Matrix<Eigen::CwiseNullaryOp<Eigen::ei_scalar_constant_op<double>, Eigen::Matrix<double, 6, 1, 2, 6, 1> > > (
    this=0x7f42db4, other=@0x7f42ccc) at /opt/qnx641/target/qnx6/mrlib/include/eigen2/Eigen/src/Core/Matrix.h:405
#7  0x080981a4 in A (this=0x7f42db4) at mrmath/ft_v_vector.cc:28
#8  0x0809820f in B (this=0x7f42db4) at mrmath/ft_v_vector.cc:185
#9  0x08078293 in mrrocpp::edp::common::manip_effector::compute_servo_joints_and_frame (this=0x80d7fc0) at edp_e_manip.cc:55

The code, that causes the abort is just creating local, temporary variable of class B:
B servo_real_kartez_pos;

I have checked, that QNX compiler honours EIGEN_ALIGN_128 statement (I am 100% sure,
checked with gdb for very simple structure alignment with and without this statement).

The question is - where is my mistake? Is it correct to make inherit in the above way?
The problem seems to be, that in frames #8 to #4 "this" is not aligned to 128bit boundary.
I have tried adding EIGEN_ALIGN_128 and virtual inheritance, but this did not solve the problem.

Thanks in advance!

--
Piotr Trojanek
Robot Control and Recognition Systems Team,
Institute of Control & Computation Engineering,
Warsaw University of Technology






--
Piotr Trojanek
#include <stdio.h>
#include <assert.h>
#include <cstdlib>

struct aligned {
	char c;
	__attribute__((aligned(16))) 
		double array[8];

	aligned() {
		printf("aligned: %p\n", array);

		assert((reinterpret_cast<std::size_t>(array) & 0xf) ==0);
	}
};

struct nonaligned {
	char c;
	double array[7];

	nonaligned() {
		printf("notaligned: %p\n", array);

		assert((reinterpret_cast<std::size_t>(array) & 0xf) ==0);
	}
};

int
main(int argc, char *argv[])
{
	aligned a;
	nonaligned na;
	return 0;
}


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