Performance 奇怪的性能问题

Performance 奇怪的性能问题,performance,g++,pointers,alignment,aliasing,Performance,G++,Pointers,Alignment,Aliasing,我有一个和这个相似的容器 template <typename Nat, typename Elt> class NatMap { public: Elt& operator[] (Nat nat) { return tab [nat.GetRaw()]; } private: Elt tab [Nat::kBound]; }; 模板 类NatMap{ 公众: Elt&运算符[](Nat-Nat){ return选项卡[nat.GetRaw()];

我有一个和这个相似的容器

template <typename Nat, typename Elt>
class NatMap {
 public:
  Elt& operator[] (Nat nat) { 
    return tab [nat.GetRaw()];
  }
 private:
  Elt tab [Nat::kBound];
};
模板
类NatMap{
公众:
Elt&运算符[](Nat-Nat){
return选项卡[nat.GetRaw()];
}
私人:
英语教学标签[Nat::kBound];
};
我想放弃Elt必须有默认构造函数的要求:

template <typename Nat, typename Elt>
class NatMap {
 public:
  Elt& operator[] (Nat nat) { 
    return ((Elt*)tab) [nat.GetRaw()];
  }
 private:
  char tab [Nat::kBound * sizeof(Elt)];
};
模板
类NatMap{
公众:
Elt&运算符[](Nat-Nat){
返回((Elt*)选项卡)[nat.GetRaw()];
}
私人:
字符选项卡[Nat::kBound*sizeof(Elt)];
};
我使用g++-4.3,这段代码在我的应用程序中比前一段代码慢25%。不幸的是,经济放缓并没有体现在一个综合基准中。 我猜这是关于编译器优化、别名、对齐或类似的东西

我该怎么做才能恢复我的表现?(不需要默认构造函数)

更新:

刚才我尝试了新的g++-4.4,它对后面的代码给出了以下警告:

dereferencing pointer '<anonymous>' does break strict-aliasing rules
取消引用指针“”会破坏严格的别名规则

小建议:不要试图做出有根据的猜测,比如编译器优化是否不同,你可以单步执行,或者找出答案。

你可能会遇到对齐问题。如果Elt不是本机对齐类型,那么通过将其放置到字符数组中来分配它可能会涉及大量未对齐的读取,而编译器为您对齐时您看不到这些读取。或者,您可能遇到了一个称为加载命中存储的问题,一些处理器在将值写入内存并立即将其读回时会显示该问题;在这些处理器中,它可以是一个与管道一样长的暂停

或者它可能完全是另一种东西,GCC生成的某种病态代码


不幸的是,堆栈跟踪无法帮助跟踪这两个问题,因为它们看起来就像一个加载操作(
lw
lb
,等等),需要40个周期而不是一个周期。暂停在CPU内部的微码中,而不是您编写的x86代码中。但是使用
-S
命令行选项查看程序集可以帮助您了解编译器真正发出的是什么,以及两种实现之间的区别。可能某个版本中出现了一些错误操作。

您使用的是
placement new
还是其他一些丑陋的黑客?不需要默认的ctor可以通过定义至少一个ctor来解决。Placement new不是一个难看的hack,而是一个基本的语言特性。通常它被很好地包装在像vector这样的容器中,所以人们认为它是模糊的。请不要这样做,这只是调用现有对象的构造函数的一种方式。为了回答你的问题,我不使用新的布局,但是我会的,因为我必须实现一个容器,它支持在公共场合只有命名构造函数的对象。注意:容器必须足够的透明,这样我就可以在包含它的对象上使用memcpy。下面是一个非常有用的答案。迈克,我不是在搜索算法中慢的部分。数组访问是必不可少的,我想知道为什么在上面的例子中,我得到的二进制文件要慢25%。在这种情况下,在指令级单步执行每个程序是一种简单的方法。他们在做不同的事情。取样也会告诉你。也许我误解了你。也许你知道他们在做什么,你只想知道为什么。。。。事实上,有时我会在IDE/调试器的两个实例中并排执行两个程序,这样我就可以看到它们的区别。它可能有点慢,但见鬼,我也是:-)看看源代码,程序在源代码级别是相同的(就分步调试而言)-即使并行执行也是相同的。只有汇编器会有帮助,但这是不可能的,因为由于整个程序的优化,更改代码中的一行会以混乱的方式影响汇编输出的所有重要部分。所以这也没用。并排运行组件。。。也许吧,但是怎么做呢?即使是gdb也不知道哪个生产线负责70%的生产线。我知道我在说什么,我去过那里,我就是这么说的。编写两个小应用程序,一个是单向的,另一个是双向的,以便删除所有其他变量。来源不完全相同。然后在组装级别执行步骤。如果gdb不能显示源代码行和反汇编,那么获取一个混合源程序集列表,并按照该列表进行操作。这并不混乱。如果编译器对代码的置乱太多,请关闭优化。您将能够理解编译器所做的工作。我也去过。我会调查一下,但英语教学几乎总是整数大小的。atributte((aligin))也没有帮助。属性(align)将被放置在char数组中的新闻所阻止;毕竟,你可以告诉它放在任意地址上。