我对处理器,内核,线程和并行性的理解是否正确?

时间:2016-11-12 02:40:13

标签: c# multithreading asynchronous parallel-processing task

我一直试图深入了解这些概念是如何相关的。让我举一个简单的例子,解释一下思考,以便你能够纠正它。

假设我想尝试对两个数组进行排序

int[] A = { ... }; // very large, very unsorted 
int[] B = { ... }; // very large, very unsorted 

通过对它们进行排序“与我的系统并行,我可以对它们进行排序。”我利用Parallel.ForEach做了很多东西的事实,我只是写了

var arrays = new List<int[]>(A, B);
Paralell.ForEach(arrays, (arr) => { Array.Sort(arr); });

现在让我说我在具有以下规范的机器上编译并运行它:

  1. 1个处理器,1个核心
  2. 1个处理器,多个核心
  3. 2个处理器,每个
  4. 至少有一个核心

    在案例1中,绝对不可能获得性能提升。它对A进行排序,然后对B进行排序,就像在常规foreach循环中一样。

    在第2种情况下,也没有性能提升,因为除非你有多个处理器,否则你的机器不能“一次做多于一件事。”即使它最终将它们排序不同的线程,控制线程的CPU做了一点A的排序,B的一点点排序,A的一点点等等,这不仅仅比排序所有A然后全部B更有效。

    由于前一种情况中提到的原因,案例3是唯一可能获得性能提升的案例。

    有人会批评我的理解吗?这是对还是错? (我没有计算机科学专业。所以请在曲线上给我评分。)

1 个答案:

答案 0 :(得分:5)

  

在案例1中......它对A进行排序,然后对B进行排序

这不是线程的工作原理。操作系统快速上下文切换两个线程。在Windows上,默认情况下每秒发生64/3次。交错使得它看起来像A和B同时被排序。不容易观察到,调试器必须让你看看Array.Sort(),它不会。当然,速度不是很快,但放缓速度相当小。它是廉价的上下文切换,不需要重新加载页面映射表,因为线程属于同一个进程。您只需支付可能已删除的缓存,每3/64秒增加约5微秒(慢0.1%)很难准确测量。

  

在案例2中,......然后你的机器不能“一次做多于一件事”

可以,每个核心可以同时执行Sort()。主要是多核处​​理器。然而,它们必须共享单个资源,即内存总线。重要的是阵列的大小和RAM芯片的速度。大型阵列不适合处理器高速缓存,从技术上讲,存储器总线可能会被来自处理器内核的请求所饱和。在这种情况下没有帮助的是元素类型,比较两个int非常快,因为它只需要一条CPU指令。期望是x2加速,但如果你观察它需要更长时间,那么你就知道RAM是瓶颈。

  

案例3是唯一可能获得绩效增长的案例

不太可能。多处理器机器通常具有NUMA架构,为每个处理器提供自己的内存总线。它们之间的互连可用于将数据从一个总线转移到另一个总线。但是这样的处理器具有多个核心。操作系统的工作就是弄清楚如何有效地使用它们。由于线程属于同一个进程,因此共享数据,它将强烈支持在同一处理器的内核上调度线程,并避免在互连上施加负载。所以期望它的表现与案例2相同。

这些是粗略的指导方针,您实际测量的现代机器设计要求。