如何在Eigen的cwise逐元素操作中启用多线程?
Eigen逐元素操作启用多线程的方法
问题背景
我代码里有大量类似点乘的逐元素操作,发现Eigen的cwise操作未启用多线程,自己用OpenMP实现的同类操作速度更快:
Eigen实现(耗时4.4ms)
Eigen::setNbThreads(10); int n = 2048*2560; MatrixXd A = MatrixXd::Ones(1, n); MatrixXd B = MatrixXd::Ones(1, n); MatrixXd D(1, n); clock_t start = clock(); for (int i = 0; i < 1000; i++) { D = A.array() *10 *B.array(); } clock_t end = clock(); double thisTime = (double)(end - start)/1000; std::cout << thisTime << std::endl;
自研OpenMP实现(耗时2.607ms)
int n = 2048*2560; MatrixXd A = MatrixXd::Ones(1, n); MatrixXd B = MatrixXd::Ones(1, n); MatrixXd D(1, n); clock_t start = clock(); for (int i = 0; i < 1000; i++) { #pragma omp parallel for num_threads(10) for (int j = 0; j < n; j++) { D(0, j) = A(0,j) * 10 * B(0, j); } } clock_t end = clock(); double thisTime = (double)(end - start)/1000; std::cout << thisTime << std::endl;
解决方法
编译时开启OpenMP支持
Eigen默认不启用OpenMP,编译必须添加对应编译器的OpenMP选项:GCC/Clang加-fopenmp,MSVC加/openmp。只有开启这个,Eigen的多线程才能依托OpenMP生效。调整并行阈值
Eigen对逐元素操作的并行有最小元素数阈值,默认值可能较高,导致你的行向量操作没触发并行。可以手动调低阈值:Eigen::setParallelThreshold(1024); // 按需调整,比如设为1024或更小当元素数量超过这个值时,Eigen会自动启用并行处理。
优化矩阵存储布局
Eigen默认是列优先存储,你的1×n行向量在内存中连续,但Eigen对列向量的并行优化更友好。可以改用行优先存储的矩阵,或者把向量改成n×1的列向量:// 行优先存储的行向量 Matrix<double, 1, Eigen::Dynamic, Eigen::RowMajor> A = Matrix<double,1,Eigen::Dynamic,Eigen::RowMajor>::Ones(1, n);这样能减少缓存失效,提升并行效率。
验证线程设置
调用Eigen::setNbThreads(10)后,通过Eigen::nbThreads()返回值确认线程数是否设置成功,避免因环境问题导致线程数不生效。
调整以上参数后,重新测试性能,不同硬件和数据规模下的最优设置可能有差异,需根据实际情况微调。
内容的提问来源于stack exchange,提问作者Oct
相关产品推荐
相关产品推荐

