在尝试用 LazyNet 时,由于原作者提供的OpenCV和OpenBLAS版本和我的环境不一样,考虑自行配置依赖。
OpenCV源码编译的文章很多,这里主要说一下OpenBLAS的编译。
cblas_sgemm crash
基于VS2017的MSVC编译器,编译安装openblas develop分支最新版,发现 LazyNet 代码有crash(access violation),而在Linux(ubuntu16.04,G++/Clang++-8)则运行正常。剥离出来的复现问题的最小化代码见下方,解决办法是用clang-cl(Windows下和MSVC兼容的clang编译器)重新编译OpenBLAS,讨论帖在此。
#include <stdio.h>
extern "C" {
#include <cblas.h>
}
int main() {
printf("OpenBLAS config info:\n%s\n", openblas_get_config());
#if 1 // will cause crash on VS2017 x64 with OpenBLAS latest
const int M = 16;
const int N = 676;
const int K = 27;
#else // won‘t crash
const int M = 4;
const int N = 2;
const int K = 3;
#endif
const float alpha = 1.0f;
const float beta = 0.f;
int lda = K;
int ldb = N;
int ldc = N;
float A[M*K];
float B[K*N];
float C[M*N];
cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, M, N, K, alpha, A, lda, B,
ldb, beta, C, ldc);
return 0;
}
clang-cl编译OpenBLAS步骤
尽管 OpenBLAS 官方 wiki 页面 How to use OpenBLAS in Microsoft Visual Studio 已经贴出了具体步骤,不过一开始我并没有去翻看此文档,想当然的认为CMake + VS2017即可。实践下来发现我并不需要fortran(用不到LAPACK),所用步骤如下:
1. 安装依赖软件
Visual Studio 2017
我没有勾选里面的Clang。后续用conda装。
CMake
我手动从官网下载的二进制包。conda安装的cmake似乎不带cmake-gui,查看CMakeCache的时候不方便。
Ninja
因为不用fortran(flang)编译,因此不必更新为kitware-ninja,常规版本即可。
conda安装的
我用的Miniconda,你用Anaconda也行,反正是用里面的conda作为包管理工具。注意conda并非只能安装Python的包(甚至pip也能装cmake,不过个人不喜欢这么做)。
首先配置conda源,在GitBash中编辑~/.condarc
channels:
- conda-forge
- defaults
show_channel_urls: true
default_channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
custom_channels:
conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
其次执行如下命令:
conda update -n base conda
conda install -y clangdev perl
2. 编译安装
下载源码
cd /d/dev
#git clone https://gitee.com/aczz/OpenBLAS
git clone https://gitee.com/xianyi/OpenBLAS
cd OpenBLAS
git checkout develop
写构建脚本
mkdir build
vim build/clang-cl.bat
build/clang-cl.bat
内容如下:
@echo off
set "LIB=%CONDA_INSTALL_LOCN%\Library\lib;%LIB%"
set "CPATH=%CONDA_INSTALL_LOCN%\Library\include;%CPATH%"
set BUILD_DIR="clang-cl"
if not exist %BUILD_DIR% mkdir %BUILD_DIR%
cd %BUILD_DIR%
cmake ../.. -G "Ninja" -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER=clang-cl -DBUILD_WITHOUT_LAPACK=yes -DDYNAMIC_ARCH=ON -DCMAKE_BUILD_TYPE=Release
cd ..
执行构建和安装
"c:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Auxiliary/Build/vcvars64.bat"
cd build
clang-cl.bat
cmake --build . --config Release
cmake --install . --prefix d:/lib/openblas/clang-cl/x64 -v
3. 使用OpenBLAS
这里主要说一下 CMake 里设置 OpenBLAS:实测可用的例子:
# OpenBLAS_DIR 指向包含OpenBLASConfig.cmake的目录
set(OpenBLAS_DIR "D:/lib/openblas/clang-cl/x64/share/cmake/OpenBLAS")
find_package(OpenBLAS REQUIRED)
add_executable(lazynet
${lazynet_srcs}
${lazynet_incs}
)
target_include_directories(lazynet
PUBLIC include
${OpenBLAS_INCLUDE_DIRS}
)
set(lazynet_dep_libs ${OpenCV_LIBS} ${OpenBLAS_LIBRARY})
if(UNIX)
list(APPEND lazynet_dep_libs pthread)
endif()
注意点:
- 不要用
OpenBLAS_LIBRARIES
变量
打印出来它的值为空,而不是像OpenBLASConfig.cmake
的注释中写的那样,“和OpenBLAS_LIBRARIY相同”
- 不要信
FindBLAS.cmake
文件
尽管CMake(我用的3.17.1)安装目录下提供了FindBLAS.cmake
文件,看似提供了各种BLAS的查找功能,但就OpenBLAS来说,在Windows下还不如手动设定;在Linux下仅对于apt安装的openblas(版本通常很老)能找到库文件,但并不提供头文件查找目录,需要自行设定:
set(BLA_VENDOR "OpenBLAS")
find_package(BLAS REQUIRED)
set(OpenBLAS_INCLUDE_DIRS "/usr/include/openblas")
set(OpenBLAS_LIBRARY ${BLAS_LIBRARIES})
而手动编译的openblas则并不能被很优雅的找到。因而,请忽略FindBLAS.cmake
这一文件。
- 自行编译的openblas,在Linux下使用时,需要额外链接pthread库