在我的CPU光线追踪器(实际上是路径追踪器)中,大部分CPU时间都花费在BVH遍历函数中。根据我的性能分析器,75%的光线追踪时间都花费在这个函数及其调用的函数上,而35%的时间则花费在函数本身上。其他40%的时间则花费在它调用的不同相交测试上。
基本上,代码通过所有与之相交的边界框和三角形进行深度优先搜索遍历。它使用静态分配的堆栈上的数组来保存要探索的节点(BVHSTACKSIZE设置为32,大多数情况下不需要该空间),以便不会动态分配内存。然而,我觉得35%的时间在这里花费太高了。我已经花了一段时间来优化代码,目前已经是我能做到的最快速度,但它仍然是我的程序中最大的瓶颈。
有没有人有更好的优化建议?我已经有一个不错的BVH构造算法了,所以我认为使用不同的BVH也不会有任何加速效果。有没有人有关于如何在Mac上进行逐行性能分析的最佳方法?
供参考,在一个示例场景中,这段代码根据相交数量需要花费1微秒到40微秒不等的时间,而while循环则运行1到约400次迭代(也取决于相交数量)。
谢谢!
基本上,代码通过所有与之相交的边界框和三角形进行深度优先搜索遍历。它使用静态分配的堆栈上的数组来保存要探索的节点(BVHSTACKSIZE设置为32,大多数情况下不需要该空间),以便不会动态分配内存。然而,我觉得35%的时间在这里花费太高了。我已经花了一段时间来优化代码,目前已经是我能做到的最快速度,但它仍然是我的程序中最大的瓶颈。
有没有人有更好的优化建议?我已经有一个不错的BVH构造算法了,所以我认为使用不同的BVH也不会有任何加速效果。有没有人有关于如何在Mac上进行逐行性能分析的最佳方法?
供参考,在一个示例场景中,这段代码根据相交数量需要花费1微秒到40微秒不等的时间,而while循环则运行1到约400次迭代(也取决于相交数量)。
谢谢!
bool BVHAccel::intersect(Ray& ray) const {
bool hit = false;
BVHNode* to_intersect[BVHSTACKSIZE];
int head = 0;
to_intersect[head++] = root;
while (head != 0) {
assert(head < BVHSTACKSIZE);
BVHNode* cur = to_intersect[--head];
if (cur->bb.intersect(ray)) { // Does not modify the ray
if (cur->isLeaf()) {
for (const auto& primitive : cur->primitives) {
hit |= primitive->intersect(ray); // Modifies the ray!
}
} else {
to_intersect[head++] = cur->r;
to_intersect[head++] = cur->l;
}
}
}
return hit;
}
bool BBox::intersect(const Ray& r) const {
double txmin = (min.x - r.o.x) * r.inv_d.x;
double txmax = (max.x - r.o.x) * r.inv_d.x;
double tymin = (min.y - r.o.y) * r.inv_d.y;
double tymax = (max.y - r.o.y) * r.inv_d.y;
double tzmin = (min.z - r.o.z) * r.inv_d.z;
double tzmax = (max.z - r.o.z) * r.inv_d.z;
ascending(txmin, txmax);
ascending(tymin, tymax);
ascending(tzmin, tzmax);
double t0 = std::max(txmin, std::max(tymin, tzmin));
double t1 = std::min(txmax, std::min(tymax, tzmax));
if (t1 < t0 || t0 > r.max_t || t1 < r.min_t) {
return false;
}
return true;
}
void ascending(double& a, double& b) {
if (a > b) {
std::swap(a, b);
}
}