2016-07-15 2 views
0

Je veux comparer un code Fortran avec des threads OpenMP avec une section critique. Pour simuler un environnement réaliste, j'ai essayé de générer de la charge avant cette section critique.Le code prend beaucoup plus de temps pour terminer avec plus de 1 thread

!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 

Je compilé ce code avec gfortran -fopenmp -o test.x test.f90 et exécuté avec time ./test.x THREAD exécution de ce code donne un comportement étrange en fonction du thread count (ensemble avec OMP_SET_NUM_THREADS): par rapport à un fil (6ms) l'exécution avec plus de fils coûte beaucoup plus de temps (2 threads: 16000ms, 4 threads: 9000ms) sur ma machine multicœur. Ce qui pourrait causer ce problème? Existe-t-il une meilleure façon de générer de la charge (mais toujours facile) sans exécuter certains effets de cache ou des choses connexes? Comportement étrange: si j'ai l'écriture dans les boucles imbriquées, l'exécution accélère considérablement avec 2 threads. Si c'est commenté, l'exécution avec 2 ou 3 threads prend une éternité (l'écriture montre une incrémentation très lente des variables de boucle) ... mais pas avec 1 ou 4 threads. J'ai essayé ce code également sur une autre machine multicœur. Là, il prend pour 1 et 3 fils pour toujours mais pas pour 2 ou 4 fils.

+3

Bienvenue sur StackOverflow. Si vous avez un problème avec un code, vous devez créer un exemple minimal, complet et vérifiable http://stackoverflow.com/help/mcve. Lequel nous pouvons essayer de courir nous-mêmes. –

+0

Est-ce que cette "autre machine" a de l'hyperthreading? [Les threads s'exécutant sur deux cœurs logiques du même noyau de CPU physique peuvent communiquer beaucoup plus rapidement que sur des cœurs physiques séparés] (http://stackoverflow.com/questions/32979067/what-will-be-used-for-data-exchange -entre-threads-sont-exécution-sur-un-core-wi/32981256). Je ne connais pas Fortran, donc je n'ai même pas essayé d'écrémer le code pour voir si cela pouvait faire partie de l'explication. –

Répondre

2

Si le code que vous affichez est vraiment complet, il vous manque la définition de loadSet dans la section parallèle dans laquelle il est private. Il est indéfini et la boucle

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

peut prendre un nombre complètement arbitraire d'itérations.

Si la valeur est définie quelque part avant dans le code que vous ne montrez pas, vous voulez probablement firstprivate au lieu de private.

+0

La variable a été définie. Le problème était, que je l'ai déclaré tout aussi privé. Merci! –