I am building a project I have received from a colleague. I am receiving the following error:
..\HelperFunctions\disp.cpp(130): error C2719: 'viewpoint': formal parameter with __declspec(align('16')) won't be aligned
I am following clues to disp.cpp
line 130 only to find this is the end of a function and all I have in this line is:
}
Following this link it is my understanding this might be an issue with the function definition, but I could not fully understand if there is anything wrong. I have commented all unnecessary elements of the function and reduced it to:
std::vector< int > HPR (typename pcl::PointCloud<PointT>::ConstPtr source,pcl::PointXYZ viewpoint, double param)
{
//commented section
std::vector< int > indices;
//commented section
return indices;
}
Still getting the same error.
- What am I missing?
- How do I address this?
P.S.
I am new to C++ and working on visual studio 2010 with PCL API.
After googling the pcl::PointXYZ
, I found out that it's actually based on the Eigen library. (I saw a lot of EIGEN
macros in the source code.)
The EIGEN library tries to obtain best performance using special SSE instructions. AFAIK, these SSE instructions require that the data has to be aligned appropriately (e.g. that addresses are multiples of 16).
This may interfere with the passing of function arguments for
std::vector<int> HPR(
typename pcl::PointCloud<PointT>::ConstPtr source,
pcl::PointXYZ viewpoint, double param);
When a function is called the arguments may be handed over in CPU registers but usually (especially on Intels x86 CPUs) they are pushed to the stack where the function accesses them using a certain base pointer, for Intels CPUs e.g. obtaining the BP register (16 bit), EBP (32 bit), or RBP (64 bit).
More about this on Eli Benderskys Stack frame layout on x86-64.
However, pushing data to stack may not allow to align the data as required (without breaking the "binary signature" of the called function). Thus, the compiler throws the error C2719.
If the 2nd parameter of the function is changed from value to reference this means the reference of the original variable is handed over. (Although this may technically not fully correct, I imagine it as handing over the address of the original variable instead of a copy on stack.) To prevent accidental overwriting the contents of the referenced variable, a const
reference can be used:
std::vector<int> HPR(
typename pcl::PointCloud<PointT>::ConstPtr source,
const pcl::PointXYZ &viewpoint, double param);
Due to the reference, the original variable is used which is either correcly aligned (or would cause another error at another line of source code). For the reference, no special alignment is required anymore.
To use a const
(or non-const
) reference instead of a value may have additionally a positive performance effect. If the parameter type is something with significant greater size than a "machine word" (i.e. something which fits into a register) than it is worth to pass the reference instead of copying the value. This is probably the case for pcl::PointXYZ
considering:
#define PCL_ADD_POINT4D \
EIGEN_ALIGN16 \
union { \
float data[4]; \
struct { \
float x; \
float y; \
float z; \
}; \
} ;
...
struct _PointXYZ
{
PCL_ADD_POINT4D; // This adds the members x,y,z which can also be accessed using the point (which is float[4])
EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
};
and
struct EIGEN_ALIGN16 PointXYZ : public _PointXYZ
(According to float[4]
, it should consume 16 bytes.)
In oppisition, it's not worth to consider a reference for primitive types like bool
, int
, and any pointer (which usually should fit into "machine word" width).