Skip to content

Eigen 使用 MKL 加速矩阵运算

介绍

Intel Math Kernel Library (MKL) 是一套高度优化的数学库,用于加速数学计算。通过将 Eigen 与 MKL 结合使用,可以显著提升矩阵运算的性能。

安装 MKL

  1. 下载 MKL: 访问 MKL 官方下载页面:Intel MKL 下载
  2. 安装 MKL: 解压下载的文件后,使用 install_GUI.sh 进行安装。默认安装路径为 /opt/intel/mkl
  3. 配置环境变量
  4. 编辑 /etc/ld.so.conf.d/intel_mkl.conf,添加以下内容:

    /opt/intel/lib/intel64
    /opt/intel/mkl/lib/intel64
    
  5. 运行 sudo ldconfig

  6. 编辑 /etc/profile,添加:

    export MKL_ROOT_DIR=/opt/intel/mkl
    
  7. 运行 sudo source /etc/profile,建议重启电脑以确保配置生效。

Eigen + MKL 的 CMake 配置

工程目录结构

/
├── CMakeLists.txt
├── FindMKL.cmake
└── main.cpp

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;
}

编译和运行

  1. 编译代码: 使用 CMake 生成 Makefile 并编译代码:
cmake .
make
  1. 运行程序
./main

性能对比

在高阶矩阵运算中,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 进行加速,显著提升矩阵运算的性能。

Ref

http://xiazuomo.com/2018/eigen-with-mkl/