[英]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.