【问题标题】:Fortran LAPACK: high CPU %sys usage with DSYEV - no parallelization - normal?Fortran LAPACK:DSYEV 的 CPU %sys 使用率高 - 没有并行化 - 正常吗?
【发布时间】:2016-06-25 21:56:42
【问题描述】:

请参阅下面的进一步更新

在运行我的 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 sys 使用率。比较这两个系统,我似乎无法找到它的来源。两者都运行相同的操作系统版本(Linux Ubuntu)、相同的 gfortran 版本(4.8)、内核版本、LAPACK 和 BLAS。 “主要”区别:处理器是有问题的系统上的 i7-4770 和另一个上的 i7-870。在越野车上运行测试代码给了我关于 %user 16s%sys 28s 的信息。在 i7-870 上是 %user 16s %sys 0s。将代码运行四次(并行)给我每个进程的总时间约为 在另一个系统上 18 秒在有问题的系统上 44 秒。 任何想法我还能寻找什么?

更新 3 我想我们越来越近了: 在具有 LAPACK 和 BLAS 库的静态链接的其他系统上构建测试程序,

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

并在有问题的系统中运行该代码使我的 %sys 时间约为 0(根据需要)。另一方面,在有问题的系统上使用指向 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* 也是如此)。还有什么想法吗?也许还有其他一些我不知道的检查库版本的命令?

【问题讨论】:

  • 你的有限元模型有多少个元素?
  • 查看嵌入在此答案中的nmon 开发人员的评论:stackoverflow.com/a/5738139/620097。如果没有办法重现您的问题,这个 Q 可能会被认为是题外话(尽管它可能很有趣)。祝你好运。
  • 我目前正在研究的模型只有大约 4000 个元素。但大小似乎不是问题,因为我可以用更小的模型重现这种行为。问题是:使用基于 Fortran 的商业 FEM 代码,只使用一个真正的单核(0% sys CPU 使用率)。所以我看不到@shellter 暗示的评论中的意义。
  • 你的 LAPACK 有线程吗?您的 LAPACK 和 BLAS 实施从何而来?
  • LAPACK 和 BLAS 来自 repo(liblapack3 和 libblas3)。据我所知,那些没有线程,是吗?

标签: linux fortran cpu-usage lapack blas


【解决方案1】:

我对减速的解释:

我们使用了 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

【讨论】:

  • 非常感谢您提供答案。我确实坚持使用 openblas,尽管我设置了 OPENBLAS_NUM_THREADS=1。我提供的测试程序只是一个小例子,除了求解 3x3 矩阵的特征值之外,还有更多对 LAPACK/BLAS 的调用。尽管如此,我确实将那些小型系统的调用从 LAPACK 更改为更快的求解器。感谢您的提示!
猜你喜欢
  • 2017-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-01
  • 1970-01-01
相关资源
最近更新 更多