我一直在尝试深入了解这些概念之间的关系。让我举一个简单的例子,并解释一下什么想法,以便您可以纠正它。
假设我想尝试对两个数组进行排序
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中,绝对不可能获得性能提升。就像在常规
foreach
循环中一样,它对A进行排序,然后对B进行排序。在情况2中,也不会获得性能提升,因为除非您拥有多个处理器,否则您的计算机实际上无法“一次完成一件以上的事情”。即使最终将它们排序在不同的线程中,控制线程的CPU也会对A进行一些排序,对B进行一些排序,对A进行更多的排序,等等,这比仅对所有线程进行排序效率更高A,然后是B的全部。
由于前面的案例中提到的原因,案例3是唯一有可能获得性能提升的案例。
有人可以批评我的理解吗?这是对还是错? (我没有主修计算机科学。因此,请给我评分。)
最佳答案
那不是线程工作的方式。操作系统在两个线程之间快速进行上下文切换。在Windows上,默认情况下每秒发生64/3次。交织使它看起来像A和B在同一时间被排序。不容易观察到,调试器将不得不在Array.Sort()内部进行查看,而事实并非如此。当然,没有其他方面更快,但是,速度下降的幅度很小。这是一种廉价的上下文切换,无需重新加载页面映射表,因为线程属于同一进程。您只需为可能已浪费的缓存付费,每3/64秒增加〜5微秒(慢0.1%)很难准确测量。
每个内核都可以并发执行Sort()。多点处理器在很大程度上。但是,它们确实必须共享一个资源,即内存总线。重要的是阵列的大小和RAM芯片的速度。大型阵列不适合处理器缓存,从技术上讲,内存总线可能会由于来自处理器内核的请求而变得饱和。在这种情况下没有帮助的是元素类型,因为只需要一条CPU指令,所以比较两个int
值非常快。期望实现x2加速,但是如果您观察到它花费了更长的时间,那么您就会知道RAM是瓶颈。
不见得。多处理器计算机通常具有NUMA架构,从而为每个处理器提供自己的内存总线。它们之间的互连可用于将数据从一条总线传送到另一条总线。但是这样的处理器也有多个核心。操作系统的工作是弄清楚如何有效地使用它们。并且由于线程属于同一进程,因此共享数据,因此强烈建议在同一处理器的内核上调度线程,并避免对互连造成负担。因此,期望它的性能与情况2相同。
这些是粗略的指导原则,您需要实际测量现代机械设计的需求。
关于c# - 我对处理器,内核,线程和并行性的理解正确吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40559038/