2012-07-15 40 views
7

我試圖使用限制限定指針,並且遇到了問題。 下面的程序只是一個簡單的問題。限制指針和內聯

calc_function使用三個指針,它們是受限制的,所以它們「應該」不會互相混淆。在Visual Studio中編譯此代碼時,該函數將被內聯,因此無論如何,Visual Studio 2010都會忽略限定符。如果我禁用內聯,代碼執行速度會提高六倍(從2200ms到360ms)。但我不想在整個項目中禁用內聯,也不想在整個文件中禁用內聯(因爲那樣會在例如所有getter和setter中調用開銷,這會很糟糕)。

(也許是唯一的解決方案是僅禁用此功能,內聯?)

我試圖創建臨時的功能限制合格的指針,無論是在頂部和內部循環,試圖告訴編譯器,我保證沒有別名,但編譯器不會相信我,它不會工作。 我也嘗試調整編譯器設置,但唯一一個我發現的工作,是禁用內聯。

我希望有一些幫助來解決這個優化問題。

要運行程序(在realeasemode中)不要忘記使用參數0 1000 2000. 爲什麼使用userinput/program參數是爲了確保編譯器不知道是否存在或不存在'指針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; 
} 
+1

+1,用於良好的性能分析實踐。我會選擇不抱怨格式說明符。附: 'clock'返回'clock_t',而不是'time_t'。 – Hurkyl 2012-07-15 20:47:17

+1

嘗試通過檢查偏移量足夠大來檢查函數調用。儘管你可能不得不使用真正的'int'變量來存儲偏移量,而不是你使用的黑客。 – Hurkyl 2012-07-15 20:55:02

+0

@Hurkyl我認爲clock_t和time_t都是typedef同一件事,但你是對的。 (順便說一句,我如何編輯我的問題?) – Boll 2012-07-15 21:28:17

回答

3

如果聲明與__declspec(noinline)的功能,這將迫使它不能被內聯:

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

您可以在每個函數的使用該手動禁用內聯。


至於restrict,編譯器只有當它想要時纔可以使用它。所以試圖「欺騙」編譯器來做這種優化時,擺弄不同版本的相同代碼是不可避免的。

+0

該解決方案適用於問題中的測試代碼以及​​我的真實應用程序。但是,如果一個非常小的函數被調用很多次,它們都會需要受限的限定指針,其中__declspec(noinline)會強制執行相當大的調用開銷。因此,我會一直接受這個最好的答案。 – Boll 2012-07-15 21:54:28

+0

是的,我知道你的意思。我的猜測是,VS2010中使用的指針別名分析僅在功能級粒度。所以它無法區分在函數中間「生成」的非別名指針。我不確定是否可以在局部聲明的指針上使用「restrict」。如果確實如此,可能會嘗試。 – Mysticial 2012-07-15 22:00:16

+0

你是完全正確的,我試圖使用本地聲明指針與限制沒有運氣。你的「__declspec(noinline)」是最好的解決方案,並且適用於我目前的情況(我的應用程序),所以我接受它作爲答案。謝謝。 – Boll 2012-07-16 10:01:17