6

限定修飾ポインターを使用しようとしましたが、問題が発生しました。以下のプログラムは、問題を提示するためだけの単純なものです。

calc_function は 3 つのポインターを使用しますが、これは制限されているため、相互にエイリアスを作成することはできません。Visual Studio でこのコードをコンパイルすると、関数がインライン化されるため、Visual Studio 2010 が修飾子を無視する理由はありません。インライン化を無効にすると、コードは 6 倍以上高速に実行されます (2200 ミリ秒から 360 ミリ秒)。しかし、プロジェクト全体またはファイル全体でインライン化を無効にしたくありません (たとえば、すべてのゲッターとセッターでオーバーヘッドが呼び出されるため、これは恐ろしいことです)。

(唯一の解決策は、この関数のみのインライン化を無効にすることでしょうか?)

関数の上部と内側のループの両方に一時的な制限修飾ポインターを作成して、エイリアシングがないことを約束することをコンパイラーに伝えようとしましたが、コンパイラーは私を信じません。仕事。また、コンパイラの設定を微調整しようとしましたが、機能することがわかった唯一の方法は、インライン化を無効にすることです。

この最適化問題を解決するための助けをいただければ幸いです。

プログラムを (realeasemode で) 実行するには、引数 0 1000 2000 を使用することを忘れないでください。ユーザー入力/プログラム引数を使用する理由は、ポインター間にエイリアシングがあるかどうかをコンパイラーが認識できないようにするためです。 a、b、およびc。

#include <cstdlib>
#include <cstdio>
#include <ctime>

// Data-table where a,b,c will point into, so the compiler cant know if they alias.
const size_t listSize = 10000;
int data[listSize];

//void calc_function(int * a, int * b, int * c){
void calc_function(int *__restrict a, int *__restrict b, int *__restrict c){
    for(size_t y=0; y<1000*1000; ++y){  // <- Extra loop to be able to messure the time.
        for(size_t i=0; i<1000; ++i){
            *a += *b;
            *c += *a;
        }
    }
}
int main(int argc, char *argv[]){ // argv SHALL be "0 1000 2000" (with no quotes)
    // init
    for(size_t i=0; i<listSize; ++i)
        data[i] = i;

    // get a, b and c from argv(0,1000,2000)
    int *a,*b,*c;
    sscanf(argv[1],"%d",&a);
    sscanf(argv[2],"%d",&b);
    sscanf(argv[3],"%d",&c);
    a = data + int(a);  // a, b and c will (after the specified argv) be,
    b = data + int(b);  // a = &data[0], b = &data[1000], c = &data[2000],
    c = data + int(c);  // So they will not alias, and the compiler cant know.

    // calculate and take time
    time_t start = clock();
        funcResticted(a,b,c);
    time_t end = clock();
    time_t t = (end-start);
    printf("funcResticted       %u (microSec)\n", t);

    system("PAUSE");
    return EXIT_SUCCESS;
}
4

1 に答える 1

3

で関数を宣言すると__declspec(noinline)、インライン化されないように強制されます。

http://msdn.microsoft.com/en-us/library/kxybs02x%28v=vs.80%29.aspx

これを使用して、関数ごとにインライン化を手動で無効にすることができます。


に関してはrestrict、コンパイラは必要な場合にのみ自由に使用できます。したがって、そのような最適化を行うためにコンパイラを「だます」ことを試みる場合、同じコードの異なるバージョンをいじることは、やや避けられません。

于 2012-07-15T20:43:20.853 に答える