为什么矩阵向量乘法缩放没有缩放?


15

抱歉,很长的帖子,但我想一开始就包括我认为相关的所有内容。

我想要的是

我正在实现用于稠密矩阵的Krylov子空间方法的并行版本主要是GMRES,QMR和CG。我(剖析后)意识到我的DGEMV例程是可悲的。因此,我决定通过隔离来集中精力解决这一问题。我尝试在12核计算机上运行它,但以下结果是4核Intel i3笔记本电脑的结果。趋势差异不大。

我的KMP_AFFINITY=VERBOSE输出在这里

我写了一个小代码:

size_N = 15000
A = randomly_generated_dense_matrix(size_N,size_N); %Condition Number is not bad
b = randomly_generated_dense_vector(size_N);
for it=1:n_times %n_times I kept at 50 
 x = Matrix_Vector_Multi(A,b);
end

我相信这可以模拟CG进行50次迭代的行为。

我尝试过的

翻译

我最初是用Fortran编写代码的。我将其翻译为C,MATLAB和Python(Numpy)。不用说,MATLAB和Python太可怕了。令人惊讶的是,对于上述值,C比FORTRAN好一到两秒。一致。

剖析

我分析了要运行的代码,并且运行了46.075几秒钟。这是将MKL_DYNAMIC设置为FALSE并且使用了所有内核的时候。如果我将MKL_DYNAMIC设置为true,则在任何给定时间点仅使用(大约)一半数量的内核。以下是一些详细信息:

Address Line    Assembly                CPU Time

0x5cb51c        mulpd %xmm9, %xmm14     36.591s

最耗时的过程似乎是:

Call Stack                          LAX16_N4_Loop_M16gas_1
CPU Time by Utilization             157.926s
CPU Time:Total by Utilization       94.1%
Overhead Time                       0us
Overhead Time:Total                 0.0%    
Module                              libmkl_mc3.so   

以下是几张图片:在此处输入图片说明 在此处输入图片说明

结论:

我是配置方面的真正初学者,但我意识到提高速度仍然不好。顺序(1个核心)代码在53秒内完成。那是小于1.1的速度!

真正的问题:我应该怎么做才能提高速度?

我认为可能有帮助的资料,但我不确定:

  • Pthreads实现
  • MPI(ScaLapack)实施
  • 手动调整(我不知道如何。如果您建议这样做,请推荐资源)

如果有人需要更多(特别是关于内存)的详细信息,请让我知道我应该运行什么以及如何运行。我以前从未进行过内存分析。

Answers:


20

您的矩阵大小为15,000 x 15,000,因此矩阵中有225M个元素。这大约需要2GB的内存。这远远超出了处理器的缓存大小,因此必须在每次矩阵乘法中从主内存中完全加载它,从而进行大约100GB的数据传输,以及源和目标向量的需求。

根据Intel规范,i3的最大内存带宽约为21 GB / s,但是如果您在网上浏览,您会发现实际上最多只有其中的一半可用。因此,至少,您希望基准测试能够持续10秒钟,而实际的45秒钟测量值与该标记相差不远。

同时,您还在做大约100亿个浮点乘和加。例如,考虑到该组合的10个时钟周期和3 GHz时钟速率,您将花费大约30秒。当然,如果缓存很聪明,它们可以与推测性内存负载同时运行。

总而言之,我想你离目标还差得远。您会期待什么?


有没有办法使速度至少达到2-3?
Inquest 2012年

@Nunoxic-您可能想使用SiSoftware Sandra之类的工具对系统上的内存性能进行基准测试。Wolfgangs的分析对我很重要,如果您的应用程序受内存带宽限制,那么并行化将毫无帮助。另外,请查看您可能拥有的任何省电选项,它们可能会限制内存性能。另外,请考虑用更高质量的内存替换您的内存,例如,较低的CAS延迟可能会大大缩短您的存储时间。
Mark Booth 2012年

4

您如何进行矩阵向量乘法?手工双环?或致电BLAS?如果您使用的是MKL,我强烈建议您使用线程版本的BLAS例程。

出于好奇,您可能还想编译自己的调整后版本的ATLAS,然后看看如何解决您的问题。

更新资料

经过下面评论中的讨论,事实证明您的Intel Core i3-330M仅具有两个“实际”内核。这两个缺少的核心都通过超线程进行仿真。由于在超线程内核中,内存总线和浮点单元都是共享的,因此,如果两者中的任何一个都是限制因素,您将不会获得任何加速。实际上,使用四个内核甚至可能会使速度变慢。

您在“仅”两个内核上得到什么样的结果?


我已经尝试过ATLA,GoTo和Netlib BLAS。所有的性能都比MKL弱。这是预期的还是我做错了什么?如手册中所述,我编辑了ATLAS。此外,我在这里粘贴了(精确)代码。它称为MKL的BLAS。
Inquest 2012年

好的,对于扩展,您确定在基线情况下,代码仅在单个CPU上运行吗?例如,如果您对其进行基准测试,CPU使用率直方图是否仅显示单个内核?
2012年

是。CPU直方图显示1个内核。
Inquest 2012年

再次出于好奇,您获得两个或三个核心会得到什么?您的计算机实际上是具有四个物理核心,还是只有两个具有超线程的核心?
2012年

我如何找到答案?我已经将我的KMP_AFFINITY包含在主要内容中。
Inquest 2012年

0

我的印象是,就内存访问时间,缓存行使用率和TLB未命中而言,行优先排序最适合此问题。我猜您的FORTRAN版本使用的是列主排序,这可以解释为什么它始终比C版本慢。

b

如果仅在一个循环中汇总矩阵的所有元素,而不是矩阵向量乘法,则也可以测试速度。(您可能希望将循环展开四倍,因为加法的非关联性可能会阻止编译器为您执行此优化。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.