当dgemm执行时,sgemm没有多线程 - 英特尔MKL

时间:2014-08-24 18:55:54

标签: c++ c multithreading blas intel-mkl

我使用英特尔MKL的?GEMM功能来增加矩阵。考虑以下两个矩阵乘法:

            cblas_?gemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m,n,k,
                            1.0,
                            Matrix1,k,
                            Matrix2,n,
                            0.0,
                            A,n);

其中m = 1E5,并且n = 1E4,k = 5。当我使用pca_dgemm和pca_sgemm时,它会使用所有12个内核,并且执行得非常好。

但是,当我执行以下矩阵乘法时:

    cblas_?gemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m,l,n,
                    1.0,
                    A,n,
                    Ran,l,
                    0.0,
                    Q,l);

其中m = 1E5,n = 1E5,并且l = 7(注意,传递的参数的顺序是不同的。这是(m,n)*(n,l))。 pca_dgemm使用所有12个核心并且执行得非常好。

然而,pca_sgemm没有。它只使用1个核心,当然需要更长的时间。当然,对于sgemm我使用浮点数组,而对于dgemm我使用的是双精度数组。

为什么会这样?他们都给出了准确的结果,但sgemm只有多线程的前者,而dgemm多线程和两者!如何简单地改变数据类型会产生这种差异?

请注意,所有数组都是使用mkl_malloc使用64的对齐分配的。

编辑2:请注意,当l = 12时,换句话说,使用更大的矩阵,它会在sgemm中进行穿线。换句话说,显然sgemm版本需要更大的矩阵来并行化,但是dgemm没有这个要求。这是为什么?

1 个答案:

答案 0 :(得分:2)

MKL功能预先做了很多工作,试图猜测什么是最快的执行操作的方式,所以在处理双打时它会产生不同的决定并不奇怪或单打。

在决定采用哪种策略时,必须权衡在单个线程中执行操作的成本与启动线程并行执行操作的开销。将要发挥作用的一个因素是SSE指令可以对单精度数字进行操作,速度是双精度数字的两倍,因此启发式可能很好地决定它可能更快地对单身操作作为SSE进行操作SIMD操作在单个核心而不是踢十二个线程并行执行。它可以并行完成多少取决于CPU架构的细节;例如,SSE2可以对四个单个操作数或两个双操作数进行操作,而更新的SSE指令集可以支持更宽的数据。

我在过去发现,对于小矩阵/向量,滚动自己的函数通常比使用MKL更快。例如,如果所有操作都在3向量和3x3矩阵上,那么在普通C中编写自己的BLAS函数要快得多,并且再次更快用SSE优化它们(如果你能满足对齐的话)约束)。对于3向和6向量的混合,编写自己的优化SSE版本仍然更快。这是因为当操作很小时,决定使用哪种策略的MKL版本的成本会变得相当大。