Eigen 使用 MKL 加速矩阵运算
介绍
Intel Math Kernel Library (MKL) 是一套高度优化的数学库,用于加速数学计算。通过将 Eigen 与 MKL 结合使用,可以显著提升矩阵运算的性能。
安装 MKL
- 下载 MKL: 访问 MKL 官方下载页面:Intel MKL 下载
- 安装 MKL:
解压下载的文件后,使用
install_GUI.sh进行安装。默认安装路径为/opt/intel/mkl。 - 配置环境变量:
-
编辑
/etc/ld.so.conf.d/intel_mkl.conf,添加以下内容: -
运行
sudo ldconfig。 -
编辑
/etc/profile,添加: -
运行
sudo source /etc/profile,建议重启电脑以确保配置生效。
Eigen + MKL 的 CMake 配置
工程目录结构
CMakeLists.txt 示例
cmake_minimum_required(VERSION 3.0)
project(EigenMKLTest)
# 设置 CMake 模块路径
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/")
# 查找 Eigen 和 MKL 包
find_package(Eigen3 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})
find_package(MKL REQUIRED)
include_directories(${MKL_INCLUDE_DIR})
include_directories(${PROJECT_SOURCE_DIR})
# 设置 C++ 标准和 OpenMP 支持
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fopenmp")
# 添加执行文件
add_executable(main main.cpp)
# 链接 MKL 库
target_link_libraries(main ${MKL_LIBRARIES})
FindMKL.cmake 配置
FindMKL.cmake 文件用于帮助 CMake 找到 MKL 库,其内容较为复杂,以下是关键部分:
# 查找 MKL 库路径
find_path(MKL_ROOT_DIR include/mkl_cblas.h PATHS /opt/intel/mkl/)
find_path(MKL_INCLUDE_DIR mkl_cblas.h PATHS ${MKL_ROOT_DIR}/include)
find_library(MKL_CORE_LIBRARY mkl_core PATHS ${MKL_ROOT_DIR}/lib/intel64)
# 设置 MKL 库选项
set(MKL_LIBRARIES ${MKL_LP_SEQUENTIAL_LIBRARIES})
# 查找线程库
find_library(MKL_SEQUENTIAL_LIBRARY mkl_sequential PATHS ${MKL_ROOT_DIR}/lib/intel64)
set(MKL_LIBRARIES ${MKL_LP_SEQUENTIAL_LIBRARIES})
# 支持 OpenMP
find_library(MKL_GNUTHREAD_LIBRARY mkl_gnu_thread PATHS ${MKL_ROOT_DIR}/lib/intel64)
set(MKL_LIBRARIES ${MKL_LP_GNUTHREAD_LIBRARIES})
示例代码
以下示例代码展示了如何使用 Eigen 和 MKL 进行矩阵乘法运算:
#define EIGEN_USE_MKL_ALL
#define EIGEN_VECTORIZE_SSE4_2
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <time.h>
int main() {
srand((unsigned)time(NULL));
clock_t start, finish;
double totaltime;
start = clock();
// 创建两个 7000x7000 的随机矩阵
Eigen::MatrixXf m1 = Eigen::MatrixXf::Random(7000, 7000);
Eigen::MatrixXf m2 = Eigen::MatrixXf::Random(7000, 7000);
// 矩阵乘法
Eigen::MatrixXf m3 = m1 * m2;
finish = clock();
totaltime = (double)(finish - start) / CLOCKS_PER_SEC;
std::cout << "矩阵乘法运行时间: " << totaltime << " 秒" << std::endl;
return 0;
}
编译和运行
- 编译代码: 使用 CMake 生成 Makefile 并编译代码:
- 运行程序:
性能对比
在高阶矩阵运算中,MKL 可显著提升性能。以下为不同配置下的性能对比:
| 测试项 | 线程 | 时间 (秒) |
|---|---|---|
| Eigen | 1 | 27.1427 |
| Eigen + OpenMP | 2 | 31.3295 |
| Eigen + MKL 单线程 | 1 | 8.43301 |
| Eigen + MKL 多线程 | 2 | 9.5142 |
注意事项
- MKL 的单线程模式在低阶矩阵运算中可能更快。
- 对于 Ubuntu 系统,推荐使用 GNU 多线程配置。
- 添加
#define EIGEN_DONT_PARALLELIZE可使 Eigen 不使用任何并行加速,但对 Eigen+MKL 配置无效。
通过以上步骤,你可以成功配置 Eigen 使用 MKL 进行加速,显著提升矩阵运算的性能。