1

以下のコードは、「REPLACING WITH ..」行の近くにある場合、4 倍高速に実行されます。ファンクターの compare_swaps() は、my_intcmp() への直接参照に置き換えられます。どうやら間接的な使用はインライン化されていません。なんで?

inline bool my_intcmp( const int & a, const int & b ) {
        return a < b;
}


template <class T, class compare>
void insertion_sort_3( T* first, T* last, compare compare_swaps ) {
    // Count is 1?
    if( 1 == (last - first) )
        return;

    for( T* it = first + 1; it != last; it ++ ) {
        T val = *it;
        T* jt;

        for( jt = it; jt != first; jt -- ) {
            // REPLACING WITH if( my_intcmp(val, *(jt - 1) ) gives 4x speedup, WHY?
            if( compare_swaps(val, *(jt - 1)) ) {
                *jt = *(jt - 1);
            } else {
                break;
            }
        }

        *jt = val;
    }
}

#define SIZE 100000
#define COUNT 4

int main() {
    int myarr[ SIZE ];

    srand( time(NULL) );

    int n = COUNT;
    while( n-- ) {
        for( int i = 0; i < SIZE; i ++ )
            myarr[ i ] = rand() % 20000;

        insertion_sort_3( myarr, myarr + SIZE, my_intcmp );
    }

    return 0;
}
4

1 に答える 1

3

コンパイラーは、実際には変更されていないと判断できない関数ポインターを認識します。私はこれを数回前に見たことがあります。この問題を解決するには、単純なラッパーを使用しますstruct

struct my_intcmp_wrapper
{
    bool operator()(int v0, int v1) const {
        return my_intcmp(v0, v1);
    }
};

特に組み込み型の場合は、オブジェクトを参照ではなく値で渡したいと思うでしょう。インライン化された関数の場合、おそらく大きな違いはありませんが、関数がインライン化されていない場合、一般的に状況が悪化します。

于 2012-10-03T23:45:24.460 に答える