Assembly x2APIC中的MSR性能
正如我们所知,在x2APIC中,我们使用MSR而不是xAPIC使用的MMIO。 但是根据我的测试,我发现MSR的访问速度比MMIO慢得多 例如,在我的环境中,我编写了一个简单的测试用例,如下所示:Assembly x2APIC中的MSR性能,assembly,x86,intel,interrupt-handling,Assembly,X86,Intel,Interrupt Handling,正如我们所知,在x2APIC中,我们使用MSR而不是xAPIC使用的MMIO。 但是根据我的测试,我发现MSR的访问速度比MMIO慢得多 例如,在我的环境中,我编写了一个简单的测试用例,如下所示: static __inline__ void __loApicWrite ( UINT32 * addr, UINT32 value ) { __asm__ volatile ( "movl %1, %0" : "=m" (*(addr)) : "
static __inline__ void __loApicWrite
(
UINT32 * addr,
UINT32 value
)
{
__asm__ volatile
(
"movl %1, %0"
: "=m" (*(addr))
: "ir" (value)
);
}
void MSR_vs_MMIO(int way)
{
unsigned long a;
unsigned long b;
int i = 0;
msrReg = MSR_BASE_ADDRESS + (LOAPIC_ESR >> 4);
if (way == 0) /*MSR*/
{
for (i = 0; i < 1000; i++)
{
a = pentiumTscGet();
__asm__ volatile
(
"wrmsr\n"
: : "c" (msrReg), "a"(0), "d" (0)
);
b = pentiumTscGet();
if ( b > a )
benchmark_record[i] = b - a ;
}
}
else /*MMIO*/
{
for (i = 0; i < 1000; i++)
{
a = pentiumTscGet();
__loApicWrite((UINT32 *)((0x82244000) + LOAPIC_ESR), 0);
b = pentiumTscGet();
if ( b > a )
benchmark_record[i] = b - a ;
}
}
return;
static\uuuuu inline\uuuuu void\uuuu loApicWrite
(
UINT32*地址:,
UINT32值
)
{
__反复无常
(
移动%1,%0
:“=m”(*(地址))
:“ir”(值)
);
}
无效MSR_vs_MMIO(内部方式)
{
无符号长a;
无符号长b;
int i=0;
msrReg=MSR\U基地址+(LOAPIC\U ESR>>4);
如果(方式==0)/*MSR*/
{
对于(i=0;i<1000;i++)
{
a=奔腾TSGET();
__反复无常
(
“wrmsr\n”
:“c”(msrReg)、“a”(0)、“d”(0)
);
b=奔腾TSGET();
如果(b>a)
基准记录[i]=b-a;
}
}
else/*MMIO*/
{
对于(i=0;i<1000;i++)
{
a=奔腾TSGET();
__loApicWrite((UINT32*)((0x82244000)+loapicu ESR),0;
b=奔腾TSGET();
如果(b>a)
基准记录[i]=b-a;
}
}
返回;
}
如果我运行“MSR_vs_MMIO 0”,我得到的数字大约是310。
如果我运行“MSR_vs_MMIO 1”,我得到的数字大约是40
我在启用和禁用x2APIC的情况下在系统上进行测试。当我在启用x2APIC的情况下启动系统时,我运行测试“MSR\u vs_MMIO 0”,当我在禁用x2APIC的情况下启动系统时,我运行测试“MSR\u vs_MMIO 1”。然后我收集了数据,发现性能有很大的不同
因此,MMIO似乎比MSR访问快8倍左右
这个结果是否如预期的那样?《英特尔手册》(我搜索过但没有得到答案)中是否有任何文档描述x2APIC中的MSR和xAPIC中的MMIO之间的性能差异
谢谢。假设您的系统以x2apic模式启动,APIC的MMIO接口将被禁用,因此您的MMIO代码实际上不会访问APIC。请参阅“英特尔SDM”第10.12.2节。如果系统以x2apic模式启动,则APIC的MMIO接口将被禁用,因此MMIO代码实际上不会访问APIC。请参阅“英特尔SDM”第10.12.2节。这可能与计时无关,但您的内联asm已损坏;)与此相关的是“WRMSR指令是一条串行化指令”(引用自指令集参考手册:))谢谢Jester,你能告诉我损坏的内联asm吗?你正在调零
eax
和edx
,但没有告诉编译器,你需要对它们进行重击,或者更好,将输入作为“a”(0)、“d”(0)
传递,并删除movl
s。谢谢Jester,我将更新我的内联asm。顺便说一句,我检查了x2APIC规范,发现了一个声明:“为了在x2APIC模式下有效地访问APIC寄存器,在写入APIC寄存器时,WRMSR的序列化语义是宽松的。”。所以问题似乎不是由“序列化”引起的。你也可以考虑对各种不同的APIC寄存器的访问。它们可能不完全相同,制造商可能更可能提高正常操作中访问的寄存器的性能,而不是设置/初始化代码或错误情况。这可能与计时无关,但您的内联asm已损坏;)与此相关的是“WRMSR指令是一条串行化指令”(引用自指令集参考手册:))谢谢Jester,你能告诉我损坏的内联asm吗?你正在调零eax
和edx
,但没有告诉编译器,你需要对它们进行重击,或者更好,将输入作为“a”(0)、“d”(0)
传递,并删除movl
s。谢谢Jester,我将更新我的内联asm。顺便说一句,我检查了x2APIC规范,发现了一个声明:“为了在x2APIC模式下有效地访问APIC寄存器,在写入APIC寄存器时,WRMSR的序列化语义是宽松的。”。所以问题似乎不是由“序列化”引起的。你也可以考虑对各种不同的APIC寄存器的访问。它们可能不完全相同,制造商可能更可能改进正常操作中访问的寄存器的性能,而不是设置/初始化代码或错误情况。感谢prl的评论。实际上,我在启用和禁用x2APIC的情况下在系统上进行测试。当我在启用x2APIC的情况下启动系统时,我运行测试“MSR\u vs_MMIO 0”,当我在禁用x2APIC的情况下启动系统时,我运行测试“MSR\u vs_MMIO 1”。然后我收集数据,发现性能有很大的不同。您应该在问题中说您在两个测试之间重新启动。@prl这也是我在设备管理器或上看不到APIC的原因!我的卡比湖系统上的pcitree(因为它使用x2APIC)感谢prl的评论。实际上,我在启用和禁用x2APIC的情况下在系统上进行测试。当我在启用x2APIC的情况下启动系统时,我运行测试“MSR\u vs_MMIO 0”,当我在禁用x2APIC的情况下启动系统时,我运行测试“MSR\u vs_MMIO 1”。然后我收集数据,发现性能有很大的不同。您应该在问题中说您在两个测试之间重新启动。@prl这也是我在设备管理器或上看不到APIC的原因!我的kaby lake系统上的pcitree(因为它使用x2APIC)