2017-06-10 3 views
1

J'essaie d'optimiser du code Fortran dont j'ai hérité. C'est un code très répétitif qui prend des jours à courir et j'essaie de réduire le temps d'exécution. Après avoir réduit le temps d'exécution de certaines fonctions et sous-routines, le dernier goulot d'étranglement, selon VTune Amplifier, est for_deallocation et for_allocation, spécifiquement appelé depuis un sous-programme. Je ne suis pas très sûr de ce que signifie «for_» devant l'allocation et la désallocation, d'autant plus qu'aucune allocation n'est faite dans la routine. Un résumé du code est le suivant:Pourquoi Fortran passe-t-il autant de temps sur 'for_allocate' ou 'for_deallocate'?

module global_variables 
    double precision, allocatable :: input_values(:) 
    double precision, allocatable :: input_values2(:,:) 
    double precision, allocatable :: indices_array(:) 
    double precision, allocatable :: value_array(:) 
    double precision, allocatable :: final_result(:) 
end module 

subroutine func1() 
    allocate(...global values...) 
    do I=1,n 
     call func2(I) 
    end do 

end subroutine func1 

subroutine func2(I) 
    double precision, intent(in) :: I 
    double precision :: value, x 
    double precision, dimension(3) :: output_array 

    call find_Indices(x) 
    value_array = input_values(indices_array) 
    call calculations(value) 

    do j = 1,3 
     value_array = input_values2(indices_array,j) 
     call calculations(output_array(j)) 
    end do 

    final_result = output_array * value 

end subroutine func2 

subroutine find_Indices(position) 
    indices_array = some calculation on position 
end subroutine find_Indices 

subroutine calculations(output) 
    double precision :: output 
    output = some calculation on value_array 
end subroutine calculations 

je devais résumer plutôt que de coller le code réel en raison de sa nature. Le sous-programme avec le temps d'allocation/désallocation excessif est func2. Il n'y a pas d'instructions d'allocation dans le sous-programme et il n'y a pas de réaffectation des valeurs globales. À l'aide de la documentation à ma disposition, j'ai été incapable de déterminer ce que l'on entend par 'for_' devant allocate/deallocate ou par la raison pour laquelle on y consacre autant de temps dans func2. En raison de la taille du code que j'ai spécifié en plaçant tous les tableaux sur le tas, ce qui rendrait compte d'une allocation, cependant, permettre aux tableaux de revenir sur la pile n'a pas du tout réduit l'heure.

Quelqu'un peut-il m'aider à comprendre la nature de for_allocate/for_deallocate? Ou la raison pour laquelle cette fonction passerait autant de temps à l'appeler?

SOLUTION:

Bien que googler propriétés tableau, pour une autre question que je faisais, je suis tombé sur ce poste: Fortran: dynamic arrays vs. automatic array Avoiding Memory Allocation

Ce qui montre qu'il ya une surcharge significative avec la modification des réseaux mondiaux affectables. Changer value_array d'un tableau allouable en un tableau de pointeurs (double precicsion, pointer :: value_array (:)) a enlevé la plus grande partie de l'overhead de for_allocate et for_deallocate et réduit l'exécution à 1/5ème de ce qu'elle était. Cela me suggère que lorsque les valeurs d'un tableau allocatable sont modifiées, le tableau d'origine est désalloué et un nouveau est alloué. Cela est peut-être bien connu dans la communauté Fortran, mais en tant que nouvel utilisateur, qui n'a pas rencontré de forme de documentation de ce comportement, ce n'était pas évident pour moi.

+0

Nous avons besoin de contexte. Un sous-programme compilable, au moins (mieux serait un petit programme), et le compilateur que vous utilisez. – Jack

+1

En l'absence de meilleures informations, on peut supposer que vous avez besoin d'informations ou de telles optimisations pour préserver les tableaux dynamiques sur plusieurs appels à func2, ainsi que d'essayer éventuellement pile vs heap. output_array semble le plus susceptible d'être déplacé en tas avec une allocation coûteuse. for_ fait simplement référence à la bibliothèque d'exécution de Fortran. – tim18

+0

J'utilise le compilateur Intel 17.0. Je verrai ce que je peux faire pour créer un exemple compilable. J'aurais dû me rendre compte que 'for_' signifierait Fortran, j'ai juste eu l'impression qu'Intel utilisait 'fort' comme l'abréviation de Fortran. –

Répondre

0

Commander les exemples « 6. Accès indirect Array » à https://software.intel.com/en-us/articles/fortran-array-data-and-arguments-and-vectorization

Les allocations répétées sont (très probablement) parce que lors de l'utilisation d'un tableau d'index, le compilateur alloue un tableau temporaire (exemple 7.1 dans le lien ci-dessus) pour stocker le tableau résultant. L'alternative consiste à faire une boucle explicite sur les indices (exemple 7.2).

Le lien ci-dessus concerne les architectures MIC mais le principe est probablement le même sur une CPU normale. Le fil ici https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/685221 fait également allusion à la création de tableaux temporaires pour l'indexation de tableau. Pour être certain de ce qui se passe, il est possible d'inspecter la sortie de l'assemblage ou de tester explicitement le scénario «indexation explicite».