次の方法で共有


__llwpcb

更新 : 2011 年 3 月

Visual Studio 2010 SP1 が必要です。

Microsoft 固有の仕様 →

Lightweight Profiling (LWP) 命令 llwpcb を生成して、Lightweight Profiling コントロール ブロック (LWPCB) のアドレスを LWP ハードウェアに渡し、Lightweight Profiling を有効または無効にします。

void __llwpcb(
   void *pcbaddress
);

パラメーター

  • [入力] pcbaddress
    ゼロ、または LWP コントロール ブロックへのポインター。

戻り値

なし。

必要条件

組み込み

アーキテクチャ

__llwpcb

LWP

ヘッダー ファイル <intrin.h>

解説

この組み込みでは、Lightweight Profiling を有効または無効にするコードを生成します。 Lightweight Profiling では、ユーザーが選択した特定のハードウェア イベントまたはソフトウェア イベントのレコードをユーザー スペースのリング バッファーに書き込みます。 LWP コントロール ブロックでは、記録対象のイベントを選択し、リング バッファーを記述します。 イベント レコードのサンプリングと書き込みは迅速に行われ、ユーザー コードの混乱が最小限に抑えられます。 リング バッファーがほぼいっぱいになると、ハードウェアは割り込みを生成して、リング バッファー内のエントリを処理するコードをアクティブにできます。 Lightweight Profiling の詳細については、AMD の「Lightweight Profiling Specification (Lightweight Profiling の仕様)」(公開番号 43724) を参照してください。

パラメーター pcbaddress が有効な LWP コントロール ブロックを指している場合、コントロール ブロックの記述に従って Lightweight Profiling が有効になります。 pcbaddress が 0 の場合、LWP の内部バッファーが LWP リング バッファーにフラッシュされ、LWP が無効になります。

llwpcb 命令は、LWP ファミリの命令の一部です。 LWP 命令を使用するには、ハードウェア サポートとオペレーティング システム サポートの両方が必要です。 LWP に対するハードウェア サポートを確認するには、InfoType を 0x80000001 にして __cpuid 組み込みを呼び出し、CPUInfo[2] (ECX) のビット 15 をチェックします。 このビットは、ハードウェアで LWP がサポートされている場合は 1 になり、サポートされていない場合は 0 になります。 LWP がハードウェアでサポートされていることを確認したら、InfoType を 0x8000001C にして __cpuid 組み込みを呼び出し、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 がハードウェアとオペレーティング システムでサポートされています。

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 機能変更