rdtscp, rdtsc: 메모리와 cpuid/rdtsc의 차이점
성능 모니터링에 TSC를 사용하고 명령어 순서를 변경하는 것을 방지한다고 가정합니다.
옵션은 다음과 같습니다.
1: rdtscp
을 사용하다「rdtscp」는, 「rdtscp」로, 「rdtscp는, 「rdtscp」를 참조해 주세요.
__asm__ __volatile__("rdtscp; " // serializing read of tsc
"shl $32,%%rdx; " // shift higher 32 bits stored in rdx up
"or %%rdx,%%rax" // and or onto rax
: "=a"(tsc) // output to tsc variable
:
: "%rcx", "%rdx"); // rcx and rdx are clobbered
★★★★★★★★★★★★★★.rdtscp
CPU를 사용합니다. 이 에는 ''를 사용해야 .rdtsc
rdtsc
는 비시리얼라이즈이기 때문에 그것만 사용해도 CPU의 순서를 변경할 수 있습니다.
따라서 다음 두 가지 옵션 중 하나를 사용하여 순서 변경을 방지할 수 있습니다.
2: 이 전화는cpuid
다음에 또 한 번.rdtsc
cpuid
을 사용하다
volatile int dont_remove __attribute__((unused)); // volatile to stop optimizing
unsigned tmp;
__cpuid(0, tmp, tmp, tmp, tmp); // cpuid is a serialising call
dont_remove = tmp; // prevent optimizing out cpuid
__asm__ __volatile__("rdtsc; " // read of tsc
"shl $32,%%rdx; " // shift higher 32 bits stored in rdx up
"or %%rdx,%%rax" // and or onto rax
: "=a"(tsc) // output to tsc
:
: "%rcx", "%rdx"); // rcx and rdx are clobbered
3: 이 전화는rdtsc
memory
재주문 되어 있습니다.
__asm__ __volatile__("rdtsc; " // read of tsc
"shl $32,%%rdx; " // shift higher 32 bits stored in rdx up
"or %%rdx,%%rax" // and or onto rax
: "=a"(tsc) // output to tsc
:
: "%rcx", "%rdx", "memory"); // rcx and rdx are clobbered
// memory to prevent reordering
세 번째 옵션에 대한 저의 이해는 다음과 같습니다.
을 발신하다__volatile__
에서는 asm의 결과를 필요로 하는(또는 입력을 변경하는) 명령 간에 최적기가 asm을 삭제하거나 이동하는 것을 방지합니다.다만, 관련 없는 조작에 대해서는 이동할 수 있습니다. ★★★★★★★★★★★★★★★★★.__volatile__
충분하지 않습니다.
되고 있는 .「 」 「 」 「 」 「 」: "memory")
. 。"memory"
할 수 할 수 clobber GCC는 asm을 으로 메모리 내용을 .
그래서 질문하겠습니다.
- : 1에 대한 는 1 : 가이 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
__volatile__
★★★★★★★★★★★★★★★★★」"memory"
맞습니까? - 2: 두 번째 2개의 콜은 같은 기능을 합니까?
- 사용방법 3: 사용방법
"memory"
다른 시리얼화 명령을 사용하는 것보다 훨씬 간단해 보입니다.왜 두 번째 옵션보다 세 번째 옵션을 사용하는가?
코멘트에서도 언급했듯이 컴파일러 장벽과 프로세서 장벽 사이에는 차이가 있습니다. volatile
★★★★★★★★★★★★★★★★★」memory
를 변경할 수 있습니다.asm은 아직 자유입니다.
은, 가 있는 를 들면, 「프로세서 장벽」입니다.rdtscp, cpuid
의 순서 「 」 ).mfence, lfence,
등 。
「 」를 하면서, 「 」를 합니다.cpuid
의 rdtsc
수 이 이루어지기 때문입니다.cpuid
클러스터 내의 여러 머신에 공통 CPU 기능 세트를 도입하는 방법(실시간 이행이 동작하도록 하는 방법)을 설명합니다.따라서 메모리 펜스의 설명 중 하나를 사용하는 것이 좋습니다.
Linux 커널은mfence;rdtsc
AMD 플랫폼 및lfence;rdtsc
인텔(R)에 접속합니다.굳이 구별하고 싶지 않다면mfence;rdtsc
양쪽에서 모두 동작합니다.다만, 로서는 약간 느립니다.mfence
보다 강한 장벽이다lfence
.
2019-11-25 편집: Linux 커널 5.4 현재 lfence는 Intel과 AMD 모두에서 rdtsc를 직렬화하는 데 사용됩니다. "x86: X86_FEATURE_MFENCE_RDTSC 제거"를 참조하십시오. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id= be261ffce6139dad5505959dec491f37f
다음과 같이 사용할 수 있습니다.
asm volatile (
"CPUID\n\t"/*serialize*/
"RDTSC\n\t"/*read the clock*/
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t": "=r" (cycles_high), "=r"
(cycles_low):: "%rax", "%rbx", "%rcx", "%rdx");
/*
Call the function to benchmark
*/
asm volatile (
"RDTSCP\n\t"/*read the clock*/
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t"
"CPUID\n\t": "=r" (cycles_high1), "=r"
(cycles_low1):: "%rax", "%rbx", "%rcx", "%rdx");
위의 코드에서 첫 번째 CPUID 콜은 RDTSC 명령 위아래 명령의 순서가 어긋나는 실행을 피하기 위한 장벽을 구현합니다.이 방법에서는 실시간 레지스터 읽기 사이에 CPUID 명령을 호출하지 않습니다.
그 후 첫 번째 RDTSC는 타임스탬프 레지스터를 읽어내고 값은 메모리에 저장됩니다.그런 다음 측정하고자 하는 코드가 실행됩니다.RDTSCP 명령은 타임스탬프 레지스터를 두 번째로 읽고 측정하려는 모든 코드의 실행이 완료되었음을 보장합니다.뒤에 나오는 두 개의 "이동" 명령은 edx 및 eax 레지스터 값을 메모리에 저장합니다.마지막으로 CPUID 콜은 그 후에 오는 명령이 CPUID 자체보다 먼저 실행되는 것이 불가능하도록 장벽이 다시 구현됨을 보증한다.
언급URL : https://stackoverflow.com/questions/12631856/difference-between-rdtscp-rdtsc-memory-and-cpuid-rdtsc
'programing' 카테고리의 다른 글
vue js에서 소품으로 수업을 통과합니까? (0) | 2022.08.03 |
---|---|
16진수 형식의 부호 없는 긴 활자 인쇄 (0) | 2022.08.03 |
동일한 키 아래에 여러 값이 있는 HashMap (0) | 2022.08.03 |
다른 컴포넌트에서 데이터 접근 (0) | 2022.08.03 |
루트 변경 없이 Nuxt.js 미들웨어 재평가 (0) | 2022.08.03 |