Share via


__llwpcb

업데이트: 2011년 3월

Visual Studio 2010 SP1이 필요합니다.

Microsoft 전용

LWP(lightweight profiling) 명령 llwpcb를 생성하여 LWPCB(lightweight profiling control block)의 주소를 LWP 하드웨어로 전달하고 간단한 프로파일링을 활성화하거나 비활성화합니다.

void __llwpcb(
   void *pcbaddress
);

매개 변수

  • [in] pcbaddress
    0 또는 LWP 제어 블록에 대한 포인터입니다.

반환 값

없음

요구 사항

내장

아키텍처

__llwpcb

LWP

헤더 파일 <intrin.h>

설명

이 intrinsic은 간단한 프로파일링을 활성화하거나 비활성화하는 코드를 생성합니다. 간단한 프로파일링은 특정 사용자 선택 하드웨어 또는 소프트웨어 이벤트에 대한 레코드를 사용자 공간의 링 버퍼에 기록합니다. LWP 제어 블록은 기록할 이벤트를 선택하고 링 버퍼를 설명합니다. 이벤트 레코드를 샘플링하고 쓰는 것은 사용자 코드 중단을 최소화하면서 매우 빠르게 수행됩니다. 링 버퍼가 거의 가득 차면 하드웨어는 인터럽트를 생성하여 링 버퍼의 항목을 처리하는 코드를 활성화할 수 있습니다. 간단한 프로파일링에 대한 자세한 내용은 AMD의 "Lightweight Profiling Specification"(발행 번호 43724)을 참조하십시오.

매개 변수 pcbaddress가 유효한 LWP 제어 블록을 가리키면 간단한 프로파일링이 제어 블록에 설명된 대로 활성화됩니다. pcbaddress가 0이면 LWP 내부 버퍼는 LWP 링 버퍼로 플러시되고 LWP가 비활성화됩니다.

llwpcb 명령은 LWP 명령군의 일부입니다. LWP 명령을 사용하려면 하드웨어 및 운영 체제 지원이 필요합니다. LWP에 대한 하드웨어 지원을 확인하려면 InfoType = 0x80000001을 사용하여 __cpuid intrinsic을 호출하고 CPUInfo[2] (ECX)의 비트 15를 확인합니다. 하드웨어에서 LWP를 지원하는 경우 이 비트는 1이고, 그렇지 않으면 0입니다. LWP가 하드웨어에 의해 지원된다는 것을 알게 되면 __cpuid intrinsic을 InfoType = 0x8000001C를 사용하여 호출하고 CPUInfo[0] (EAX)의 비트 0을 확인합니다. 운영 체제에서 LWP를 사용할 수 있는 경우 이 비트는 1이고, 그렇지 않으면 0입니다. 비트가 1인 경우 아래 설명한 대로 CPUInfo[]에서 다른 중요한 정보를 사용할 수 있습니다. CPUInfo[3] (EDX)의 값은 CPUInfo[0] (EAX)의 기능과 같은 LWP 기능을 나타내지만 EDX의 값은 하드웨어의 LWP 기능을 나타내는 반면 EAX의 값은 현재 운영 체제에 의해 활성화된 LWP 기능을 나타냅니다.

CpuInfo[]

비트

필드 이름

설명

0 (EAX)

0

LwpAvail

LWP는 HW 및 OS에서 지원합니다

1

LwpVAL

LWPVAL 명령 사용 가능

2

LwpIRE

사용 가능한 명령 만료된 이벤트

3

LwpBRE

사용 가능한 분기 만료된 이벤트

4

LwpDME

DCache 누락 이벤트 사용 가능

5

LwpCNH

CPU 시계가 사용 가능한 이벤트를 중지시키지 않았음

6

LwpRNH

CPU 참조 시계가 사용 가능한 이벤트를 중지시키지 않았음

30-7

예약되었습니다.

31

LwpInt

임계값 오버플로 인터럽트 사용 가능

1 (EBX)

7-0

LwpCbSize

LWPCB의 쿼드워드 단위 크기

15-8

LwpEventSize

링 버퍼 이벤트 레코드의 바이트 단위 크기

23-16

LwpMaxEvents

최대 Eventid 값이 지원됨(255는 포함하지 않음)

31-24

LwpEventOffset

LWPCB의 시작부터 EventInterval1 필드의 바이트의 오프셋입니다. 항상 8의 배수입니다.

2 (ECX)

4-0

LwpLatencyMax

캐시 대기 시간 카운터의 비트 수

5

LwpDataAddress

캐시에 누락된 참조의 이벤트 레코드 보고서 데이터 주소가 누락된 경우 1

8-6

LwpLatencyRnd

캐시 대기 시간이 반올림(0-4)되는 비트입니다.

15-9

LwpVersion

LWP 구현의 버전

23-16

LwpMinBufferSize

LWP 링 버퍼의 최소 크기, 32*EventSize 단위

예제

#include <intrin.h>
#include <stdio.h>

#define MAX_EVENTS 6
#define LWPEVENTSIZE 32
#define BUFFERSIZE 4096

struct lwpEventRecord {
    unsigned __int64 EventId : 8;
    unsigned __int64 CoreId : 8;
    unsigned __int64 Flags : 16;
    unsigned __int64 Data1 : 32;
    unsigned __int64 InstructionAddress;
    unsigned __int64 Data2;
    unsigned __int64 Reserved;
};

struct lwpEventRecord ringBuffer[BUFFERSIZE];

struct lwpcb0 {
    unsigned __int64 Flags : 32;
    unsigned __int64 BufferSize : 28;
    unsigned __int64 Random : 4;
};

struct lwpcbEvent {
    unsigned __int64 EventInterval : 26;
    unsigned __int64 EIReserved1 : 6;
    unsigned __int64 EventCounter : 26;
    unsigned __int64 EIReserved2 : 6;

};

struct lwpcbStruct {
    unsigned __int64 Flags : 32;
    unsigned __int64 BufferSize : 28;
    unsigned __int64 Random : 4;

    unsigned __int64 BufferBase;

    unsigned __int64 BufferHeadOffset : 32;
    unsigned __int64 Reserved1 : 32;

    unsigned __int64 MissedEvents;

    unsigned __int64 Threshold : 32;
    unsigned __int64 Filters : 32;

    unsigned __int64 BaseIP;

    unsigned __int64 LimitIP;

    unsigned __int64 Reserved2;

    unsigned __int64 BufferTailOffset : 32;
    unsigned __int64 Reserved3 : 32;

    unsigned __int64 Reserved4[7];

    struct lwpcbEvent Events[MAX_EVENTS]; // event 1 == index 0
} myLWPCBStruct;

__m128d data[100];

extern void __cpuid(int *CPUInfo, int InfoType);
// Return 1 if LWP is supported by the hardware
int LwpSupported()
{
    int cpuInfo[4] = {0};
    __cpuid(cpuInfo, 0x80000001);
    if (cpuInfo[2] & (1 << 15)) return 1;
    else return 0;
}

// Return 1 if LWP is enabled by the OS
// Assumes LWP is supported by the hardware
int LwpAvailable()
{
    int cpuInfo[4] = {0};
    __cpuid(cpuInfo, 0x8000001C);
    if (cpuInfo[0] & 1) return 1;
    else return 0;
}

// Return 1 if LWPVAL instruction is supported by this hardware
// Assumes LWP is supported by the hardware
int LwpvalSupported()
{
    int cpuInfo[4] = {0};
    __cpuid(cpuInfo, 0x8000001C);
    if (cpuInfo[3] & (1 << 1)) return 1;
    else return 0;
}

// Return 1 if LWPVAL instruction is enabled by the OS
// Assumes LWPVAL is supported by the hardware
int LwpvalAvailable()
{
    int cpuInfo[4] = {0};
    __cpuid(cpuInfo, 0x8000001C);
    if (cpuInfo[3] & (1 << 1)) return 1;
    else return 0;
}

void
initializeLWPCB(struct lwpcbStruct *p)
{
    int i, lwpvalok;
    unsigned __int64 *dummy;
    p->Flags =  0; // disable HW counters & threshold interrupts
    p->BufferSize = sizeof(ringBuffer)/sizeof(struct lwpEventRecord);
    p->BufferSize *= sizeof(struct lwpEventRecord);
    p->Random = 0; // No randomness in counters
    p->BufferBase = (unsigned __int64)&ringBuffer[0];
    /// Value of BufferHeadOffset here is arbitrary
    p->BufferHeadOffset = p->BufferSize -
                          3*sizeof(struct lwpEventRecord);
    p->MissedEvents = 0;
    p->Threshold = 2*p->BufferSize; // don't want threshold interrupts
    p->Filters = 0; // shouldn't matter for this test
    p->BaseIP = 0; // shouldn't matter for this test
    p->LimitIP = 0; // shouldn't matter for this test
    p->BufferTailOffset = p->BufferHeadOffset; // ring buffer empty
    p->Reserved1 = p->Reserved2 = p->Reserved3 = 0;
    for (i = 0; i < 7; i++) p->Reserved4[i] = 0;
    for (i = 0; i < MAX_EVENTS; i++) {
        p->Events[i-1].EventInterval = 0;
        p->Events[i-1].EIReserved1 = 0;
        p->Events[i-1].EventCounter = 0;
        p->Events[i-1].EIReserved2 = 0;
    }
    if (LwpvalSupported() && LwpvalAvailable()) {
        p->Flags |= 2; // Count LWPVAL events
        p->Events[0].EventInterval = 9; // count every 10th LWPVAL
    }
}
#define LOOPSIZE 31
main()
{
    int i;
    __m128d temp;
    double sum = 0;
    struct lwpcbstruct *plwpcb;
    unsigned int tailOffset, headOffset, bufferSize, bufferCapacity;
    unsigned int headRecord, tailRecord;
    int headMinusTail;
    unsigned int recordSize = sizeof(struct lwpEventRecord);
    unsigned int numEntries;
    unsigned int lwpvalCount, lwpinsCount;

    if (!LwpSupported()) {
        printf("LWP is not supported by this hardware\n");
        exit(1);
    }
    if (!LwpAvailable()) {
        printf("OS has not made LWP available\n");
        exit(1);
    }
#if defined(_M_X64)
    printf("64-bit compiler\n");
#else
    printf("32-bit compiler\n");
#endif
    initializeLWPCB(&myLWPCBStruct);
    __llwpcb(&myLWPCBStruct);
    plwpcb = __slwpcb();
    if ((unsigned __int64)plwpcb != (unsigned __int64)&myLWPCBStruct) {
        printf("Test failed: bad return from __slwpcb()\n");
        exit(1);
    }

    if (LwpvalSupported() && LwpvalAvailable()) {
        for (i = 0; i < LOOPSIZE; i ++) {
            if (i % 7 == 0) __lwpins32(0xdeadbeef, i, 0x01234567); 
            __lwpval32(0x0badf00d, i, 0xcad00cad);
        }
#if defined(_M_X64)
        for (i = 0; i < LOOPSIZE; i ++) {
            if (i % 7 == 0) __lwpins64(0xdeadbeefdeadbeefll, i, 0x01234567); 
            __lwpval64(0x0badf00d0badf00dll, i, 0xcad00cad);
        }
#endif
    } else {
        if (!LwpvalSupported()) {
            printf("LWPVAL instruction not supported by the hardware\n");
        } else if (!LwpvalAvailable()) {
            printf("LWPVAL instruction not enabled\n");
        }
        for (i = 0; i < LOOPSIZE; i ++) {
            if (i % 7 == 0) __lwpins32(0xdeadbeef, i, 0x01234567); 
        }
#if defined(_M_X64)
        for (i = 0; i < LOOPSIZE; i ++) {
            if (i % 7 == 0) __lwpins64(0xdeadbeefdeadbeefll, i, 0x01234567); 
        }
#endif
    }

    plwpcb = __slwpcb();

    tailOffset = myLWPCBStruct.BufferTailOffset;
    headOffset = myLWPCBStruct.BufferHeadOffset;
    bufferSize = myLWPCBStruct.BufferSize;
    bufferCapacity = bufferSize / recordSize;

    headMinusTail = headOffset;
    headMinusTail -= tailOffset;
    if (tailOffset <= headOffset) numEntries = headMinusTail;
    else numEntries = headMinusTail + bufferSize;
    numEntries /= recordSize;

    tailRecord = tailOffset / recordSize;
    headRecord = headOffset / recordSize;
    printf("%d entries in ring buffer\n", numEntries);

    lwpvalCount = lwpinsCount = 0;
    for (i = tailRecord; i != headRecord; i = (i + 1)%bufferCapacity) {
        switch(ringBuffer[i].EventId) {
            case 1:
                lwpvalCount += 1;
                break;
            case 255:
                lwpinsCount += 1;
                break;
            default:
                printf("WARNING: bad EventId %d in ring buffer\n", 
                        ringBuffer[i].EventId);
                break;
        }
    }
    printf("%d LWPVAL instructions, %d LWPINS instructions\n",
            lwpvalCount, lwpinsCount);
}
      

참고 항목

기타 리소스

__lwpval32, __lwpval64

__lwpins32, __lwpins64

__slwpcb

Visual Studio 2010 SP1용으로 추가된 LWP 내장 함수

변경 기록

날짜

변경 내용

이유

2011년 3월

이 내용이 추가되었습니다.

SP1 기능 변경