2

我有一个类似于这个的容器。

template <typename Nat, typename Elt>
class NatMap {
 public:
  Elt& operator[] (Nat nat) { 
    return tab [nat.GetRaw()];
  }
 private:
  Elt tab [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)];
};

我使用 g++-4.3,这段代码在我的应用程序中的运行速度比前一个慢 25% 。不幸的是,放缓并未体现在综合基准中。我想这与编译器优化、别名、对齐或类似的东西有关。

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

更新:

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

dereferencing pointer '<anonymous>' does break strict-aliasing rules
4

2 回答 2

1

您可能会遇到对齐问题。如果 Elt 的大小不是本机对齐类型,那么通过放置将其分配到字符数组中可能会涉及许多未对齐的读取,当编译器为您对齐时您看不到这些读取。或者您可能会遇到一个称为加载命中存储的问题,一些处理器在将值写入内存然后立即将其读回时会表现出来;在那些处理器中,它可能与管道一样长。

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

不幸的是,堆栈跟踪无助于追踪这些问题中的任何一个,因为它们看起来就像一个加载操作(lw,lb等),需要四十个周期而不是一个。停顿在 CPU 内部的微码中,而不是您编写的 x86 代码中。但是使用-S命令行选项查看程序集可以帮助您弄清楚编译器真正发出了什么,以及它在您的两个实现之间有何不同。也许在一个版本中出现了一些不好的操作。

于 2009-11-03T02:43:49.217 回答
0

小建议:与其尝试做出有根据的猜测,例如编译器优化是否不同,您可以单步执行,也可以使用这种非正统的方法找出答案。

于 2009-10-30T16:22:36.227 回答