【发布时间】:2016-06-19 12:40:18
【问题描述】:
我将首先提供一些背景信息。我正在学习写一个光线追踪器,一个非常简单的。我还没有任何加速结构,所以有问题的代码旨在找到射线击中的最近物体。由于我还在学习,如果答案集中在我观察到的看似奇怪的问题上,我将不胜感激 - 我知道 RT 逻辑现在是非常错误的。无论如何,它会产生正确的结果。
1. 第一种方法:对于每个命中,将一个命中结果结构对象添加到列表中,然后将std::sort 与一个比较命中点到射线距离的谓词应用起源。根据教科书应该是O(N log N),我认为这是次优的,因为我只需要第一个结果,而不是整个排序列表。
2. 第二种方法:每当有命中时,取距离并与最小值进行比较,该最小值首先初始化为std::numeric_limits<float>::max()。好吧,您的标准“在数组中查找最小值”算法。应该是O(N),因此速度更快。
这些代码位于递归函数中。在 10 个球体的相同场景上进行测试,1 快了一个数量级。距离函数的调用量比2少几倍。我错过了什么? 我不确定是否需要上下文,如果这个问题有“要切断的分支”,请告诉我。
代码片段 1:
result rt_function(...) {
static int count{};
std::vector<result> hitList;
for(const auto& obj : objList) {
const result res = obj->testOuter(ray);
if ( res.hit ) {
hitList.push_back(res);
}
}
if (!hitList.empty()) {
sort(hitList.begin(), hitList.end(), [=](result& hit1, result& hit2) -> bool {
std::cerr << ++count << '\n';
return cv::norm(hit1.point - ray.origin) <
cv::norm(hit2.point - ray.origin);
});
const result res = hitList.front();
const SceneObject* near = res.obj;
// the raytracing continues...
计数 == 180771
代码片段 2:
result rt_function(...) {
static int count{};
float min_distance = std::numeric_limits<float>::max(), distance{};
result closest_res{}; bool have_hit{};
for(const auto& obj : objList) {
const result res = obj->testOuter(ray);
if ( res.hit ) {
have_hit = true;
std::cerr << ++count << '\n';
distance = cv::norm(res.point - ray.origin);
if (distance < min_distance) {
min_distance = distance; closest_res = res;
}
}
}
if (have_hit) {
const result res = closest_res;
const SceneObject* near = res.obj;
// the raytracing continues...
计数 == 349633
我想 (a) 了解为什么比较少以及 (b) 瓶颈在哪里,因为运行时间明显更长,因为我已经如上所述。
【问题讨论】:
-
在我看来,代码 sn-p 1 的计数大约是代码 sn-p 2 的两倍,与您的描述相反。
-
@user2357112 哎哟明白了,很好!
-
@templatetypedef 改为通过引用捕获,得到 180807,有点变化,但仍然不多。无论如何,我正在使用
ray变量的捕获。 -
您有没有机会使用相同的
count变量运行这些? -
@user2357112 对不起,我不确定我明白了吗?这些代码位于不同的 git 分支中。我签出一个分支,添加计数语句,构建,并在有和没有计数语句的情况下运行几次。在这两种情况下,2 都比较慢。
-O3在 gcc 中启用。