当gemm做时,sgemm不多线程
sgemm does not multithread when dgemm does - 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没有。它只使用一个核心,当然,需要更长的时间。当然,对于sgemm,我使用浮点数数组,而对于dgemm,我使用双精度数数组。
为什么会这样?它们都给出了准确的结果,但是在前者上只使用多线程,而在两者上都使用多线程!简单地改变数据类型怎么会产生这种差异呢?
请注意,所有数组都是使用mkl_malloc分配的,使用64的对齐方式。
编辑2:还请注意,当l=12时,换句话说,有一个更大的矩阵,它在sgemm中线程。换句话说,很明显,sgemm版本需要更大的矩阵来并行化,但dgemm没有这个要求。为什么会这样?
MKL函数预先做了相当多的工作来尝试猜测执行操作的最快方式,因此在处理双精度数或单精度数时得出不同的决定并不奇怪。
在决定采用哪种策略时,它必须权衡在单个线程中执行操作的成本与启动线程并行执行操作的开销。其中一个重要的因素是SSE指令对单精度数字的操作速度是双精度数字的两倍,因此启发式可能会认为,在单个核上执行SSE SIMD操作可能比在单个核上执行SSE SIMD操作更快,而不是踢开12个线程并行执行。它到底能并行处理多少将取决于你的CPU架构的细节;例如,SSE2可以对四个单操作数或两个双操作数进行操作,而最新的SSE指令集支持更广泛的数据。
我在过去发现,对于小矩阵/向量,滚动自己的函数通常比使用MKL更快。例如,如果您的所有操作都是在3向量和3x3矩阵上,那么用纯C编写自己的BLAS函数要快得多,使用SSE优化它们要快得多(如果您能满足对齐约束)。对于3向量和6向量的混合,编写自己的优化SSE版本仍然更快。这是因为当操作很小时,MKL版本决定使用哪种策略的成本会成为相当大的开销。
- 在C++中使用cURL和多线程
- 多线程双缓冲区
- 为什么我的多线程作业队列崩溃
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 试图创建一个多线程程序来查找0-100000000之间的总素数
- 为什么一个向量上的多线程操作很慢
- 学习多线程C++:添加线程不会使执行速度更快,即使它看起来应该
- 全局变量 多读取器 一个写入器多线程安全?
- boost::文件系统::recursive_directory_iterator多线程安全
- 如何阻止TensorFlow的多线程
- 如何在多线程中正确使用unique_ptr进行多态性?
- 并发/多线程:是否可以以这种方式生成相同的输出?
- sigwait() 在多线程程序中不起作用
- 多线程程序中出现意外的内存泄漏
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 多线程比没有线程C++慢
- 具有 C++11 多线程的特征库
- 通过安装信号处理程序关闭多线程应用程序
- 成员变量在多线程 C++ 时自行更改
- 当gemm做时,sgemm不多线程