仅测试集合集合中的每个元素一次

时间:2014-08-17 18:22:46

标签: c++ c++11 optimization

我正在为x86消费者硬件编写CPU光线跟踪器(在C ++ 11中,到目前为止使用gcc 4.7.1)。

我正在使用一个持有三角形的kD树,并且用我给定的光线将叶子中的所有三角形相交。此任务根据我的探查器占用大部分运行时间(取决于kd-tree以及大约50%或更多运行时的输入和选择参数)。

for (auto p : leaf.triangles) {
    p->intersect(ray, t, intersection); //void intersect(const Ray& ray, float t, Intersection& output)
}

(p是指向矢量中其他位置的三角形的类型指针。)

我的kd树可能会更深,但这迫使我有更多的叶子共享同一个三角形。因为我经常被迫测试相邻的叶子,所以我最终将一遍又一遍地交叉相同的三角形。到目前为止,这可能是我最大的瓶颈。

一个简单的解决方案似乎是某种列表,可以保留我已经交叉的所有指针。我决定使用unordered_set<Triangle*>因为findemplace的平均费用不变。

unordered_set<Triangle*> alreadyTested; //used for all leafs a ray visits
for (auto p : leaf.triangles) {
     if (alreadyTested.find(p) == alreadyTested.end()) {
          p->intersect(ray, t, intersection);
          alreadyTested.emplace(p);
     }
}

使用GCC -O3编译

我的运行时整体增加了4到8倍。我的探查器告诉我,findemplace大约需要一个intersect取消任何速度加值。错过的跳跃预测可能是大幅放缓的原因。

我该怎么做(“它”每个三角形只调用一次相交)?

1 个答案:

答案 0 :(得分:1)

您可以继续对光线进行计数,并将与三角形相交的最后一条光线的索引直接存储在三角形中。如果你是多线程的,你可以通过线程索引拥有多个这样的值和索引。

由于重新散列,

emplace可能会花费很多时间。您可以使用从最后一帧收集的统计信息(对于相同的光线,或者只是所有光线的上限),为unordered_set构造函数指定更好的初始桶数。