2012-07-15 2 views
7

제한된 포인터를 사용하려고했지만 문제가 발생했습니다. 아래의 프로그램은 문제를 제시하기위한 간단한 프로그램입니다.포인터 및 인라인 제한

calc_function은 세 개의 포인터를 사용하며,이 포인터는 서로 별칭이 아니므로 "SHALL"로 제한됩니다. Visual Studio에서이 코드를 컴파일 할 때 함수가 인라인되므로 아무 이유없이 Visual Studio 2010에서 한정자를 무시합니다. 인라이닝을 비활성화하면 코드가 6 번 더 빠르게 실행됩니다 (2200ms에서 360ms로). 하지만 전체 프로젝트 나 전체 파일에서 인라인을 비활성화하고 싶지는 않습니다 (예 : 모든 게터와 세터에서 오버 헤드가 발생하여 끔찍할 것입니다).

는 (유일한 솔루션은이 함수의 인라인을 비활성화 할 수 있습니다?) 내가 말하려고 임시가 상단 및 내부 루프에서 모두 함수에 자격을 갖춘 포인터를 제한 만들려고 한

컴파일러는 에일리어싱이 없다고 약속하지만 컴파일러는 나를 믿지 않을 것이며 작동하지 않을 것입니다. 나는 또한 컴파일러 설정을 조정하려고했지만, 내가 찾은 유일한 것은 인라인을 비활성화하는 것입니다.

이 최적화 문제를 해결하는 데 도움을 주셔서 감사합니다.

0 1000 2000을 사용하는 것을 잊지 마세요. 사용자 입력/프로그램 인수를 사용하는 이유는 컴파일러가 컴파일러가 ' 포인터들 a, b, c 사이의 에일리어싱. 당신이 __declspec(noinline)으로 함수를 선언하면

#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'은'time_t'가 아니라'clock_t'를 리턴합니다. – Hurkyl

+1

오프셋이 충분히 큰지 확인하여 함수 호출을 지키십시오. 실제로 사용 된 해킹이 아니라 실제 int 변수를 사용하여 오프셋을 저장해야합니다. – Hurkyl

+0

@Hurkyl 나는 clock_t와 time_t가 똑같은 typedefs라고 생각했지만 당신은 옳았다. (Btw, 어떻게 내 질문 - 게시물을 편집합니까?) – Boll

답변

3

, 그것이이 인라인되지 강제 :

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

당신은 함수 단위에 수동으로 인라인을 사용하지 않도록 설정할 수 있습니다.


restrict의 경우 컴파일러는 원하는 경우에만 자유롭게 사용할 수 있습니다. 컴파일러가 그러한 최적화를 수행하도록 "속이려"시도 할 때 같은 코드의 서로 다른 버전으로 주변을 둘러 보는 것은 다소 피할 수없는 일입니다.

+0

이 솔루션은 문제의 테스트 코드와 실제 응용 프로그램에서 모두 작동합니다. 그러나 __declspec (noinline)이 매우 큰 호출 오버 헤드를 요구하는 매우 제한된 수의 포인터가 여러 번 호출되는 아주 작은 함수에 필요한 경우 몇 가지 문제가 있습니다. 그러므로 나는 이것을 최상의 대답으로 받아들이면서 기다릴 것입니다. – Boll

+0

네가 무슨 뜻인지 알 겠어. 내 생각 엔 VS2010에서 사용 된 포인터 별칭 지정 분석은 함수 수준의 세밀도에서만 사용된다는 것입니다. 그래서 함수의 중간에서 "생성 된"앨리어스가없는 포인터를 구별 할 수 없습니다. 나는'restrict'가 국지적으로 선언 된 포인터에서 사용될 수 있는지 확신하지 못합니다. 그렇게된다면, 시도해 볼만한 것일 수도 있습니다. – Mysticial

+0

당신은 완전히 옳았고 제한적으로 행운이있는 지역에서 선언 된 포인터를 사용하려고했습니다.귀하의 "__declspec (noinline)"최고의 솔루션이며, 현재의 경우 (내 응용 프로그램)에서 작동하므로 답변으로 받아들입니다. 감사. – Boll