2016-07-15 21 views
0

Ich möchte einige Fortran-Code mit OpenMP-Threads mit einem kritischen Abschnitt benchmarken. Um eine realistische Umgebung zu simulieren, habe ich vor diesem kritischen Abschnitt versucht, etwas zu laden.Code braucht viel mehr Zeit, um mit mehr als 1 Thread fertig zu sein

!Kompileraufruf: gfortran -fopenmp -o minExample.x minExample.f90 

    PROGRAM minExample 
    USE omp_lib 
    IMPLICIT NONE 
    INTEGER      :: n_chars, real_alloced 
    INTEGER      :: nx,ny,nz,ix,iy,iz, idx 
    INTEGER      :: nthreads, lasteinstellung,i 
    INTEGER, PARAMETER    :: dp = kind(1.0d0) 
    REAL (KIND = dp)    :: j 
    CHARACTER(LEN=32)    :: arg 

    nx    = 2 
    ny    = 2 
    nz    = 2 
    lasteinstellung= 10000 
    CALL getarg(1, arg) 
    READ(arg,*) nthreads 
    CALL OMP_SET_NUM_THREADS(nthreads) 
!$omp parallel 
!$omp master 
    nthreads=omp_get_num_threads() 
!$omp end master 
!$omp end parallel 
    WRITE(*,*) "Running OpenMP benchmark on ",nthreads," thread(s)" 

    n_chars = 0 
    idx = 0 
!$omp parallel do default(none) collapse(3) & 
!$omp shared(nx,ny,nz,n_chars) & 
!$omp private(ix,iy,iz, idx) & 
!$omp private(lasteinstellung,j) !& 
    DO iz=-nz,nz 
     DO iy=-ny,ny 
      DO ix=-nx,nx 
!     WRITE(*,*) ix,iy,iz 
      j = 0.0d0 
      DO i=1,lasteinstellung 
       j = j + real(i) 
      END DO 
!$omp critical 
      n_chars = n_chars + 1    
      idx = n_chars      
!$omp end critical 
      END DO 
     END DO 
    END DO 
    END PROGRAM 

ich diesen Code mit gfortran -fopenmp -o test.x test.f90 kompiliert und ausgeführt mit time ./test.x THREAD Ausführen dieses Codes auf die Fadenzahl je ein seltsames Verhalten ergibt (eingestellt mit OMP_SET_NUM_THREADS): Im Vergleich zu einem Gewinde (6 ms), um die Ausführung mit mehr Threads kostet viel mehr Zeit (2 Threads: 16000ms, 4 Threads: 9000ms) auf meinem Multicore-Rechner. Was könnte dieses Verhalten verursachen? Gibt es einen besseren (aber immer noch einfachen) Weg, die Last zu generieren, ohne einige Cache-Effekte oder ähnliche Dinge auszulösen?

Edit: seltsames Verhalten: Wenn ich das Schreiben in den verschachtelten Schleifen habe, beschleunigt die Ausführung dramatisch mit 2 Threads. Wenn es auskommentiert wird, dauert die Ausführung mit 2 oder 3 Threads für immer (Schreiben zeigt eine sehr langsame Inkrementierung von Schleifenvariablen) ... aber nicht mit 1 oder 4 Threads. Ich habe diesen Code auch auf einem anderen Multicore-Rechner ausprobiert. Da dauert es für 1 und 3 Threads für immer, aber nicht für 2 oder 4 Threads.

+3

Willkommen bei StackOverflow. Wenn Sie ein Problem mit einem Code haben, sollten Sie ein minimales, vollständiges und überprüfbares Beispiel http://stackoverflow.com/help/mcve erstellen. Was wir versuchen können, uns selbst zu lenken. –

+0

Hat diese "andere Maschine" Hyperthreading? [Threads, die auf zwei logischen Kernen des gleichen physischen CPU-Kerns ausgeführt werden, können viel schneller kommunizieren als auf separaten physischen Kernen] (http://stackoverflow.com/questions/32979067/what-will-be-used-for-data-exchange -between-threads-ausführen-auf-einem-Kern-wi/32981256). Ich kenne Fortran nicht, also habe ich nicht einmal versucht, den Code zu überfliegen, um zu sehen, ob das Teil der Erklärung sein könnte. –

Antwort

2

Wenn der Code, den Sie anzeigen, wirklich vollständig ist, fehlt die Definition von loadSet im parallelen Abschnitt, in dem es private ist. Es ist undefined und

    DO i=1,loadSet 
        j = j + real(i) 
       END DO 

kann eine beliebige Anzahl von Iterationen dauern.

Wenn der Wert irgendwo zuvor in dem Code definiert ist, den Sie nicht zeigen, möchten Sie wahrscheinlich firstprivate anstelle von private.

+0

Variable wurde definiert. Das Problem war, dass ich es für genauso privat erklärt habe. Vielen Dank! –