2016-10-19 7 views
5

간단한 MWE :유효하지 않은 주소를 프리 페치하면 어떻게됩니까?

int* ptr = (int*)malloc(64 * sizeof(int)); 
_mm_prefetch((const char*)(ptr + 64), _MM_HINT_0); 
  1. 이 정의되거나 정의되지 않은 동작이 있습니까?
  2. 신호를 발생시키고 프로그램 실행을 중단 할 수 있습니까?
내가 루프 프리 페치 내부 ( rbx에 저장) 주소를 확인하지 않고 수행 컴파일러 생성 된 코드, 이러한 프리 페치를 볼 수 있기 때문에 내가 부탁 해요

: 모든

400e73:  49 83 c5 40    add r13,0x40 
400e77:  62 f1 f9 08 28 03  vmovapd zmm0,ZMMWORD PTR [rbx] 
400e7d:  4d 3b ec    cmp r13,r12 
400e80:  62 d1 f9 08 eb 4d ff vporq zmm1,zmm0,ZMMWORD PTR [r13-0x40] 
400e87:  90      nop 
400e88:  62 d1 78 08 29 4d ff vmovaps ZMMWORD PTR [r13-0x40],zmm1 
400e8f:  72 03     jb  400e94 <main+0x244> 
400e91:  49 89 c5    mov r13,rax 
400e94:  62 f1 78 08 18 53 1d vprefetch1 [rbx+0x740] 
400e9b:  ff c1     inc ecx 
400e9d:  62 f1 78 08 18 4b 02 vprefetch0 [rbx+0x80] 
400ea4:  48 83 c3 40    add rbx,0x40 
400ea8:  81 f9 00 00 10 00  cmp ecx,0x100000 
400eae:  72 c3     jb  400e73 <main+0x223> 
+1

설명서를 보셨습니까? – fuz

+1

Intel Intrinsic Guide는 그것에 대해 아무 말도하지 않습니다. Intel Intrinsics Refernce도 아닙니다. Intel Xeon Phi 명령어 세트 참조 (분해 된 코드는 KNC 용으로 컴파일되었습니다). 내가 아는 한. 모든 프로그래머가 메모리에 대해 알아야 할 사항에 대해서만 설명했습니다. _ 프로그램은 _mm_prefetch 내장 함수를 프로그램의 모든 포인터에 사용할 수 있습니다. 대부분의 프로세서 (물론 모든 x86 및 x86-64 프로세서)는 유효하지 않은 포인터로 인한 오류를 무시하므로 프로그래머의 삶이 훨씬 쉬워집니다 ._ –

+0

좋은 점. 이 질문을하기 전에 확인해 주셔서 감사합니다. 그러한 중요한 세부 사항이 문서화되지 않은 채 남아 있다는 것에 흥미 롭습니다! – fuz

답변

4

첫째는 컴파일러는 그것을하거나 당신이 그것을하는 것은 이론에서 매우 다른 것들입니다. 그냥 동등한 것으로 보이기 때문에 컴파일러는 표현할 수 있는지 아니면 완전히 표준 C인지에 관계없이 작동하는 더러운 해킹을 사용할 수 있습니다.

물론 프리 페치는 신호를 생성하지 않습니다 * 만약 그렇다면 그것은 거의 쓸모가 없을 것입니다. TLB 미스를 트리거하는지 여부에 따라 일부 잘못된 포인터의 경우 매우 느릴 수 있습니다. 따라서 컴파일러는 안전하게 사용할 수 있지만 모든 것을 무차별로 사용해서는 안됩니다.

이제 포인터 연산을 사용하여 범위를 벗어난 포인터를 만들면 이론적으로는 UB이지만 포인터에 적용하면 UB의 종류가 대부분 어쨌든 작동합니다 (플랫 메모리를 사용하면 추가됩니다). , 컴파일러가이를 감지하지 못하면 컴파일러가 실패 할 수있는 유일한 방법은 동적 크기를 추론해야한다는 것입니다. 분명히 위의 경우는 SSE 내장 함수를 지원한다고 주장하는 컴파일러가 지원해야합니다. 그렇지 않으면이 답변에서 보여준 것처럼 합리적으로 프리 페칭을 사용할 수 없으며 표준의 맨 위에 추가 보장이 필요합니다. 수동에서

* :

PREFETCHh 명령은 단지 힌트 및 프로그램 동작에 영향을주지 않습니다.

신호는 프로그램 동작에 영향을 미치므로 생성 할 수 없습니다.

+0

경계 밖의 포인터를 만드는 것은 일반적인 아키텍처에서 잘 작동하지만, 미래의 컴파일러는 포인터를 계산하면 유효하며 컴파일러는 미리/시간적으로 그것을 역 참조 할 수 있으므로 정의되지 않은 행동이 유효하지 않은 경우. – fuz

+0

@FUZxxl IA64 컴파일러는 이미 그렇게했지만 괜찮습니다. 그래도, 그 포인터를 프리 페치에 사용하는 경우에는 최소한 * 깨뜨릴 수 없습니다. 그렇지 않으면 파손될 수 있습니다. – harold

+0

UB? 이것은 하드웨어로, 언어 표준이 아닙니다. – doug65536