恒's profileFrensel的日记PhotosBlogLists Tools Help

Blog


    March 31

    OpenMP怪问题

    我近日遇到一个奇怪的问题,想不通……
    我写了个OpenMP的测试程序,放在不同CPU的机上使用相同的编译器(Intel Visual Fortran Compiler 9.1)编译,运行时间差别很大。例如下面这程序:
    !  OMPtest.f90
        program OMPtest
            implicit none
            integer, parameter :: N = 100
            real(8) :: A(N, N), B(N, N), C(N, N), D(N, N)     
            integer :: i
    LN = 1000000
            integer :: timediff, time(2)
            integer :: num_threads = 2
           
           
    call omp_set_num_threads(num_threads)
            call random_number(A)
            call random_number(B)

           
           
    ! clock
            call system_clock(time(1))

           
           
    !$OMP PARALLEL
            !$omp do
            do i = 1, LN
                C =  A + B
           
    end do
            !$omp end do

            call system_clock(time(2))
            timediff = time(2) - time(1)
           

            print *, "Elapsed time is", timediff / 10000e0, "seconds"
           
    print *, C(1 : 3, 1 : 3)
       
    end program OMPtest
    这程序是有毛病的,主要是!$omp do这句,后面应该加上private(C)lastprivate(C)字句,避免下面的循环在多线程运算时,使用相同的C
    这程序在E6400中编译运行时,竟然毫无问题,使用10秒左右就算完(单线程时要约17秒)。然而,把这相同的程序,放到Pentium D 925上运算,也是使用双线程,竟然要50多秒才算完(单线程时要约18秒)。尽管CPU不同,但我是用相同的编译器,用相同的参数去编译,实在不能理解为什么结果会差那么多。当然,在!$omp do后面加上private(C)lastprivate(C)字句,Pentium D 925也能用10秒多一点算完这个程序。

    November 05

    Intel Visual Fortran中编译MEX文件

    要自己在Microsoft Visual Studio .NET中使用Intel Visual Fortran Compiler编译MEX文件,必须做一系列的设定。这些内容在Matlab的Help中有说明(Custom Building on Windows)。其中的内容主要针对C++,尽管Fortran的设置也是类似的,但有一点必须注意。有一步要设Module-Definition File(.def),这个东西在Compaq Visual Fortran(CVF)和Intel Visual Fortran(IVF)中是不同的。CVF中,是EXPORTS _MEXFUNCTION@16;IVF中是EXPORTS MEXFUNCTION,搞错了就会出现LNK2001: unsolved external symbol。其实设这些东西,大可先参考Matlab自己bat文件中的设定。可到C:\Program Files\MATLAB\R2006b\bin\win32\mexopts找出intelf90opts.bat,这东西就是Matlab自己做的设定,在Matlab中使用mex命令编译时就是根据这文件的设置来编译的。
    October 14

    Intel Math Kernel Library的多线程小测试

    近来在试用Intel那个Math Kernel Library(MKL)。那东西挺不错,集成了BLAS、CBLAS、LAPACK、ScaLAPACK、矢量数学、矢量统计和FFT等库。其中有些地方使用了OpenMP作多线程计算,用户只需设定一个环境变量,便能令该部份作任意线程数运行。MKL中的BLAS level3运算全部都可以多线程化,我们便以此做测试。测试中我们为了简单起见,使用了BLAS95接口,减少输入参数个数。测试的CPU是Intel Core 2 Duo E6400。
        program test_MKL_BLAS3
        use mkl95_blas
        implicit none
       
        integer, parameter :: N = 1000
        real(8) :: a(N, N), b(N, N), c(N, N)
        integer :: timediff, i
        integer :: time(2)
       
        a = 1.23456789d0
        b = 9.87654321d0
       
        !time
        call system_clock(time(1))
        do i = 1, 30
            call gemm(a, b, c) !c = a * b, BLAS Level 3 subroutine
        end do
        call system_clock(time(2))
        timediff = time(2) - time(1)
       
        print *, "finish..."
        print *, "the duration of the program is ", timediff / 10000e0, "s"
       
        end program test_MKL_BLAS3
    此程序就是做矩阵大小为1000x1000的矩阵-矩阵相乘30次,使用BLAS Level 3子程序gemm。在Release模式下编译为执行文件test_MKL_BLAS3.exe。要使用多线程运算,必须在运行前设定环境变量OMP_NUM_THREADS。如果没有设定,则默认为1个线程。我们首先让程序运行在1个线程下,进入相应的目录,在命令行下输入:
    C:\your directory\test_MKL_BLAS3
     finish...
     the duration of the program is   11.61000 s
    即用了约11.6秒。接着我们令BLAS Level 3运行在两个线程下,即在命令行输入:
    C:\your directory\set OMP_NUM_THREADS=2
    C:\your directory\test_MKL_BLAS3
     finish...
     the duration of the program is   6.156000 s
    使用了约6.2秒,比单线程时要快约47%。另外,在Intel Dothan 730(单核的笔记本CPU,主频1.6GHz)中测试,要约53秒……差距巨大……