24小时热门版块排行榜    

查看: 655  |  回复: 1

holmescn

金虫 (正式写手)

[交流] 初试OpenMP

先上代码
CODE:
Program euler41
    Implicit None
    Integer, Parameter :: N = 9
    Integer, Dimension(N) :: Digits
    Integer :: I, R, X

    ! Digits
    Digits = (/(I, I=N,1,-1)/)

    !$OMP PARALLEL SHARED(Digits) Private(R,I,X)
    !$OMP DO
    Do R = 9, 1, -1
        Do I = 1, Arrangement(N, R)
            X = Permutations(R, I)
            If(IsPrime(X)) Then
                Print *, X
            EndIf
        EndDo
    EndDo
    !$OMP END DO
    !$OMP END PARALLEL

Contains

    Function Arrangement(N, M) Result(R)
        Implicit None
        Integer, intent(in) :: N, M
        Integer :: R
        Integer :: I
        R = 1
        Do I = (N-M+1), N
            R = R * I
        End DO
    EndFunction

    Function IsPrime(N) Result(R)
        Implicit None
        Integer :: N, I
        Logical :: R
        R = .True.
        !$OMP PARALLEL SHARED(N, R) PRIVATE(I)
        !$OMP DO
        DO I = 2, Floor(Sqrt(N*1.0))
            If(Mod(N, I) == 0) Then
                R = .False.
            EndIf
        EndDo
        !$OMP END DO
        !$OMP END PARALLEL
        Return
    EndFunction

    Function Permutations(R, nth) Result(V)
        Implicit None
        Integer, Dimension(N) :: Indices
        Integer, Intent(In) :: R, nth
        Integer :: V
        Integer :: M
        Integer :: Factorial
        Integer :: I, J, K

        Indices = 1
        M = nth - 1
        V = 0
        Factorial = Arrangement(N-1, N-1)

        Do I = 1, R
            J = M / Factorial + 1
            M = Mod(M, Factorial)
            If(N.ne.I) Factorial = Factorial / (N-I)

            ! Find the index
            K = 1
            Do
                If(Indices(K) > 0) J = J - 1
                If(J .eq. 0) Exit
                K = K + 1
            End Do
            Indices(K) = 0

            ! Gen the Number
            V = V*10 + Digits(K)
        EndDo
    EndFunction
End Program euler41

题目是Euler工程的第四十一题. 这个题显然是可以并行的. 因为生成一个排列数, 和判断这个数是不是质数是并行的.同时, 判断一个数是不是质数也是可以并行的, 因为判断某个数是不是给定数的因数这个操作是independent的.

这样, 就有了上面的代码. 但不知道是什么地方写的不对, 用gfortran 编译的时候, 使用-openmp选项, 好像没有起什么作用. 运行速度还是和没有openmp的一样. 使用top查看,也没看出多线程来. 使用ifort编译,运行结果出错. 真是有些郁闷.

具体情况还在研究中. 大家一起讨论讨论吧.
回复此楼
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

holmescn

金虫 (正式写手)


jjdg(金币+1): 欢迎在本版开题讨论 2011-07-14 20:12:32
1. 调整了一下程序. 减少了一些重复运算.
2. 同时, 把OpenMP的directive写得简单了.
3. gfotran 的openmp 是使用 -fopenmp, 而intel的是-openmp

结果, gfortran -fopenmp -O3 这样编译, 还是需要43s才能运行完. 而ifort -openmp -O3只需要0.6s了.
CODE:
Program euler41
    Implicit None
    Integer, Parameter :: N = 9
    Integer, Dimension(N) :: Digits
    Integer :: I, R, X
    Integer :: Fac

    ! Digits
    Digits = (/(I, I=N,1,-1)/)
    Fac = Arrangement(N-1, N-1)

    Do R = 9, 1, -1
    !$OMP PARALLEL DO
        Do I = 1, Arrangement(N, R)
            X = Permutations(R, I, Fac)
            If(IsPrime(X) .and. X > 97000000) Then
                Print *, X
                Stop
            EndIf
        EndDo
    !$OMP END PARALLEL DO
    EndDo
Contains

    Function Arrangement(N, M) Result(R)
        Implicit None
        Integer, intent(in) :: N, M
        Integer :: R
        Integer :: I
        R = 1
        Do I = (N-M+1), N
            R = R * I
        End DO
    EndFunction

    Function IsPrime(N) Result(R)
        Implicit None
        Integer :: N, I
        Logical :: R
        R = .True.
        !$OMP PARALLEL DO
        DO I = 2, Floor(Sqrt(N*1.0))
            If(Mod(N, I) == 0) Then
                R = .False.
            EndIf
        EndDo
        !$OMP END PARALLEL DO
        Return
    EndFunction

    Function Permutations(R, nth, Fac) Result(V)
        Implicit None
        Integer, Dimension(N) :: Indices
        Integer, Intent(In) :: R, nth
        Integer, Intent(In) :: Fac
        Integer :: Factorial
        Integer :: V
        Integer :: M
        Integer :: I, J, K

        Indices = 1
        M = nth - 1
        V = 0
        Factorial = Fac

        Do I = 1, R
            J = M / Factorial + 1
            M = Mod(M, Factorial)
            If(N.ne.I) Factorial = Factorial / (N-I)

            ! Find the index
            K = 1
            Do
                If(Indices(K) > 0) J = J - 1
                If(J .eq. 0) Exit
                K = K + 1
            End Do
            Indices(K) = 0

            ! Gen the Number
            V = V*10 + Digits(K)
        EndDo
    EndFunction
End Program euler41

2楼2011-07-14 16:29:24
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
相关版块跳转 我要订阅楼主 holmescn 的主题更新
普通表情 高级回复 (可上传附件)
信息提示
请填处理意见