2016-12-28 2 views
1

내 C 프로그램에서 Windows 10 Home을 실행하는 64 비트 Intel Corei5-2410M Sandy Bridge 컴퓨터의 클럭 사이클 수를 계산하지만 이상한 점이 있습니다. 릴리스 빌드에서 Code :: Blocks (CB) 16.01을 사용하여 -O2 및 -O3에서 프로그램을 컴파일합니다. -O2의 경우 클럭 사이클은 정상이지만 -O3은 0 사이클을 반환합니다. 현재로서는 터보 부스트 및 하이퍼 스레딩을 고려하지 않지만 나중에는 비활성화 할 것입니다.코드를 사용하여 -O3에서 클럭 사이클 수를 계산하는 방법 : Windows 10에서 16.01 블록?

나는 우리가 나는 rdtscp 명령을 사용하고

int32_t X[17], Y[9]; 
int64_t Z[9]; 
utype64 start, end; 
uint32_t i; 

srand(time(NULL)); 
for(i=0; i<17; i++) 
    X[i] = rand()%(uint32_t)pow(2.0, 29); 
srand(time(NULL)); 
for(i=0; i<9; i++) 
    Y[i] = rand()%(uint32_t)pow(2.0, 29); 

start=rdtsc(); 
end=rdtscp(); 
start=rdtsc(); 
for(i=0; i<10000000; i++) 
    schoolbook_9(X, Y, Z); 

end=rdtscp(); 
printf("\n%s%"PRIu64"\n", "The cycles count using SB of size 9 is :: ", (end-start)/10000000); 

을 다음과 같이 내가 클럭주기를 믿는다

void schoolbook_9(int32_t *X, int32_t *Y, int64_t *Z){ 
Z[0] = (int64_t)X[0]*Y[0] + (int64_t)X[1]*Y[1] + (int64_t)X[2]*Y[2] + (int64_t)X[3]*Y[3] + (int64_t)X[4]*Y[4] + (int64_t)X[5]*Y[5] + (int64_t)X[6]*Y[6] + (int64_t)X[7]*Y[7] + (int64_t)X[8]*Y[8]; 
Z[1] = (int64_t)X[9]*Y[0] + (int64_t)X[0]*Y[1] + (int64_t)X[1]*Y[2] + (int64_t)X[2]*Y[3] + (int64_t)X[3]*Y[4] + (int64_t)X[4]*Y[5] + (int64_t)X[5]*Y[6] + (int64_t)X[6]*Y[7] + (int64_t)X[7]*Y[8]; 
Z[2] = (int64_t)X[10]*Y[0] + (int64_t)X[9]*Y[1] + (int64_t)X[0]*Y[2] + (int64_t)X[1]*Y[3] + (int64_t)X[2]*Y[4] + (int64_t)X[3]*Y[5] + (int64_t)X[4]*Y[6] + (int64_t)X[5]*Y[7] + (int64_t)X[6]*Y[8]; 
Z[3] = (int64_t)X[11]*Y[0] + (int64_t)X[10]*Y[1] + (int64_t)X[9]*Y[2] + (int64_t)X[0]*Y[3] + (int64_t)X[1]*Y[4] + (int64_t)X[2]*Y[5] + (int64_t)X[3]*Y[6] + (int64_t)X[4]*Y[7] + (int64_t)X[5]*Y[8]; 
Z[4] = (int64_t)X[12]*Y[0] + (int64_t)X[11]*Y[1] + (int64_t)X[10]*Y[2] + (int64_t)X[9]*Y[3] + (int64_t)X[0]*Y[4] + (int64_t)X[1]*Y[5] + (int64_t)X[2]*Y[6] + (int64_t)X[3]*Y[7] + (int64_t)X[4]*Y[8]; 
Z[5] = (int64_t)X[13]*Y[0] + (int64_t)X[12]*Y[1] + (int64_t)X[11]*Y[2] + (int64_t)X[10]*Y[3] + (int64_t)X[9]*Y[4] + (int64_t)X[0]*Y[5] + (int64_t)X[1]*Y[6] + (int64_t)X[2]*Y[7] + (int64_t)X[3]*Y[8]; 
Z[6] = (int64_t)X[14]*Y[0] + (int64_t)X[13]*Y[1] + (int64_t)X[12]*Y[2] + (int64_t)X[11]*Y[3] + (int64_t)X[10]*Y[4] + (int64_t)X[9]*Y[5] + (int64_t)X[0]*Y[6] + (int64_t)X[1]*Y[7] + (int64_t)X[2]*Y[8]; 
Z[7] = (int64_t)X[15]*Y[0] + (int64_t)X[14]*Y[1] + (int64_t)X[13]*Y[2] + (int64_t)X[12]*Y[3] + (int64_t)X[11]*Y[4] + (int64_t)X[10]*Y[5] + (int64_t)X[9]*Y[6] + (int64_t)X[0]*Y[7] + (int64_t)X[1]*Y[8]; 
Z[8] = (int64_t)X[16]*Y[0] + (int64_t)X[15]*Y[1] + (int64_t)X[14]*Y[2] + (int64_t)X[13]*Y[3] + (int64_t)X[12]*Y[4] + (int64_t)X[11]*Y[5] + (int64_t)X[10]*Y[6] + (int64_t)X[9]*Y[7] + (int64_t)X[0]*Y[8];} 

mingw32-gcc.exe -Wall -O2 -m32 -IC:\GMP\include -c "E:\abc\main.c" -o obj\Release\main.o 
mingw32-gcc.exe -Wall -O3 -m32 -IC:\GMP\include -c "E:\abc\main.c" -o obj\Release\main.o 

을 컴파일 다음 명령을 사용하여 내 시스템이 지원하기 때문에 32 비트 시스템에서는 사용할 수 없기 때문에 프로그램을 테스트했습니다. th와 함께/밖으로 rdtscp. 인수 X, Y 및 Z는 X와 Y가 32 비트이고 Z가 64 비트 인 배열입니다.

제 질문은 -O3에서주기를 계산하는 방법입니다. 왜냐하면 현재 코드에서는 0 사이클을 얻습니다.

flage -ftree-loop-vectorize은이 페이지 https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html에 설명 된대로 -O3으로 설정됩니다. 루프가 벡터화되었다는 의미입니까? 그렇다면 벡터의 길이 (4 요소, 6 요소 등)를 어떻게 결정할 수 있습니까?

+0

예, 몇 분 안에 질문을 업데이트하겠습니다. 나는 rdtsc()와 rdtscp()를 두 번 호출하지만 실제로 G. Paoloni의 백서에서 세 번 호출하는 것이 좋습니다 (http://www.intel.com/content/dam/www/public/us/en). /documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf – user110219

+1

'pow (2.0, 29);'->'1 << 29' –

답변

0

end - start10000000보다 작고 -O3이기 때문입니다. 귀하의 부서는 0을 생산합니다.

utype64 result = end - start; 
utype64 cycle = 10000000; 
utype64 total = result/cycle; 
utype64 rest = result % cycle; 
printf("The cycles count using SB of size 9 is " PRIu64 
     " and the rest is " PRIu64 "\n", 
     total, rest); 

그리고 두 번 전화하지 마십시오. srand(time(NULL));. 쓸데없고 이상한 행동을 일으킬 수 있습니다.

참고 : 직접 테스트 할 수 없습니다.

+0

네, 맞습니다. * (end-start) * <10000000이고 그 이유는 -O3에서 0이됩니다. 이것이 제가 -O3을 위해 무엇을해야하는지 묻고있는 이유입니다. 논리적으로 * end *가 항상 * start *보다 클 것이라고 생각하지 않습니까? 그렇다면 왜 utype64 result = * end *> * start *입니까? * end * - * start * : * start * - * end *; ? – user110219

+0

@ user110219 왜 내가 그런 짓을했는지 기억이 안납니다. 내가 더 이상 당신의 질문을 이해하지 못한다. 0이기 때문에 사이클 번호가 있습니다. 문제가 보이지 않습니다. 아마도 ['clock_gettime()'] (https://linux.die.net/man/3/clock_gettime)을 사용할 수 있습니다. – Stargateur

+0

@ user110219'-O [0 | 1 | 2 | 3]'최적화와 다른 점이 없어야 동작이 바뀌지 않아야합니다. 변경되는 유일한 것은 프로그램이 더 빠릅니다. – Stargateur