在矩阵乘法中使用 C++2011 线程而不是 OpenMP 时出现异常加速

Posted

技术标签:

【中文标题】在矩阵乘法中使用 C++2011 线程而不是 OpenMP 时出现异常加速【英文标题】:Anomalous acceleration noted when using C++2011 threads instead of OpenMP in matrix multiplication 【发布时间】:2012-03-10 23:51:52 【问题描述】:

为我的学生编写演示代码(矩阵乘法)以表明即使使用并行代码也必须正确使用缓存,我发现使用 C++2011 线程(通过 boost::thread)优于 OpenMP(并行)线程超过 2 倍!

我能想到的唯一可能的解释是,在 C++2011 中,每个线程总是在同一个内核上运行。因此有可能将数据保存在缓存中。

这是真的吗?

演示代码很长(在正确、错误(坏缓存访问)、标量和 OpenMP 中重复相同的矩阵初始化和乘法四次),可以在以下位置找到:

http://www.giuseppelevi.com/uploads/3/2/9/8/3298932/matrix_mul_boost_thread.cpp

我使用的编译器是VS2010。 BOOST 1.45 处理器:英特尔酷睿 I5 M430。 omp_get_wtime() 用于分析它的每个部分。 为了在运行中给出一些数字,我得到了这些数字:

标量执行时间:14.42 秒

BOOST 线程:2.28

OpenMP 线程:5.10

因为只有 2 个物理内核具有超线程,所以 BOOST Thread 获得的 6.31 加速比(相对于标量)非常令人惊讶和“反常”。

【问题讨论】:

我将投反对票,因为这里没有太多相关信息。邮政编码、分析信息等。 boost::thread 版本如何运行 VS omp 版本只有 1 个线程?尝试使用各种分块将 omp 调度更改为动态/静态。 比较两个不同的实现,都使用线程,没有显示超线性加速。超线性加速意味着当我们将使用的线程/内核数量增加一倍(但程序在其他方面相同)时,我们将获得超过一倍的性能。我认为这从未见过。接近线性改进是设计师努力追求的理想。即使线程有完全独立的工作,以极低的成本集成到最终结果中,怎么可能是超线性的。 我相信每个 Windows 线程都与一个特定的核心挂钩。当核心有上下文切换时,这不会强制转储和重新加载 L3 缓存。 L3 根据需要重新加载。因此,如果一个核心在上下文中快速切换然后又返回,则 L3 缓存基本保持不变。 这里有些东西很奇怪......如果你甚至通过超线程获得 3 倍的加速,我会感到非常惊讶,但 2 核 + HT 的 6 倍是不可能的。要么你的串行版本慢得不自然,要么并行版本不能正常工作。您是否尝试在最后验证并行实现是否返回正确的结果? 【参考方案1】:

默认情况下,会使用 schedule(static,1),这通常会导致错误共享,并且有时会导致调度不理想。 改用 schedule(guided),这通常会带来更好的扩展。

【讨论】:

以上是关于在矩阵乘法中使用 C++2011 线程而不是 OpenMP 时出现异常加速的主要内容,如果未能解决你的问题,请参考以下文章

使用win32线程的矩阵乘法

Java中的多线程矩阵乘法

MPI矩阵乘法

使用某些线程进行矩阵乘法的 MPI 程序的调试断言失败

矩阵乘法中每个单元格的平均值,而不仅仅是 python 中的总和

tensorflow核心概念之op