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