5

所以我正在创建一个包含类 someBase {}; 的库。它将由下游用户在多个类中派生。

class someBase {
  public:
    virtual void foo()=0;
};

我还有一个指向 someBase 的指针向量,我正在这样做:-

vector <someBase*> children;

// downstream user code populates children with some objects over here

for (i=0; i<children.size(); i++)
  children[i]->foo();

现在分析表明,对虚拟调用的分支错误预测是我的代码中的一个(几个)瓶颈。我想做的是以某种方式访问​​对象的 RTTI,并使用它根据类类型对子向量进行排序,以改善指令缓存局部性和分支预测。

关于如何做到这一点的任何建议/解决方案?

要记住的主要挑战是:-

1.) 我真的不知道哪些类或多少类将从 someBase 派生。假设,我可以在某个公共文件的某个地方有一个全局枚举,下游用户可以编辑它以添加他们自己的类类型,然后对其进行排序(基本上实现我自己的 RTTI)。但这是一个丑陋的解决方案。

2.) PiotrNycz 在下面的回答中建议使用 type_info。但是,只有 != 和 == 是为此定义的。关于如何在 type_info 上得出严格的弱排序的任何想法?

3.) 我真的很想改进分支预测和指令缓存局部性,所以如果有替代解决方案,那也将受到欢迎。

4

2 回答 2

4

typeid运营商。

您可以使用它来定义比较器以对向量中的对象进行排序。

像这样:

inline bool compareTypes(BaseClass* obj1, BaseClass* obj2)
{
   int compareRes = strcmp(typeid(*obj1).name(), typeid(*obj2).name());
   if (compareRes < 0) return true;
   if (compareRes > 0) return false;
   std::less<BaseClass*> ptrComp;
   return ptrComp(obj1, obj2); 
}

和:

  sort(v.begin(), v.end(), compareTypes);

[更新]

感谢您指出我有一个为此目标设计的功能。所以std::type_info::before(const type_info&) const比较器将像这样简单:

inline bool compareTypes(A* obj1, A* obj2)
{
   return typeid(*obj1).before(typeid(*obj2));
}

我的早期版本还不错;)它可用于需要对给定类的对象进行排序的情况。

于 2012-09-19T20:12:43.403 回答
0

您可以在初始化中按类型对指针进行一次分类,例如:

std::vector<derivedA*> derivedA_list;
std::vector<derivedB*> derivedB_list;
//...

for (i=0; i<children.size(); i++)
    if (derivedA *d = dynamic_cast<derivedA*>(children[i]))
        derivedA_list.push_back(d);
    else if (derivedB *d = dynamic_cast<derivedB*>(children[i]))
        derivedB_list.push_back(d);
    //...

然后调用该函数,您可以进行非虚拟调用:

for (i=0; i<derivedA.size(); ++i)
    derivedA_list[i]->derivedA::foo();
for (i=0; i<derivedB.size(); ++i)
    derivedB_list[i]->derivedB::foo();

另请注意,使用迭代器的循环可能会得到更好的优化。

于 2012-09-19T20:18:09.087 回答