Fortran LAPACK:使用DSYEV的CPU%使用率高 - 没有并行化 - 正常吗?

时间:2016-03-10 20:46:39

标签: linux fortran cpu-usage lapack blas

请参阅下面的进一步更新

在运行Fortran代码时,我正在观察安静的高系统CPU使用率。 “用户CPU使用率”占用大约一个核心(系统是Intel i7,4核/ 8线程,运行Linux),而系统CPU占用大约2个核心(因此整体CPU使用率约为75%)。任何人都可以向我解释这是来自何处以及这是“正常”行为吗?

我用gfortran编译代码(优化关闭了-O0,虽然那部分似乎并不重要)并且链接了BLAS,LAPACK和一些(其他)C函数。我自己的代码没有使用任何并行化,链接代码也没有(据我所知)。至少我没有使用任何并行化的库版本。

代码本身是关于组装和解决有限元系统并使用大量(?)分配和内部函数调用(matmul,dot_product),尽管整体RAM使用率非常低(~200MB)。我不知道这些信息是否足够/有用,但我希望有人知道那里发生了什么。

祝你好运, 本

更新 我想我从LAPACK中调用了DSYEV来解决(部分)问题(计算真实symm的特征值。矩阵A,在我的情况下为3x3)。

program test

implicit none

integer,parameter :: ndim=3
real(8) :: tens(ndim,ndim)

integer :: mm,nn
real(8), dimension(ndim,ndim):: eigvec
real(8), dimension(ndim)   :: eigval

character, parameter    :: jobz='v'  ! Flags calculation of eigenvectors
character, parameter    :: uplo='u'  ! Flags upper triangular 
integer, parameter      :: lwork=102   ! Length of work array
real(8), dimension(lwork)  :: work      ! Work array
integer :: info   

tens(1,:) = [1.d0, 2.d0, 3.d0]
tens(2,:) = [2.d0, 5.d0, 1.d0]
tens(3,:) = [3.d0, 1.d0, 1.d0]   

do mm=1,5000000    
    eigvec=tens
   ! Call DSYEV
   call dsyev(jobz,uplo,ndim,eigvec,ndim,eigval,work,lwork,info)
enddo

write(*,*) eigvec
write(*,*) int(work(1))

endprogram test

使用

完成编译和链接
gfortran test.f90 -o test -llapack

这个程序给了我非常高的%sys CPU使用率。任何人都可以验证这一点(显然LAPACK是解密代码所必需的)吗?这是“正常”行为还是我的代码/系统/图书馆员出了问题......?

更新2 受到@ roygvib评论的鼓励,我在另一个系统上运行了代码。在第二个系统上,无法再现高CPU系统使用率。比较这两个系统我似乎无法找到它的来源。两者都运行相同的操作系统版本(Linux Ubuntu),相同的gfortran版本(4.8),内核版本,LAPACK和BLAS。 “主要”差异:处理器在越野车系统上是i7-4770,在另一个上是i7-870。在错误的测试代码上运行测试代码给了我%user 16s %sys 28s 。在i7-870上,它是%user 16s %sys 0s 。运行代码四次(并行)为我提供了关于 18s在另一个系统上 44s在错误系统上的每个过程的总体时间。 任何想法我还能找到什么?

更新3 我想我们越来越近了: 使用到LAPACK和BLAS库的静态链接在另一个系统上构建测试程序,

gfortran test.f90 -O0 /usr/lib/liblapack.a /usr/lib/libblas.a -Wl,--allow-multiple-definition

并且在错误系统中运行该代码给了我一个约为0的%sys时间(根据需要)。另一方面,使用到错误系统上的LAPACK和BLAS的静态链接构建测试程序并在另一个系统上运行代码也会返回高%sys CPU使用率!显然,图书馆似乎有所不同,对吧? 在错误系统上构建静态版本会导致文件大小约为18MB(!),而另一个系统则为100KB。另外,我必须包括

-Wl,--allow-multiple-definition

仅在其他系统上执行命令(否则会抱怨xerbla的多个定义),而在错误系统上我必须(明确地)链接到libpthread

gfortran test.f90 -O0 /usr/lib/liblapack.a /usr/lib/libblas.a -lpthread -o test

有趣的是

apt-cache policy liblapack*

返回两个系统的相同版本和repo目的地(libblas *也是如此)。还有什么想法?也许还有一些其他命令来检查我不知道的库版本?

1 个答案:

答案 0 :(得分:2)

我对经济放缓的解释:

使用了LAPACK和BLAS的线程(可能是OpenMP)版本。这些尝试启动多个线程来并行解决线性代数问题。这通常可以加快计算速度。

然而在这种情况下

do mm=1,5000000    
   eigvec=tens
   call dsyev(jobz,uplo,ndim,eigvec,ndim,eigval,work,lwork,info)
enddo

这有很多次调用库来解决一个非常小的问题(一个3x3矩阵)。这不能有效地并行解决,矩阵太小。与线程同步相关的开销主导了解决方案时间。同步(如果不是线程创建)完成 5000000次

补救:

  1. 使用非线程BLAS和LAPACK

  2. 如果使用OpenMP set OMP_NUM_THREADS=1完成并行化,这意味着只使用一个线程

  3. 根本不使用LAPACK,因为特殊情况3x3可以使用专门的算法https://en.wikipedia.org/wiki/Eigenvalue_algorithm#3.C3.973_matrices

相关问题