【问题标题】:Why does sorting call the comparison function less often than a linear minimum search algorithm?为什么排序调用比较函数的频率低于线性最小搜索算法?
【发布时间】: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 中启用。

标签: c++ algorithm sorting


【解决方案1】:

像 O(N²) 这样的语句就像一个维度;点数翻倍,时间翻了四倍。 O(log N) 算法对于小的 N 可能会很慢,关键是如果 N 翻倍或增加 10 倍运行时间不会。

与在 1000 页的字典中查找特定单词和在 20 个单词的句子中查找特定单词进行比较。在找到特定单词之前对 20 个单词的句子进行排序比直接阅读一次需要更长的时间。

【讨论】:

  • 没错,但在这种情况下,排序实际上更快,这就是诀窍。
猜你喜欢
  • 1970-01-01
  • 2020-07-10
  • 1970-01-01
  • 1970-01-01
  • 2013-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
相关资源
最近更新 更多