programing

rdtscp, rdtsc: 메모리와 cpuid/rdtsc의 차이점

copyandpastes 2022. 8. 3. 23:46
반응형

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

★★★★★★★★★★★★★★.rdtscpCPU를 사용합니다. 이 에는 ''를 사용해야 .rdtscrdtsc는 비시리얼라이즈이기 때문에 그것만 사용해도 CPU의 순서를 변경할 수 있습니다.

따라서 다음 두 가지 옵션 중 하나를 사용하여 순서 변경을 방지할 수 있습니다.

2: 이 전화는cpuid 다음에 또 한 번.rdtsccpuid을 사용하다

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: 이 전화는rdtscmemory재주문 되어 있습니다.

__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,등 。

「 」를 하면서, 「 」를 합니다.cpuidrdtsc 수 이 이루어지기 때문입니다.cpuid클러스터 내의 여러 머신에 공통 CPU 기능 세트를 도입하는 방법(실시간 이행이 동작하도록 하는 방법)을 설명합니다.따라서 메모리 펜스의 설명 중 하나를 사용하는 것이 좋습니다.

Linux 커널은mfence;rdtscAMD 플랫폼 및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

반응형