当前位置:  开发笔记 > 编程语言 > 正文

多核+超线程 - 线程是如何分布的?

如何解决《多核+超线程-线程是如何分布的?》经验,为你挑选了3个好方法。

我正在阅读新的英特尔凌动330的评论,他们注意到任务管理器显示4个核心 - 两个物理核心,另外两个由超线程模拟.

假设你有一个包含两个线程的程序.假设这些是在PC上进行任何工作的唯一线程,其他一切都是空闲的.操作系统将两个线程放在同一个核心上的概率是多少?这对程序吞吐量有很大影响.

如果答案不是0%,那么除了创建更多线程之外,是否还有其他缓解策略?

我希望Windows,Linux和Mac OS X会有不同的答案.


使用sk的答案作为Google饲料,然后按照链接,我在Windows中找到了GetLogicalProcessorInformation函数.它说的是"共享资源的逻辑处理器.这种资源共享的一个例子就是超线程场景." 这意味着jalf是正确的,但它不是一个明确的答案.



1> joshperry..:

Linux具有非常复杂的线程调度程序,可以识别HT.其中一些策略包括:

被动负载平衡:如果物理CPU运行多个任务,则调度程序将尝试在第二个物理处理器上运行任何新任务.

主动负载均衡:如果有3个任务,当第二个物理处理器空闲时,一个物理cpu上有2个,另一个上有1个,调度程序将尝试将其中一个任务迁移到它.

它在尝试保持线程亲和性时执行此操作,因为当线程迁移到另一个物理处理器时,它将不得不从主内存重新填充所有级别的缓存,从而导致任务停顿.

所以回答你的问题(至少在Linux上); 在双核超线程机器上给出2个线程,每个线程将在其自己的物理核心上运行.



2> Todd Gamblin..:

一个理智的操作系统会尝试在自己的内核上安排计算密集型任务,但是当您启动上下文切换时会出现问题.现代操作系统仍然倾向于在核心上安排工作,而这些核心在调度时没有工作,但这可能导致并行应用程序中的进程相当自由地从核心交换到核心.对于并行应用程序,您不希望这样,因为您丢失了该进程可能在其核心的高速缓存中使用的数据.人们使用处理器亲和力来控制它,但在Linux上,sched_affinity()的语义在发行版/内核/供应商等之间可能会有很大差异.

如果您使用的是Linux,则可以通过Portable Linux Processor Affinity Library(PLPA)轻松控制处理器关联.这就是OpenMPI内部使用的内容,以确保流程在多核和多串口系统中安排到自己的内核; 他们只是将模块拆分为独立项目.OpenMPI在洛斯阿拉莫斯的许多其他地方使用,所以这是经过良好测试的代码.我不确定Windows下的等价物是什么.



3> bart..:

我一直在寻找关于Windows上的线程调度的一些答案,并且有一些经验信息,我将在这里发布给将来可能偶然发现这篇文章的任何人.

我写了一个简单的C#程序,它启动了两个线程.在我的四核Windows 7机箱上,我看到了一些令人惊讶的结果.

当我没有强制亲和力时,Windows会将两个线程的工作负载分散到所有四个核心.注释掉了两行代码 - 一行将线程绑定到CPU,另一行建议理想的CPU.该建议似乎没有任何效果,但设置线程关联确实导致Windows在自己的核心上运行每个线程.

要最好地查看结果,请使用.NET Framework 4.0客户端附带的免费编译器csc.exe编译此代码,并在具有多个内核的计算机上运行它.在处理器关联线注释掉之后,任务管理器显示线程分布在所有四个核心上,每个核心运行大约50%.通过设置亲和性,两个线程以100%最大化两个核心,其他两个核心空闲(这是我在运行此测试之前预期会看到的).

编辑:我最初发现这两种配置在性能上存在一些差异.但是,我无法复制它们,所以我编辑了这篇文章来反映这一点.我仍然发现线程亲和力很有趣,因为它不是我所期望的.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

class Program
{
    [DllImport("kernel32")]
    static extern int GetCurrentThreadId();

    static void Main(string[] args)
    {
        Task task1 = Task.Factory.StartNew(() => ThreadFunc(1));
        Task task2 = Task.Factory.StartNew(() => ThreadFunc(2));
        Stopwatch time = Stopwatch.StartNew();
        Task.WaitAll(task1, task2);
        Console.WriteLine(time.Elapsed);
    }

    static void ThreadFunc(int cpu)
    {
        int cur = GetCurrentThreadId();
        var me = Process.GetCurrentProcess().Threads.Cast().Where(t => t.Id == cur).Single();
        //me.ProcessorAffinity = (IntPtr)cpu;     //using this line of code binds a thread to each core
        //me.IdealProcessor = cpu;                //seems to have no effect

        //do some CPU / memory bound work
        List ls = new List();
        ls.Add(10);
        for (int j = 1; j != 30000; ++j)
        {
            ls.Add((int)ls.Average());
        }
    }
}

推荐阅读
雨天是最美
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有