簡體   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