Partage
  • Partager sur Facebook
  • Partager sur Twitter

Temps d'exécution du code parallélisé

temps d'exécution du code parallélisé>celui du code séquentiel (OMP)

    14 juin 2021 à 14:09:14

     Bonjour, 
    Je travaille sur la parallélisation d’un code en utilisant OpenMP avec 3 types de threads et pas 2 comme d’habitude. Je devrais avoir un thread master d’application, un thread master et des threads workers.

    Le thread de gestion des applications gérera le graphique des tâches de l’application (c.-à-d. il indiquera quelles tâches sont prêtes à exécuter et les mettra dans la file d’attente) le thread master lira la file d’attente et dès qu’une tâche est prête, il regardera si un thread worker est disponible pour l’exécuter, et enfin les workers qui accomplissent les tâches assignées par le maître.

    Pour ce faire, j’ai implémenté une sous-routine qui exécute 3 tâches (3 boucles). J’ai aussi un diagramme de séquence à suivre :
    Diagramme de séquence
    subroutine management_3_tasks(tasklist_GRAD,ww,pas,cpt ,nb_element,cpt1,dt,dx,p_element,u_prime,u_prime_moins,u_prime_plus,&
           &taux,grad_x_u,grad_t_u,grad_x_f,grad_t_f,ax_plus,ax_moins,ux_plus,ux_moins,sm,flux,tab0,tab)
        INTEGER ::i,j,k,ff,pas
        INTEGER,intent(inout)::cpt,cpt1,nb_element,ww
        real*8  :: dt,dx
        integer ,allocatable, dimension(:),intent(inout) ::p_element
        REAL*8 ,allocatable, dimension(:),intent(inout) :: u_prime,u_prime_moins, u_prime_plus,taux,grad_x_u,&
             &grad_t_u,grad_t_f,grad_x_f,flux,sm
        real*8,allocatable,dimension(:),intent(inout) :: ax_plus,ax_moins,ux_moins,ux_plus
        REAL*8 ,allocatable, dimension(:,:),intent(inout) ::tab0,tab
        type(tcb)::self
        !OpenMP variables
        integer::num_thread,nthreads
        integer, external :: OMP_GET_THREAD_NUM, OMP_GET_NUM_THREADS    
        type(tcb),dimension(20)::tasklist_GRAD,tasks_ready_master
        !Variables pour gestion des threads 
        integer,allocatable,dimension(:)::threads_list !list containing the numbers of the threads workers 
        integer,dimension(100)::threads_list_all !liste containing the numbers of the threads workers in order according to the tasks 
        integer,dimension(3)::threads_list_part1 ! 3 first tasks 
        !=======================================================================================================================================================
        !$OMP PARALLEL PRIVATE(num_thread) &
        !$OMP SHARED(tasklist_GRAD,threads_list,threads_list_all,tasks_ready_master) &
        !$OMP SHARED(threads_list_part1,nthreads)
    
        num_thread=OMP_GET_THREAD_NUM() ! rank of the thread 
        nthreads=OMP_GET_NUM_THREADS() ! number of threads
    
    
    
        !Thread Application Master (number 1)
        if (num_thread==1) then
           do ff=1,3 ! 3 tâches
              if (associated(tasklist_GRAD(ff)%f_ptr) .eqv. .true. ) then ! Si tâche attribuée 
                 tasks_ready_master(ff) = tasklist_GRAD(ff) ! égalité de pointeurs 
                 tasks_ready_master(ff)%state=STATE_READY
              end if
           end do
        end if
        !$OMP BARRIER
    
        !Thread Master (numero 0)
        if (num_thread==0) then 
    
           allocate(threads_list(nthreads-2)) ! list of the workers 
           do ff=1,nthreads-2 
              threads_list(ff)=ff+1 ! 2,3,..,number of threads-2
           end do
    
    
           do ff=1,3,nthreads-2
              if (tasks_ready_master(ff)%state==STATE_READY) then
                 threads_list_all(ff:ff+nthreads-3)=threads_list(:)
              end if
           end do
           threads_list_part1=threads_list_all(1:3) ! 3 tasks
           deallocate(threads_list)
        end if
    
        !$OMP BARRIER
    
        !Threads workers 
        do ff=1,3 
           if (num_thread==threads_list_part1(ff)) then
              !$OMP TASK
              call tasks_ready_master(ff)%f_ptr(self,ww,pas,cpt ,nb_element,cpt1,dt,dx,p_element,u_prime,u_prime_moins,&
                   &u_prime_plus,taux,grad_x_u,grad_t_u,grad_x_f,grad_t_f,ax_plus,ax_moins,ux_plus,ux_moins,sm,flux,tab0,tab)
              tasks_ready_master(ff)%state=STATE_RUNNING
              !$OMP END TASK
           end if
        end do
        
        !$OMP BARRIER
        !Thread Master (numero 0)
        if (num_thread==0) then
           do ff=1,3 
              if (tasks_ready_master(ff)%state==STATE_RUNNING) then
                 tasklist_GRAD(ff)%state=STATE_RUNNING   
              end if
           end do
        end if
        !$OMP END PARALLEL
      end subroutine management_3_tasks  
    
    Le code entier est ici : https://gitlab-sds.insa-cvl.fr/houeslat/stage_hecese/-/blob/master/OpenMP/hecese_OpenMP.f90. Quand je l’exécute, j’obtiens un temps d’exécution plus grand que celui que j’avais avec le code séquentiel (https://gitlab-sds.insa-cvl.fr/houeslat/stage_hecese/-/blob/master/Sequential/hecese_seq.f90).
    tasklist_GRAD est une liste de pointeurs sur fonction et est définie par : 
    !Tasklists  
      type(tcb),dimension(20)::tasklist_GRAD
    !tasks assignment 
      !GRAD
      tasklist_GRAD(1)%f_ptr => u_prime_1 !0
      tasklist_GRAD(1)%state=STATE_WAITING
      tasklist_GRAD(2)%f_ptr => u_prime_droite_1 !1
      tasklist_GRAD(2)%state=STATE_WAITING 
      tasklist_GRAD(3)%f_ptr => u_prime_gauche_1 !2
      tasklist_GRAD(3)%state=STATE_WAITING 
    
    chaque case de cette liste pointe sur une procédure. 
    type:: tcb !task control block 
         procedure(my_interface),NOPASS,pointer:: f_ptr => null() !the function pointer
         integer :: state     !the task state
      end type tcb
    Je voudrais savoir pourquoi le temps d’exécution du code parallélisé (4 threads) est supérieur à celui du code séquentiel (1 thread). J’ai aussi des valeurs étranges comme si les calculs étaient faits plusieurs fois.
    Je ne peux pas poster le code entier qui est calme longtemps c’est pourquoi je vous ai donné le lien vers mon git. Vous pouvez trouver à la fois le code séquentiel et le code parallèle.
    C'est la première fois que je poste une question sur ce forum. Excusez-moi si ma question n'est pas bien formulée. 

    -
    Edité par HakimOueslati1 14 juin 2021 à 14:13:21

    • Partager sur Facebook
    • Partager sur Twitter
      14 juin 2021 à 15:49:10

      Salut,

      avant d'essayer de trouver une solution, pourrais-tu nous dire ce que tu entends pas "plus long" ? Quelle est la durée d'exécution séquentielle, et quelle est la durée d'exécution parallèle ? Quelles routines utilises-tu pour mesurer le temps d'exécution ? (cette dernière question à plus d'importance qu'on ne le crois ...).

      • Partager sur Facebook
      • Partager sur Twitter

      Avez-vous entendu parler de Julia ? Laissez-vous tenter ...

        14 juin 2021 à 15:56:04

        Nozio a écrit:

        Salut,

        avant d'essayer de trouver une solution, pourrais-tu nous dire ce que tu entends pas "plus long" ? Quelle est la durée d'exécution séquentielle, et quelle est la durée d'exécution parallèle ? Quelles routines utilises-tu pour mesurer le temps d'exécution ? (cette dernière question à plus d'importance qu'on ne le crois ...).


        Salut, 

        En ce qui concerne le temps d'exécution du code séquentiel, j'obtiens 20 secondes. Pour le code parallélisé, le temps est estimé à 80 secondes voire 100 secondes. Pour le code séquentiel, j'ai utilisé CPU_TIME et system_clock. Pour le code parallélisé, j'ai utilisé omp_get_wtime. 

        • Partager sur Facebook
        • Partager sur Twitter
          15 juin 2021 à 16:27:53

          J'ai peut-être une idée : lorsqu'on utilise des tâches, il faut les lancer à partir d'un seul thread. Comme tu as pu le remarquer, une région parallèle (qui ici correspond au corps de ta routine) est exécuté par tous les threads en même temps (d'où le fait que tu testes ton numéro de thread). En particulier, tes tâches parallèles sont toutes lancées autant de fois que tu as des threads. Par exemple, si tu as 3 tâches parallèles et 4 threads, tu en lances 3x4=12 alors que tu ne voudrais en lancer que 3 (du coup tu refais le calcul pour rien). Je pense qu'il faut encadrer la zone de code où tu lances tes tâches par un environnement

          !$OMP SINGLE
          ...
          !$OMP END SINGLE
          

          qui indique que la portion de code que tu vas exécuter ne dois l'être qu'à partir d'un seul thread (mais qui ne sera pas forcément le 0 ou le 1). Peut-être suffit-il simplement de re-tester le numéro de thread sur lequel tu es.

          • Partager sur Facebook
          • Partager sur Twitter

          Avez-vous entendu parler de Julia ? Laissez-vous tenter ...

          Temps d'exécution du code parallélisé

          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
          • Editeur
          • Markdown