Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
È necessario Visual Studio 2010 SP1.
Specifici di Microsoft
Genera l'istruzione della profilatura leggera (LWP) llwpcb per passare l'indirizzo di un blocco di controllo della profilatura leggera (LWPCB) all'hardware LWP e abilitare o disabilitare la profilatura leggera.
void __llwpcb(
void *pcbaddress
);
Parametri
- [in] pcbaddress
Zero o un puntatore a un blocco di controllo LWP.
Valore restituito
Nessuno.
Requisiti
Intrinseco |
Architettura |
|---|---|
__llwpcb |
LWP |
File di intestazione <intrin.h>
Note
Questo intrinseco genera il codice che abilita o disabilita la profilatura leggera. La profilatura leggera scrive i record per determinati eventi hardware o software selezionati dall'utente in un buffer circolare nello spazio dell'utente. Il blocco di controllo LWP seleziona gli eventi da registrare e descrive il buffer circolare. Il campionamento e la scrittura dei record di evento si verificano molto rapidamente, con interruzione minima del codice utente. Quando il buffer circolare diventa quasi pieno, l'hardware può generare un interrupt per attivare il codice che elabora le voci nel buffer circolare. Vedere "Lightweight Profiling Specification" di AMD (numero pubblicazione 43724) per informazioni dettagliate sulla profilatura lightweight.
Quando il parametro pcbaddress punta a un blocco di controllo LWP valido, viene abilitata la profilatura leggera come descritto dal blocco di controllo. Quando pcbaddress è 0, i buffer LWP interni vengono scaricati nel buffer circolare LWP e LWP viene disabilitato.
L'istruzione llwpcb è parte della famiglia LWP di istruzioni. Le istruzioni LWP richiedono sia un supporto hardware che del sistema operativo. Per determinare il supporto hardware per LWP, chiamare __cpuid intrinseco con InfoType = 0x80000001 e il bit di controllo 15 di CPUInfo[2] (ECX). Questo bit è 1 quando LWP è supportato dall'hardware, e 0 in caso contrario. Una volta che si sa che LWP è supportato dall'hardware, chiamare __cpuid intrinseco con InfoType = 0x8000001C e bit di controllo 0 di CPUInfo [0] (EAX). Questo bit è 1 se il sistema operativo ha reso LWP disponibile, in caso contrario è 0. Se il bit è 1, saranno presenti altre informazioni importanti disponibili in CPUInfo[], come descritto di seguito. Notare che i valori in CPUInfo [3] (EDX) rappresentano le stesse funzionalità LWP di quelli in CPUInfo [0] (EAX), ma i valori in EDX rappresentano le funzionalità LWP dell'hardware, mentre i valori in EAX rappresentano le funzionalità LWP attualmente abilitate dal sistema operativo.
CpuInfo[] |
Bit |
Nome campo |
Oggetto di descrizione |
|---|---|---|---|
0 (EAX) |
0 |
LwpAvail |
LWP è supportato da HW e sistema operativo |
1 |
LwpVAL |
Istruzione LWPVAL disponibile |
|
2 |
LwpIRE |
Evento di istruzioni ritirate disponibile |
|
3 |
LwpBRE |
Evento di creazione di un ramo ritirata disponibile |
|
4 |
LwpDME |
Evento delle richieste non soddisfatte DCache disponibile |
|
5 |
LwpCNH |
I clock della CPU non hanno arrestato l'evento disponibile |
|
6 |
LwpRNH |
I clock di riferimento della CPU non hanno arrestato l'evento disponibile |
|
30-7 |
Riservato. |
||
31 |
LwpInt |
Interruzione dell'overflow di soglia disponibile |
|
1 (EBX) |
7-0 |
LwpCbSize |
Dimensione di LWPCB in parole quadruple |
15-8 |
LwpEventSize |
Dimensione di un record di evento di buffer circolare in byte |
|
23-16 |
LwpMaxEvents |
Valore Eventid massimo supportato (escluso 255) |
|
31-24 |
LwpEventOffset |
Offset in byte del campo EventInterval1 dall'inizio di LWPCB. Sempre un multiplo di 8. |
|
2 (ECX) |
4-0 |
LwpLatencyMax |
Numero di bit nei contatori di latenza della cache |
5 |
LwpDataAddress |
1 se i record degli eventi delle richieste non soddisfatte nella cache segnalano l'indirizzo dei dati del riferimento mancante |
|
8-6 |
LwpLatencyRnd |
Bit in base ai quali viene arrotondata la latenza della cache (da 0 a 4) |
|
15-9 |
LwpVersion |
Versione dell'implementazione LWP |
|
23-16 |
LwpMinBufferSize |
Dimensione minima del buffer circolare LWP, in unità di 32*EventSize |
Esempio
#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);
}
Vedere anche
Altre risorse
Oggetti intrinseci LWP aggiunti per Visual Studio 2010 SP1
Cronologia delle modifiche
Data |
Cronologia |
Motivo |
|---|---|---|
|
Marzo 2011 |
È stato aggiunto questo contenuto. |
Modifica di funzionalità in SP1. |