2014-02-05 99 views
0

我是Fortran初級編程人員,仍然在主要學習過程中。 我爲Fortran中的FE Simulation編寫了一個程序。但表現仍然過於緩慢。 因此我首先實現了稀疏矩陣,這很好地加速了代碼。但它還不夠快。 這就是爲什麼我認爲使用openMP和並行化代碼的部分將是非常有用的。 但是,當我試圖實現openMP的命令時,代碼工作速度比以前更慢(我假設開銷太多),或者它不再正確執行。正確使用openMP與Fortran Do Loops

在即將到來的代碼部分之前,有一個do循環用於時間步進。 變量nE相當高,可以說高達50K或更多。這個循環對於每個時間步都是必須要計算的。 它是我想要並行代碼的一部分:

!$omp parallel 
!$omp do private(v, b, N_loc, c, n, vertices, a1, a2, a3, b1, b2, b3, etc...) 
    do v = 1, nE 
    do b = 1, 4 
     N_loc(1,b) = umesh_elt(v,b) !Extracting node numbers 
     c(1,b) = c_s(N_loc(1,b),1) !Extracting values 
     n(1,b) = n_s(N_loc(1,b),1) 
     vertices(b,1) = umesh_co(N_loc(1,b),1) !Extracting coordinates 
     vertices(b,2) = umesh_co(N_loc(1,b),2) !Extracting coordinates 
    end do 



    a1 = 0.25*(-vertices(1,1)+vertices(2,1)+vertices(3,1)-vertices(4,1)) 
    a2 = 0.25*(-vertices(1,1)-vertices(2,1)+vertices(3,1)+vertices(4,1)) 
    a3 = 0.25*(+vertices(1,1)-vertices(2,1)+vertices(3,1)-vertices(4,1)) 
    b1 = 0.25*(-vertices(1,2)+vertices(2,2)+vertices(3,2)-vertices(4,2)) 
    b2 = 0.25*(-vertices(1,2)-vertices(2,2)+vertices(3,2)+vertices(4,2)) 
    b3 = 0.25*(+vertices(1,2)-vertices(2,2)+vertices(3,2)-vertices(4,2)) 


    do j = 1, nGauss 
     J_c(1,1) = a1 + a3*QuadRuleX(j,2) 
     J_c(1,2) = a2 + a3*QuadRuleX(j,1) 
     J_c(2,1) = b1 + b3*QuadRuleX(j,2) 
     J_c(2,2) = b2 + b3*QuadRuleX(j,1) 

     J_det(j,1) = J_c(1,1)*J_c(2,2) - J_c(1,2)*J_c(2,1) 
    end do 

    do k = 1, 4 
     y(k,1) = 0.0 
     do z = 1, nGauss 
      r = QuadRuleX(z,1) 
      t = QuadRuleX(z,2) 

      if (k == 1) then 
      phi = 0.25*(r-1)*(t-1) 
      else if (k == 2) then 
      phi = -0.25*(r+1)*(t-1) 
      else if (k == 3) then 
      phi = 0.25*(r+1)*(t+1) 
      else if (k == 4) then 
      phi = -0.25*(r-1)*(t+1) 
      endif 


      phi_1 = 0.25*(r-1)*(t-1) 
      phi_2 = -0.25*(r+1)*(t-1) 
      phi_3 = 0.25*(r+1)*(t+1) 
      phi_4 = -0.25*(r-1)*(t+1) 


      c_h = c(1,1)*phi_1+c(1,2)*phi_2+c(1,3)*phi_3+c(1,4)*phi_4 
      n_h = n(1,1)*phi_1+n(1,2)*phi_2+n(1,3)*phi_3+n(1,4)*phi_4 
      y(k,1)=(phi*((((hi-1)*c_h+hi)/(2*(hi-1)*c_h+1))*n_h* (2-n_h)-n_h))*J_det(z,1)*QuadRuleW(z,1)+y(k,1) 
     end do 
    end do 

    S(z1,1) = y(1,1)+S(z1,1) 
    S(z2,1) = y(2,1)+S(z2,1) 
    S(z3,1) = y(3,1)+S(z3,1) 
    S(z4,1) = y(4,1)+S(z4,1) 

    end do 

!$omp end do 
!omp end parallel 

此快照的代碼後,有時間步驟結束do循環和一些if從句停止模擬,如果具體的事情已經發生。

我編譯這與選項 ifort -mkl -openmp NAME.f90 當嘗試使用 時間execeute它./a.out 的代碼無法正常工作,程序啓動和停止沒有任何錯誤。

我認爲我基本上做了一些錯誤,就像我沒有正確理解如何正確設置那些使用openMP的循環。有人有任何建議嗎?

我感謝任何幫助,非常感謝! 阿恩

回答

0

這是一個有點太長了評論,所以我會後它作爲一個答案......

這很難說是全球性的,什麼是不整PRIVATE()聲明地方..

乍看之下,只有S(,1) = y(,1)+S(,1)行似乎是至關重要的。你能確保沒有兩個線程同時嘗試訪問相同的S(,1)嗎?從我看到的z1 - z4設置爲外部循環 - 所以我的猜測是他們是相同的所有線程和race condition發生。

如果它們的意思是相同的,這就像是一個reduction操作。作爲一個快速修復(只是爲了調試,除非你真的需要就不要使用它),你可以將代碼塊置於critical部分。

+0

感謝您的留言。這導致我在我的代碼中犯了我的錯誤。我整理了幾天的代碼,並且z的聲明是問題。非常感謝你! – BBQTime