У меня есть следующий код Fortran
DO ir = 1, N
cfac = exp( ci*B ) / dble( degen(ir) )
C(:,:) = C(:,:) + cfac*D(:,:, ir )
ENDDO
Этот цикл занимает 14.00 с 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 с.
Почему это медленнее и как я могу улучшить код (без изменения опции компилятора)?
Спасибо,
Самуэль
-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