Eigen vs Matlab:并行矩阵乘法
Eigen vs Matlab: parallelized Matrix-Multiplication
我想比较矩阵乘法中 Matlab 的速度与英特尔(R) 酷睿(TM) i7-4770 CPU @ 3.40GHz 上特征 3 的速度。包含特征的代码:
#include <iostream>
#include "Eigen/Dense"
#include <chrono>
#include <omp.h>
using namespace std;
using namespace Eigen;
const int dim=100;
int main()
{
std::chrono::time_point<std::chrono::system_clock> start, end;
int n;
n = Eigen::nbThreads();
cout<<n<<"n";
Matrix<double, Dynamic, Dynamic> m1(dim,dim);
Matrix<double, Dynamic, Dynamic> m2(dim,dim);
Matrix<double, Dynamic, Dynamic> m_res(dim,dim);
start = std::chrono::system_clock::now();
for (int i = 0 ; i <100000; ++i) {
m1.setRandom(dim,dim);
m2.setRandom(dim,dim);
m_res=m1*m2;
}
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::cout << "elapsed time: " << elapsed_seconds.count() << "sn";
return 0;
}
它是用g++ -O3 -std=c++11 -fopenmp
编译的,用OMP_NUM_THREADS=8 ./prog
执行的。在我正在使用的 Matlab 中
function mat_test(N,dim)
%
% N: how many tests
% dim: dimension of the matrices
tic
parfor i=1:N
A = rand(dim);
B = rand(dim);
C = A*B;
end
toc
结果是:Matlab 为 9s,特征为 36s。在本征案中,我做错了什么?我可以排除矩阵的动态分配。此外,仅使用 3 个线程而不是 8 个线程。
编辑:
也许我没有说得足够清楚:任务是将 dim=100 的双值矩阵乘以 100000 次,这些矩阵每次都是随机填充的,而不仅仅是一次。使用本征尽可能快地完成。如果 Eigen 无法应对 Matlab,你会建议什么选择?
下面是合理使用Eigen的代码的更好版本。总结一下:
- 将
setRandom()
移出基准测试循环。setRandom()
调用系统rand()
函数,这相当慢。 - 使用
.noalias()
以避免创建临时(仅当右侧是产品时才有意义) - 将OMP_NUM_THREADS设置为真正的内核数,而不是超线程数。(4 在您的情况下) 您的 CPU 支持 AVX 和 FMA
- ,这些 AVX 和 FMA 仅受 Eigen 的 devel 分支支持(将变为 3.3),因此请使用 devel 分支并使用
-mavx
和-mfma
编译器选项启用它们(与仅 SSE 相比,速度约为 x3.5)
代码:
#include <iostream>
#include "Eigen/Dense"
#include <chrono>
using namespace std;
using namespace Eigen;
const int dim=100;
int main()
{
std::chrono::time_point<std::chrono::system_clock> start, end;
int n;
n = Eigen::nbThreads();
cout << n << "n";
Matrix<double, Dynamic, Dynamic> m1(dim,dim);
Matrix<double, Dynamic, Dynamic> m2(dim,dim);
Matrix<double, Dynamic, Dynamic> m_res(dim,dim);
start = std::chrono::system_clock::now();
m1.setRandom();
m2.setRandom();
for (int i = 0 ; i <100000; ++i) {
m_res.noalias() = m1 * m2;
}
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::cout << "elapsed time: " << elapsed_seconds.count() << "sn";
return 0;
}
除了将随机化移出循环(在 Eigen 和 Matlab 中),正如 ggael 建议的那样,在 Matlab 中将 parfor
替换为 for
,因为在 Eigen 代码中,您可以按顺序处理矩阵。
我不确定 Matlab 是如何并行化其代码的:也许多个线程在同一对矩阵上工作,并在完成后切换到下一个矩阵;也许每个线程处理自己的矩阵对。有人可能会争辩说,后者可能更快,因为更好地使用了特定于核心的缓存。
相关文章:
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 数据成员SFINAE的C++17测试:gcc vs clang
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- C++17中的并行执行策略
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 正在VS调试器中监视映射条目
- Confusion: decltype vs std::function
- 将IBM Rhapsody模型集成到VS 2019中
- VS Code "command":"make"与终端窗口中的命令行"make"不同
- 使用VS Code和CMake Tools运行自定义命令
- 并行用于C++17中数组索引范围内的循环
- 如何在Elixir中调用递归函数并行
- OpenMP:并行更新数组总是需要减少数组吗
- 修改 VS Code 中的默认C++代码段
- 如何使用c++在VS 2019上运行SQL查询
- vs 2015 constexpr变量不恒定,但与2019相比还好吗
- Eigen vs Matlab:并行矩阵乘法
- 并行OpenMP缩减vs.函数定义
- 微软TPL(任务并行库)vs英特尔TBB(线程构建块)