我有一个可以运行32位或64位的系统。如果我定义一个具有7个long和1个char的结构,那么我理解如果该结构运行在32位上,则long将被分配32位,char将被分配8位,并且该结构将至少需要232位。但是如果结构运行在64位上,那么long将被分配64位,char将被分配8位,并且该结构将至少需要456位。我还了解到,如果结构需要2位的幂,那么内存将针对结构的数组进行优化。因此,这种结构必须在32位系统上填充256位,或者在64位系统上填充512位。填充是否会自动添加到结构中以优化内存,或者我是否应该向结构中添加某些内容以使其更接近2位的幂,以便优化这些结构的数组的处理?
发布于 2015-04-12 05:37:26
编辑:刚刚看到了一篇关于使用移位与乘法进行数组索引的文章。我的建议是根据您的数据适当地调整结构的大小,如果可以的话,请注意不要因为slop而浪费空间。如果分析器确定索引元素是影响性能的主要因素,您可以尝试添加slop以明确达到特定的字节大小。然而,我的直觉告诉我(在带有缓存的现代系统上),如果不必要地增加结构的大小并将有用的内存从缓存中取出,您将遭受更大的性能损失!:D
(原始回复如下)
我认为你不会因为没有将你的结构调整到2的幂而看到性能损失。结构数组的性能问题通常是由于对齐造成的。
调整和性能
为了最小化访问标量变量所需的指令数量,变量必须存在于内存中的一个位置,该位置必须是其字节大小的倍数。结构的含义如下:
实际上,由于结构的地址等于其第一个成员的地址,给定结构的起始地址必须是其第一个成员大小的倍数,对于编译器编写者来说,以字节为单位
处理结构对齐的
现代系统上的大多数编译器都会自动在结构后面添加填充,以满足自对齐类型的对齐要求。
因此,一般来说,您的结构将与结构中最大元素的倍数对齐。由于结构中的长整型,数组中的每个结构都会间隔开,这样每个结构的起始地址就是sizeof(long)
的倍数。这是通过将"slop“透明地添加到结构的末尾来实现的。试试这个,看看你会得到什么:
#include <stdio.h>
struct my_struct
{
long l1;
long l2;
long l3;
long l4;
long l5;
long l6;
long l7;
char c;
};
int main( int argc, char** argv )
{
printf("sizeof(my_struct) == %lu\n", sizeof(struct my_struct));
return 0;
};
/* EOF */
包装注意事项:
通常,对于支持自对齐类型的系统上的自对齐类型,通常可以使用__attribute__((packed))
,但这可能会导致性能损失,因为访问给定成员所需的机器指令数量将增加。
如果你真的很关心不会因为对齐斜率而浪费空间,并且你不需要这些长整型中的所有值,那么看看你是否可以使用掩码将char
移动到其中一个长整型中,或者尝试使用位域。
我个人最喜欢的关于结构、打包和对齐的资源之一:The Lost Art of C Structure Packing
发布于 2015-04-12 05:27:49
是否会自动将填充添加到结构中以优化内存,或者我是否应该向结构中添加某些内容以使其更接近2位的幂,以便优化这些结构的数组的处理?
不,你不需要在你的struct声明中添加任何东西。一般来说,对齐和填充是由编译器来处理的。您可以通过打印sizeof(your_struct);
的输出自己测试这一点。
然而,可以做相反的事情,并针对大小而不是速度进行优化。如果内存不足,或者您通过网络发送原始结构,这将非常有用。GCC有__attribute__((packed))
可以做到这一点。
发布于 2021-12-29 03:15:58
这有点晚了,但我只想分享这篇关于结构打包的文章,详细介绍如何通过重新排列结构成员的声明顺序来优化结构变量的大小:http://www.catb.org/esr/structure-packing/
https://stackoverflow.com/questions/29583173
复制相似问题