Имам следния код на Fortran
DO ir = 1, N
cfac = exp( ci*B ) / dble( degen(ir) )
C(:,:) = C(:,:) + cfac*D(:,:, ir )
ENDDO
Този цикъл отнема 14.00s с gcc -02.
Бих искал да го оптимизирам. Опитах с рутината BLAS, която прави умножение матрица-вектор:
DO ir = 1, N
cfac(ir) = exp( ci*B ) / dble( degen(ir) )
ENDDO
DO j = 1, M
CALL zgemv ('n', M, N, cone, D(j,:,:), M,cfac(:),1,czero, C(j,:), 1 )
ENDDO
Оказа се, че получавам същия резултат, но за ... 17,67 s.
Защо е по-бавен и как мога да подобря кода (без да променям опцията на компилатора)?
Благодаря ти,
Самуил
-fdump-tree-optimized
, ако използвате gfortran. Също така опитайте-fopt-info
, за да разберете какъв вид оптимизации (напр. векторизация) прави компилаторът. Може да искате да опитате -O2, който прави някои цикли по различен начин, може да помогне, но и да навреди. Като цяло съм доста скептичен, ако компилаторът вече го векторизира, няма да има много място за подобрение. - person Vladimir F   schedule 01.10.2015C(:,:)
не се препоръчва и може да обърка оптимизатора, вижте software.intel.com/en-us/blogs/2008/03/31/ - person Vladimir F   schedule 01.10.2015C
и да се отхвърли(:,:)
, което указва секция от масив (целият масив във вашия случай). (Вижте публикацията в блога.) - person Raul Laasner   schedule 01.10.2015-funroll-loops
не е част от-O2
или-O3
на gcc. Той е част от-fprofile-use
. Автоматичната векторизация обикновено се случва само на-O3
. Така че за OP-O3 -march=native -mtune=native -funroll-loops
може да е добър избор. (Оставете-ffast-math
/-Ofast
, ако имате нужда от закръгляване, за да се случи в реда на изходния код и/или да обработвате безкрайностите и NaN по начина, по който източникът би го направил.) - person Peter Cordes   schedule 02.10.2015--param max-unroll-times=2
или 4 groups.google.com/d/msg/comp.lang.fortran/dcGPDgo1-w0/ - person Vladimir F   schedule 02.10.2015