4

我在基于 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 仍然可以相同。

这种奇怪的情况有解释吗?

4

4 回答 4

2

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:

unsigned int cpu_eax;
unsigned int cpu_ebx;
unsigned int cpu_ecx;
unsigned int cpu_edx;
unsigned int apic_id;

__asm
{
  mov    eax, 0x1
  cpuid
  mov     [cpu_eax], eax
  mov     [cpu_ebx], ebx
  mov     [cpu_ecx], ecx
  mov     [cpu_edx], edx
}

apic_id = ( cpu_ebx & 0xFF000000) >> 24; 

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.

于 2011-02-04T03:01:14.350 回答
1

这是因为 cpuid 不能在 MSVC++ 内联 __asm 语句中使用,因为它会破坏寄存器(即编译器在 eax 中存储了一些变量,您调用 cpuid 更改了编译器背后的寄存器)。MSVC++ 编译器没有等效于GCC 的 clobber list,所以它不会工作。

您需要使用另一种方法来识别当前正在运行的 CPU,虽然在我的脑海中,我想不出一个好的方法......

编辑:另外,你为什么关心 APIC ID?如果您只想在 n 个处理器上以顺序方式执行相同的代码 n 次,您不能只设置关联、睡眠、递增关联、睡眠等吗?

于 2009-09-15T02:06:59.883 回答
1

您可以将 DPC 发布到不同的 cpu 并在 DPC 产品中进行操作。

于 2011-12-12T02:31:16.040 回答
0

在循环的第一次迭代中,您似乎将关联掩码设置为 0。MSDN 文档没有明确指定在这种情况下应该采取什么行为,但我敢打赌它会让线程在这种情况下在任何地方运行.

于 2009-09-18T22:37:13.433 回答