微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么我的电脑更喜欢偶数核?

如何解决为什么我的电脑更喜欢偶数核?

我的电脑配备了第 10 代 Core i7 vPRO,并启用了虚拟化。 8 个内核 + 8 个虚拟内核。 (i7-10875H,彗星湖)

每个物理核心被分成对,所以核心 1 承载虚拟核心 0 和 1,核心 2 承载虚拟核心 2 和 3。我注意到在任务管理器中,每个核心对的第一项似乎是首选核心,从更高的使用率来看。我确实为某些繁重的程序手动设置了一些关联,但我总是将这些设置为 4 组,从 0-3、4-7、8-11、12-15 开始,并且从不与不同的逻辑处理器不匹配。

我想知道为什么会发生这种行为 - 偶数内核是否等同于物理内核,后者可能会稍微快一些?如果是这样,如果我运行的程序没有高线程数,我会在没有虚拟化的情况下获得稍微更好的时钟速度吗?

enter image description here

enter image description here

解决方法

总的来说(对于“调度器理论”):

  • 如果您关心性能,请尽可能将任务分散到物理内核上。这可以防止出现“两个任务运行速度变慢,因为它们共享一个物理内核,而整个物理内核处于空闲状态”的情况。

  • 如果您关心功耗而不是性能,请尽可能让任务使用同一物理内核中的逻辑处理器。这可能允许您将整个内核置于非常节能的“什么都不做”状态。

  • 如果您关心安全性(而不是性能或功耗),则根本不要让不相关的任务使用同一物理内核中的逻辑处理器(因为信息,例如当前正在使用的指令类型,可以从一个逻辑处理器“泄漏”到同一物理内核中的另一个逻辑进程)。请注意,相关任务最好在同一物理核心中使用逻辑进程(例如,属于同一进程的 2 个线程彼此信任,但不属于彼此不信任的不同进程的线程) .

当然,一个好的操作系统会知道每个任务的偏好(如果每个任务都关心性能、功耗或安全性),并且会做出明智的决定来处理具有不同偏好的混合任务。遗憾的是,没有好的操作系统——大多数操作系统和 API 都是在 1990 年代或更早的时候设计的(那时 SMP 才刚刚开始,而且所有的 CPU 都是相同的)并且缺乏做出明智决策所需的任务信息;因此,他们认为性能是所有任务唯一重要的因素,从而导致您所看到的“尽可能将任务分散在物理核心上,即使它并不理想”行为。

,

我的猜测是由于超线程。

超线程不会使 CPU 容量翻倍(根据英特尔的说法,它平均增加了约 30%),因此首先在物理内核之间分配工作是有意义的,并在整体 CPU 需求开始时使用超线程作为最后的手段超过 50%。

有趣的事实:据报道,超线程系统上 50% 的总体 CPU 负载实际上是约 70% 的负载,而剩余的 50% 相当于剩余的约 30%。

如果我们查询操作系统以查看逻辑处理器如何分配给内核1,我们将看到这样的情况:

Core 0: mask 0x3
Core 1: mask 0xc
Core 2: mask 0x30
Core 3: mask 0xc0
. . .

这意味着逻辑处理器 0 和 1 位于核心 0、2 和 3 上,以此类推。

您可以在 BIOS 中禁用超线程。但是因为它增加了性能,所以有这个功能是件好事。只需要注意不要固定工作,使其竞争同一个内核。


1 为了检查核心分配,我使用下面的一个小 C 程序。这些信息也可以通过 WMIC 获得。

#include <stdio.h>
#include <stdlib.h>
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x601
#include <Windows.h>

int main() {
    DWORD len = 65536;
    char *buf = (char*)malloc(len);
    if (!GetLogicalProcessorInformationEx(RelationProcessorCore,(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)buf,&len)) {
        return GetLastError();
    }
    union {
        PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX info;
        PBYTE infob;
    };
    info = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)buf;
    for (size_t i = 0,n = 0; n < len; i++,n += info->Size,infob += info->Size) {
        switch (info->Relationship) {
        case RelationProcessorCore:
            printf("Core %zd:",i);
            for (int j = 0; j < info->Processor.GroupCount; j++)
                printf(" mask 0x%llx",info->Processor.GroupMask[j].Mask);
            printf("\n");
            break;
        }
    }
    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。