Есть ли способ увеличить скорость работы с массивами в Фортране под Windows, например Python numpy? - PullRequest
3 голосов
/ 08 апреля 2020

Извините за возможное дублирование. О проблеме. numpy (1.18.2) в python 3.8.2 дает мне очень высокую скорость моделирования (в 3 раза быстрее) для матричного продукта по сравнению с GNU Fortran (9.2.0 MinGW.org G CC Build-20200227- 1) под Windows. Я использовал команду gfortran.exe test.f без каких-либо дополнительных опций.

Кто-нибудь знает, что вызывает это, и возможно ли увеличить скорость симуляции в Фортране?

Вот код Фортрана:

program product_test
    INTEGER :: N,N_count,i,j,k,nc
    REAL*8 :: t1,t2
    REAL*8,dimension (:,:), allocatable :: a,b,c

    N = 200
    N_count = 10

    allocate ( a(N,N) )
    allocate ( b(N,N) )
    allocate ( c(N,N) ) 

    call RANDOM_NUMBER(a)
    call RANDOM_NUMBER(b)

    print *, 'Matrix Multiplication: C = A * B for size (',N,',',N,')'
    call CPU_TIME ( time_begin )
    do nc=1,N_count
        c = MATMUL(a,b)
    end do
    call CPU_TIME ( time_end )
    t2 = (time_end - time_begin)/N_count
    print *, 'Time of operation was ', t2, ' seconds'

end

Вот вывод:

Умножение матрицы: C = A * B для размера (200, 200)
Время работы было 9.3749 E-003 секунд

Вот код python 3:

import numpy as np
import time

N = 200
N_count = 10

a = np.random.rand(N,N)
b = np.random.rand(N,N)
c = np.zeros([N,N], dtype = float)


print('Matrix product in python (using numpy): c= a*b for size (',N,',',N,')')
start_time = time.time()
for nc in range(N_count):
    c = a@b
t2 = (time.time() - start_time)/N_count
print('Elapsed time = ',t2,'s')

Вот результат:

Матричный продукт в python (с использованием numpy): c = a * b для размера (200, 200)
Истекшее время = 0,0031252 s

I извините Чтобы избежать недоразумений, я удалил ту часть кода, которая не была посвящена моему вопросу.


Дополнительные тесты. после комментариев "roygvib" и " Владимир Ф ", я сделал тест с блас / лапак:

gfortran test.f -lopenblas -o test.exe или gfortran test.f -ffast-math -o test.exe или gfortran test.f -lblas -o test.exe или gfortran test.f -llapack -o test.exe дайте мне время расчета 0,0063 с для матричное умножение квадратных матриц с размером (200 x 200).

К сожалению, я удалил предыдущую версию mingw, и были выполнены новые тесты под GNU Fortran (x86_64-posix-seh-rev0, созданный MinGW -W64 проект 8.1.0). Может быть, я сделал что-то неправильно, потому что нет никакой разницы между -llapack, -lblas, -lopenblas. Для измерения времени я использовал SYSTEM_CLOCK, как предложил «Владимир Ф.».

Теперь это лучше, но numpy все же быстрее, чем фортран (не три раза, а два раза). Следуя последнему комментарию «Владимир Ф», я обнаружил, что в отличие от Python, Fortran использует в основном одно логическое ядро ​​(на моем P C есть 4 логических ядра с процессором Intel i3). Таким образом, это проблема неправильно настроенного MinGW на моем P C (Windows8.1).

enter image description here

Ответы [ 2 ]

4 голосов
/ 08 апреля 2020

Используйте MATMUL или внешние библиотеки, такие как BLAS для умножения матриц в Fortran. У нас много вопросов, касающихся производительности умножения матриц

Fortran Производительность умножения матриц при различной оптимизации
производительность операций матрицы Фортрана
Как BLAS получает такие экстремальные характеристики?

Вы должны прочитать их первый. Вы никогда не должны делать матричное умножение наивно для l oop, это всегда будет медленным. Существуют специальные алгоритмы умножения матриц. Они эффективно используют пропускную способность памяти, а также используют векторизованные инструкции (часто написанные непосредственно в сборке).


Многие компиляторы Fortran позволяют вам вызывать BLAS xGEMM напрямую через MATMUL. В гфортране это возможно с -fexternal-blas, упомянутым ройгвибом. Если у вас возникли проблемы, вызовите DGEMM напрямую.

Некоторые реализации BLAS могут использовать несколько потоков. Если вы пытаетесь, чтобы вы не не использовали CPU_TIME для измерения скорости, вы должны использовать SYSTEM_CLOCK или альтернативу.


Кроме того, вы не сообщили об использовании каких-либо флагов оптимизации, таких как -O3. Они необходимы для любой достойной производительности, если только не оптимизированная внешняя библиотека выполняет всю работу.

0 голосов
/ 20 апреля 2020

Проблема была возможно в совместимости разных версий. Я обновил компилятор и библиотеки (я обновил до g cc 9.3.0, openblas 0.3.9 после удаления всех предыдущих версий).

Теперь следующие результаты для матричного продукта: c = a * b с размером матрицы (2000x2000) (с усреднением 20 испытаний) более адекватны (я провел тест на P C с Intel i5 (4 логических ядра) в Windows 10):

  1. 0,237833s (minGW64) и 0,236853s (cygwin64). C ++ с броненосцем с использованием g cc 9.3.0 + openblas 0.3.9
  2. 0.2492s (minGW64) и 0.2479 (cygwin64), норма = 0. Фортран (matmul) с флагом -fexternal-blas, командная строка: gfortran FILE_NAME.f95 -o FILE_NAME -O3 -ffast-math -fexternal-blas "[pathto]\libopenblas_v0.3.9-gcc_9_3_0.a" (g cc 9.3.0, openblas 0.3.9)
    0.2484s (dgemm), тогда как 1.12894s для matmul, норма = 1.5695E-10. Fortran в minGW64 с флагом -lopenblas, командная строка: gfortran FILE_NAME.f95 -o FILE_NAME -O3 -ffast-math lopenblas (g cc 9.3.0)
  3. 0.2562533s , норма = 0.0. python (numpy)
  4. 0,285133 с (R2016a) и 0,269926 с (R2020a), норма = 8,4623e-12. Matlab 64.
  5. 0.3133 с , норма = 1.5695E-10. Fortran (matmul) в minGW64 / cygwin64 с флагом -lblas, командная строка: gfortran FILE_NAME.f95 -o FILE_NAME -O3 -ffast-math -lblas (g cc 9.3.0, в cygwin64).

Чтобы запустить эти тесты, я использовал cygwin (или minGW) для компиляции кода c ++, используя armadillo ( OpenMP C ++ Matrix Multiplication работает медленнее параллельно ), где три матрицы A , B, C были созданы и сохранены на диск для использования тех же матриц в этих тестах. Таким образом, «норма» указывает на относительную точность матричного произведения. Я обнаружил, что numpy использует openblas (libopenblas.PYQHXLVVQ7VESDPUVUADXEVJOBGHJPAY.gfortran-win_amd64). Matlab на моем P C дает мне следующую информацию о библиотеке blas / lapack: Intel (R) Math Kernel Library version 11.2.3 Build 20150413 for applications with Intel (R) 64 architecture, CNR AVX2 branch в R2016a и Intel(R) Math Kernel Library Version 2019.0.3 Product Build 20190125 for Intel(R) 64 architecture applications, CNR branch AVX2 в R2020a.

Скорость симуляции Fortran теперь резонирует с другими языками. И openBLAS победил в C ++ (возможно, благодаря его адаптации для C). Отмечая, что matlab показывает относительно высокую скорость вычислений при не полностью используемых процессорах . Все языки / программы используют все 4 ядра моей системы:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...