用于检测 APIC id 的代码为不同的逻辑处理器返回相同的 id
我在基于 Intel Core2 的 Win2k3 机器上运行 NT 服务,我需要迭代所有逻辑 CPU(进程关联中的所有位)。为此,我调用 GetProcessAffinityMask() 来检索系统关联掩码,然后依次将进程切换到每个处理器:
DWORD systemMask;
GetProcessAffinityMask( ... &systemMask );
DWORD processorId = 1;
while( systemMask != 0 ) {
SetProcessAffinityMask(... processorId );
Sleep( 1 ); // to be sure that it shifts to that processor
systemMask >>= 1;
processorId <<= 1;
}
在每次迭代中,我调用 此处的代码 用于检索当前处理器 APIC id。问题是,对于不同的处理器,它有时会返回相同的 APIC id。根据文档,系统中的每个处理器必须具有相同的 ID。
我尝试对此进行调试 - 检查 Windows 是否确实更改了亲和性:
while( systemMask != 0 ) {
SetProcessAffinityMask(... processorId );
Sleep( 1 ); // to be sure that it shifts to that processor
DWORD tempAffinity;
GetProcessAffinityMask( ... &tempAffinity );
// run APIC id detection code here
systemMask >>= 1;
processorId <<= 1;
}
它返回的亲和性掩码完全符合我的预期,但对于不同的处理器,APIC id 仍然可以相同。
对于这种奇怪的情况有解释吗?
I run my NT service on an Intel Core2 based Win2k3 machine where I need to iterate through all logical CPUs (all bits in process affinity). To do so I call GetProcessAffinityMask() to retrieve the system affinity mask and then switch the process to each processor in turn:
DWORD systemMask;
GetProcessAffinityMask( ... &systemMask );
DWORD processorId = 1;
while( systemMask != 0 ) {
SetProcessAffinityMask(... processorId );
Sleep( 1 ); // to be sure that it shifts to that processor
systemMask >>= 1;
processorId <<= 1;
}
On each iteration I invoke code from here to retrieve the current processor APIC id. The problem is that for different processors it sometimes returns identical APIC ids. According to documentation each processor in the system must have an identical id.
I tried debugging this - checked whether Windows actually changes the affinity:
while( systemMask != 0 ) {
SetProcessAffinityMask(... processorId );
Sleep( 1 ); // to be sure that it shifts to that processor
DWORD tempAffinity;
GetProcessAffinityMask( ... &tempAffinity );
// run APIC id detection code here
systemMask >>= 1;
processorId <<= 1;
}
It returns exactly the affinity mask I expect but APIC ids can still be the same for different processors.
Is there an explanation to this weird situation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您无法使用 Windows API 调用来确定这一点。
首先,在使用 EAX = 0x1 调用 CPUID 后,Intel CPU 上的 APCID(不确定 AMD 或其他 CPU)最初被编码在 EBX 寄存器(位 24 - 31)又名 EBX[31:24] 的 8 位部分内。
考虑以下带有内联汇编的 C/C++ 代码:
GetProcessAffinityMask 只是枚举所有可用核心、CPU 内的核心以及每个 CPU 具有超线程功能的核心,并返回这些组合的总数。它没有物理 CPU 与 CPU 内的内核与支持超线程的内核的概念。至少它没有这样报道。
You can not use the Windows API call to determine this.
First, the APCID on Intel CPUs (not sure about AMD or others) is encoded initially within an 8 bit section of the EBX register (bit 24 - 31) aka EBX[31:24] after a call the CPUID with EAX = 0x1.
Consider the following C/C++ code with in-line assembly:
GetProcessAffinityMask simply enumerates all of the available cores, cores within a CPU, and hyper-thread capable cores per CPU and returns the total of these combinations. It has no concept of physical CPU vs. cores within a CPU vs. hyper thread capable cores. At least it does not report it as such.
这是因为 cpuid 不能在 MSVC++ 内联 __asm 语句中使用,因为它会破坏寄存器(即编译器在 eax 中存储了一些变量,您调用了 cpuid ,它在编译器背后更改了寄存器)。 MSVC++ 编译器没有相当于 GCC 的破坏列表,所以它不会工作。
您需要使用另一种方法来识别当前正在运行的CPU,尽管我想不出一个好的方法...
编辑:另外,您为什么关心APIC ID?如果您只想以顺序方式在 n 个处理器上执行相同的代码 n 次,难道您不能只设置亲和性、睡眠、增量亲和性、睡眠等吗?
It's because cpuid can't be used in MSVC++ inline __asm statements because it trashes the registers (i.e. the compiler stored some variable in eax, you called cpuid which changed the register behind the compiler's back). MSVC++ compiler has no equivalent to GCC's clobber list, so it won't work.
You need to use an alternate method to identify the currently running CPU, though off the top of my head, I can't think of a good one...
Edit: Also, why do you care about the APIC ID? If all you want to do is execute the same code n times on n processors in a sequential fashion, can't you just set the affinity, Sleep, increment affinity, Sleep, etc.?
您可以将DPC发布到防御CPU并在DPC产品中进行操作。
you can post DPC to deffent cpu and do operation in the DPC producre.
在循环的第一次迭代中,您似乎将亲和力掩码设置为 0。MSDN 文档没有明确指定在这种情况下的行为应该是什么,但我敢打赌它会让线程在这种情况下的任何地方运行。
In the first iteration of the loop, it appears that you set the affinity mask to 0. The MSDN docs don't clearly specify what the behavior should be in that case, but I would bet it would let the thread run anywhere in that case.