Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ __属性__((压缩))会影响程序的性能吗?_C++_C_Data Structures_Struct - Fatal编程技术网

C++ __属性__((压缩))会影响程序的性能吗?

C++ __属性__((压缩))会影响程序的性能吗?,c++,c,data-structures,struct,C++,C,Data Structures,Struct,我有一个叫做log的结构,里面有13个字符。在做了一个sizeof(log)之后,我看到大小不是13而是16。我可以使用_u属性_u((packed))将其设置为13的实际大小,但我想知道这是否会影响程序的性能。这是一种经常使用的结构 我希望能够阅读结构的大小(13而不是16)。我可以使用一个宏,但如果这个结构曾经被改变,即添加或删除字段,我希望新的大小在不改变宏的情况下被更新,因为我认为这很容易出错。有什么建议吗?是的,它会影响程序的性能。添加填充意味着编译器可以使用整数加载指令从内存中读取内

我有一个叫做log的结构,里面有13个字符。在做了一个sizeof(log)之后,我看到大小不是13而是16。我可以使用_u属性_u((packed))将其设置为13的实际大小,但我想知道这是否会影响程序的性能。这是一种经常使用的结构


我希望能够阅读结构的大小(13而不是16)。我可以使用一个宏,但如果这个结构曾经被改变,即添加或删除字段,我希望新的大小在不改变宏的情况下被更新,因为我认为这很容易出错。有什么建议吗?

是的,它会影响程序的性能。添加填充意味着编译器可以使用整数加载指令从内存中读取内容。在没有填充的情况下,编译器必须单独加载内容并进行位移位以获得整个值。(即使是x86并且这是由硬件完成的,也必须完成)


考虑一下:如果不是出于性能原因,编译器为什么要插入随机的、未使用的空间?

是的,它会影响性能。在这种情况下,如果使用
((packed))
属性分配此类结构的数组,则大多数结构都必须以未对齐结束(而如果使用默认打包,则它们都可以在16字节边界上对齐)。如果这些结构对齐,复制它们的速度会更快。

是的,这会影响性能。如何使用取决于它是什么以及您如何使用它

未对齐的变量可能跨越两条缓存线。例如,如果您有64字节的缓存线,并且您从13字节结构的数组中读取了一个4字节的变量,那么它有3/64(4.6%)的几率分布在两行中。额外缓存访问的代价很小。如果你的程序所做的每件事都是对这一个变量施加重击,那么4.6%将是性能影响的上限。如果日志记录占程序工作负载的20%,而对该结构的读/写占日志记录的50%,那么您已经只占了1%的一小部分

另一方面,假设日志需要保存,将每条记录缩减3个字节可以为您节省19%,这意味着需要大量内存或磁盘空间。主内存,尤其是磁盘速度较慢,因此最好打包日志以减小其大小



要在不担心结构更改的情况下读取结构的大小,请使用
sizeof
。无论您喜欢使用数值常量,无论是
const int
enum
,还是
#define
,只需添加
sizeof

不要使用
uu属性((压缩))
。如果您的数据结构在内存中,请允许它占用编译器确定的自然大小。如果是读/写磁盘,写序列化和反序列化函数;不要简单地将cpu本机二进制结构存储在磁盘上。“压缩”结构确实没有合法的用途(或者很少;请参阅此答案上的注释以了解可能存在的不同观点)。

与所有其他性能优化一样,您需要分析代码以找到正确的答案。正确的答案会因建筑以及你如何使用你的结构而有所不同

如果您要创建巨大的阵列,那么打包所节省的空间可能意味着在缓存中安装与不安装的区别。或者,您的数据可能已经放入缓存中,在这种情况下,这不会有什么区别。如果您在STL关联容器中分配大量结构,该容器使用
运算符new
为您的结构分配存储,这可能根本不重要--
运算符new
可能会将您的存储四舍五入到对齐的内容中

如果大多数结构都位于堆栈上,那么额外的存储可能已经被优化掉了


对于这样一个易于测试的变化,我建议构建一个计时装置,然后尝试两种方法。对于进一步的优化,我建议使用探查器来识别瓶颈并从那里着手。

大多数硬件都可以处理大多数未对齐的负载,而不会受到惩罚。该规则的例外是当访问跨越某种边界时:缓存线、页面等。提及指令会产生误导。特别是,如果工作集不适合缓存(并非异常情况),则“压缩”阵列的DRAM事务更少的好处可能会超过额外的缓存访问。对于写入磁盘的结构,情况更是如此。@potatosatter:“大多数”?也许如果“大多数机器都是x86”的话,你的说法有可能是真的,但最后我检查了大多数机器都是嵌入式系统、手机等。。在大多数硬件上,未对齐的访问意味着编译器必须生成执行逐字节加载/存储的代码,可能使用位移位和按位或汇编值来处理较大的类型。这是一个巨大的惩罚。@R:Wikipedia说,ARMv6之前的ARM不支持未对齐。除此之外,SPARC和DSP,大多数体系结构都支持它。无论如何,即使是以CPU速度完成的繁琐的字节翻转也可能不会比额外的磁盘/闪存/DRAM传输时间慢。@Potatostater,有更多的DSP和CPU内核会对未对齐的访问造成比你想象的更大的惩罚。请注意,x86上的SSE2也需要对齐。除非你有很好的理由,否则这确实是一个让默认行为不受影响的领域。即使这样,也要进行测试和基准测试。@Potatoswatter:如果不是出于性能原因,编译器为什么要插入对齐填充?还有一些情况需要处理逐位排列的数据结构。例如,大多数SPI或I2C设备采用具有非常特定结构的字节数据。给定20位左右移位和掩蔽操作之间的选择,或