对齐、总尺寸和SSE
Alignment, total size and SSE
我正在尝试为PCL
库定义一个自定义点类型。在那篇教程中,他们谈论的是记忆对齐,所以我一开始就试图了解它是如何工作的。
在本页中,他们提出了一种计算结构总对齐度的相当简单的方法。例如,这种结构
// Alignment requirements
// (typical 32 bit machine)
// char 1 byte
// short int 2 bytes
// int 4 bytes
// double 8 bytes
// structure C
typedef struct structc_tag
{
char c;
double d;
int s;
} structc_t;
将具有24:的大小
1 byte for the char + 7 bytes of padding + 8 bytes for the double + 4 bytes for the int + 4 bytes of padding
对于g++ 4.8.1
,sizeof返回24。到目前为止,一切都很好。
现在,在PCL
中,他们用这个方案定义了SSE
对齐的点类型(这里是最简单的点,它在每个轴上保持位置)。
union
{
float data[4];
struct
{
float x;
float y;
float z;
};
};
sizeof返回16。使用并集可以确保point type
是SSE对齐的(我在这里读到的是16字节对齐),并且使用结构可以访问轴值。
引用PCL
文档:
用户可以访问的points[i].data[0]或points[i].x访问例如x坐标。
我的推理在此之前有效吗?
在我的情况下,我想更改双打的浮动,以便在X
和Y
轴上有更高的精度。
那么,将点类型声明为:就足够了吗
union {
float data[4];
struct {
double x;
double y;
float z;
};
};
sizeof返回24,它不是16的倍数(所以我知道它不是SSE对齐的),但它是"双对齐的"。
我的问题是,我如何定义我的点类型,以便能够将X
和Y
坐标存储为双坐标,并且仍然是SSE aligned
?
PS:此外,如果你们中有人知道这方面的好资源,请告诉我。我想更好地理解这个话题。
PS 2:我忘了说,我正在尝试的平台是64位的。
PS 3:如果可能的话,我对pre-C++11
解决方案感兴趣。像g++ 4.4
(及其对应的MinGW
)这样旧的编译器必须能够构建新的点类型。
对象的大小和对齐不是一回事。如果结构的大小是16字节或一些倍数,并不意味着它必须是16字节对齐的。
在您的情况下,由于代码是以64位模式编译的,您只需要将结构填充到32字节。在64位模式下,堆栈在Windows和Linux/Unix中是16字节对齐的。
在32位模式中,它不必是16字节对齐的。你可以测试一下。如果您在32位模式下在MSVC中运行下面的代码,您可能会发现数组中每个元素的地址都不是16字节对齐的(您可能需要运行几次)。因此,即使结构的大小是16字节的倍数,它也不一定是16字节对齐的。
#include <stdio.h>
int main() {
union a {
float data[4];
struct {
double x;
double y;
float z;
float pad[3];
};
a b[10];
for(int i=0; i<10; i++) {
printf("%dn", ((int)&b[i])%16);
}
}
如果您希望您的代码也能在32位模式下工作,那么您应该对齐内存。如果你在Windows或Linux上以32位模式运行下面的代码,你会发现它总是16字节对齐的。
#include <stdio.h>
#ifdef _MSC_VER // If Microsoft compiler
#define Alignd(X) __declspec(align(16)) X
#else // Gnu compiler, etc.
#define Alignd(X) X __attribute__((aligned(16)))
#endif
int main() {
union a {
float data[4];
struct {
double x;
double y;
float z;
float pad[3];
};
a Alignd(b[10]);
for(int i=0; i<10; i++) {
printf("%dn", ((int)&b[i])%16);
}
}
为了有一个具有2个双精度和一个浮点的结构,并且是SSE对齐的(16字节),请使用:
#pragma pack(1)
struct T
{
double x,y; // 16 bytes
float z; // 4 bytes
char gap[12]; // 12 bytes
};
sizeof(T)
将是32,所以如果第一个点是16字节对齐的,那么整个向量将被对齐。
为了使第一个点对齐,应该对堆栈变量使用__attribute((aligned(16)),或对堆内存使用aligned_alloc。
但是,PCL的大多数算法都是为浮点而非双精度编写和硬编码的,所以它们不起作用。。。
参考:pcl用户链接
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 如何创建一个QTableWidgetItem,用长文本右对齐,左边有省略号
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 64位机器上的C++内存对齐
- 为什么我可以将变量存储在不是其最小对齐方式的倍数的地址?
- 使 std::vector 分配对齐内存的现代方法
- C++ cout 将双精度对齐到精度 2 并正确对齐
- 在 64 位边界上对齐C++结构数组?
- 三维矢量的SSE对齐
- 像“float[10][10]”初始化的数组是否已经针对 SIMD/SSE 进行了内存对齐
- SSE 向量的对齐和未对齐加载和存储 - 如何减少代码重复
- 存储SSE操作结果时的对齐要求
- 对齐、总尺寸和SSE
- 动态分配的内存在 SSE 中未对齐
- 使用带有自定义对齐分配器实现的最新g++,使用SSE和-O3选项编译时出现非法指令(核心转储)
- 正在对齐SSE的模板矢量结构
- 如何对齐结构数组,每个结构都需要对齐(SSE)
- 在托管代码中调用SSE代码(对齐)
- C++中SSE的内存对齐,_aligned_malloc等效
- 随机存取与SSE对齐的存储器