【发布时间】:2012-02-23 14:12:33
【问题描述】:
在Game Coding Complete, 3rd Edition, 一书中,作者提到了一种既可以减小数据结构大小又提高访问性能的技术。本质上,它依赖于在成员变量与内存对齐时获得性能这一事实。这是编译器可以利用的一个明显的潜在优化,但是通过确保每个变量对齐,它们最终会膨胀数据结构的大小。
或者至少这是他的主张。
他指出,真正的性能提升是通过动用大脑并确保正确设计结构以利用速度提升的优势,同时防止编译器膨胀。他提供了如下代码sn-p:
#pragma pack( push, 1 )
struct SlowStruct
{
char c;
__int64 a;
int b;
char d;
};
struct FastStruct
{
__int64 a;
int b;
char c;
char d;
char unused[ 2 ]; // fill to 8-byte boundary for array use
};
#pragma pack( pop )
在未指定的测试中使用上述struct 对象,他报告15.6% 的性能提高(222ms 与192ms 相比)并且FastStruct 的大小更小。这一切在纸上对我来说都是有道理的,但在我的测试下却无法坚持:
同时结果和大小(计算char unused[ 2 ])!
现在,如果 #pragma pack( push, 1 ) 仅与 FastStruct 隔离(或完全删除),我们确实会看到不同之处:
所以,最后,这里有一个问题:现代编译器(特别是 VS2010)是否已经针对位对齐进行了优化,因此缺乏性能提升(但增加了结构大小作为副作用,就像 Mike Mcshaffry 所说)?还是我的测试不够密集/不确定,无法返回任何重要结果?
对于测试,我对未对齐的__int64 成员执行了数学运算、列主要多维数组遍历/检查、矩阵运算等各种任务。这两种结构都没有产生不同的结果。
最后,即使它们没有提高性能,这仍然是一个有用的花絮,需要牢记以将内存使用量降至最低。但是,如果我没有看到性能提升(无论多么小),我会很高兴。
【问题讨论】:
-
您在所有测试中得到完全相同的时间这一事实表明您运行的时间不够长。时序代码的分辨率可能不够高,无法显示任何差异。
-
也许在你的测试过程中,有问题的变量被使用了太多,它被缓存在一个寄存器中。让 int64 变量跨越内存边界需要两条汇编指令才能获取它必然会更慢。
-
@BoPersson:更有可能的是,编译器只是简单地优化了它们以生成相同的代码。
-
@Bo Persson 我正在使用 Boost::Chrono 进行时间测量,如果这有影响的话。
-
为了扩展上面@BoPersson 的评论,您获得相同的微秒时间,无论是逐个案例还是逐个运行,这一事实非常可疑。你的时间框架有缺陷。
标签: c++ performance visual-studio-2010 optimization compiler-construction