繁体   English   中英

可以使用通用方法来减少算法执行的平均工作量吗?

[英]Can a generic approach be used to reduce average effort performed by algorithms?

我遇到(并编写了)代码,其中在布尔关系表达式中自然使用标准模板库会导致(可能)浪费精力。

例如,

if (std::distance(begin, end) <= 2) { ... }

要么:

if (std::count(begin,end,val) >= 3) { ... }

在这两种情况下,都可以编写自定义算法,以避免在部分评估范围后知道答案时避免不必要的迭代/评估。

有没有一种通用的方法可以用来防止在这种情况下浪费精力?

编辑:试图解决“关闭”投票。

例如,我可以实现bool distance_at_least(begin, end, 3) bool distance_at_most(begin, end, 2) bool count_at_least(begin, end, val, 5)等。

我要求一种可用于所有这些类型的查询的(通用)方法。

编辑:这是一个变体的解决方案的模型,它试图传达为什么我不愿意写许多变体。

#include <vector>
#include <list>

namespace DETAIL {

    template <class ITER, class CAT>
    bool distance_at_least_dispatch(ITER begin, ITER end, typename std::iterator_traits<ITER>::difference_type n, CAT)
    {
        while (begin != end && n > 0) {
            ++begin;
            --n;
        }
        return n == 0;
    }

    template <class ITER>
    bool distance_at_least_dispatch(ITER begin, ITER end, typename std::iterator_traits<ITER>::difference_type n, std::random_access_iterator_tag)
    {
        return std::distance(begin, end) >= n;
    }
}

template <class ITER>
bool distance_at_least(ITER begin, ITER end, typename std::iterator_traits<ITER>::difference_type n)
{
    using CAT = typename std::iterator_traits<ITER>::iterator_category;
    return DETAIL::distance_at_least_dispatch(begin, end, n, CAT());
}

int main(int argv, char* argc[])
{
    std::vector<int> v;
    std::list<int> l;
    std::generate_n(std::back_inserter(v), 5, std::rand);
    std::generate_n(std::back_inserter(l), 5, std::rand);

    std::cout << distance_at_least(v.begin(), v.end(), 3) << std::endl;
    std::cout << distance_at_least(v.begin(), v.end(), 5) << std::endl;
    std::cout << distance_at_least(v.begin(), v.end(), 6) << std::endl;
    std::cout << distance_at_least(l.begin(), l.end(), 3) << std::endl;
    std::cout << distance_at_least(l.begin(), l.end(), 5) << std::endl;
    std::cout << distance_at_least(l.begin(), l.end(), 6) << std::endl;

    return 0;
}

我认为这里的主要问题应该是std::count(b,e,v) < 2是否对像样的编译器那么糟糕。 这是一个模板函数,因此完整的实现在调用时可用,并且它是一个相当简单的函数。 这使其成为内联的主要候选人。 这意味着优化器将看到将计数返回值与<2进行比较,后跟一个分支。 还可以看到计数一次增加一,并且没有副作用。

因此,可以重新排列代码,移动分支并消除循环的冗余部分。

在伪代码中,未优化:

count = 0
:loop
if (*b==v) ++count
++b
if(b!=e) goto loop
if(count >=2) goto past_if
// Then-block
:past_if

现在进行了优化

count = 0
:loop
if (*b==v) ++count
if(count>=2) goto past_if
++b
if(b!=e) goto loop
// Then-block
:past_if

如您所见,这是一个简单的重新排序。 仅一行移动。 这不是火箭科学,一个不错的优化程序应该能够弄清楚这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM