请参阅下面的进一步更新
在运行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 *也是如此)。还有什么想法?也许还有一些其他命令来检查我不知道的库版本?
答案 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次!
补救:
使用非线程BLAS和LAPACK
如果使用OpenMP set OMP_NUM_THREADS=1
完成并行化,这意味着只使用一个线程
根本不使用LAPACK,因为特殊情况3x3可以使用专门的算法https://en.wikipedia.org/wiki/Eigenvalue_algorithm#3.C3.973_matrices