Большие различия в производительности ОС для матричных вычислений
На моих двух компьютерах я попробовал этот код:
N <- 10e3
M <- 2000
X <- matrix(rnorm(N * M), N)
system.time(crossprod(X))
Первый - стандартный ноутбук, и эта операция занимает 1,7 секунды.
> sessionInfo()
R version 3.4.4 (2018-03-15)
Platform: x86_64-redhat-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)
Matrix products: default
BLAS/LAPACK: /usr/lib64/R/lib/libRblas.so
Второй - довольно хороший настольный компьютер, и он занял 17 секунд.
> sessionInfo()
R version 3.4.4 (2018-03-15)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Linux Mint 18.3
Matrix products: default
BLAS: /usr/lib/libblas/libblas.so.3.6.0
LAPACK: /usr/lib/lapack/liblapack.so.3.6.0
Настольный компьютер более производительный, чем ноутбук, но для этого матричного вычисления требуется в 10 раз больше времени.
Проблема исходит от используемого по умолчанию BLAS/LAPACK?
2 ответа
tldr: CentOS использует однопоточный OpenBLAS, Linux Mint по умолчанию использует Reference BLAS, но может использовать другие версии BLAS.
Пакеты R для CentOS, доступные от EPEL, зависят от openblas-Rblas
, Похоже, что это сборка OpenBLAS, предоставляющая BLAS для R. Так что, хотя похоже, что используется BLAS R, на самом деле это OpenBLAS. Версия LAPACK всегда предоставлена R.
На Debian и производных дистрибутивах, таких как Mint, r-base-core
зависит от
- libblas3 | libblas.so.3
- liblapack3 | liblapack.so.3
По умолчанию они предоставляются ссылочными реализациями. libblas3
а также liblapack3
, Это не особенно быстро, но вы можете легко заменить их, установив такие пакеты, как libopenblas-base
, Вы можете контролировать BLAS и LAPACK, используемые в вашей системе, через update-alternatives
,
Для контроля количества потоков с помощью OpenBLAS я обычно использую RhpcBLASctl
:
N <- 20000
M <- 2000
X <- matrix(rnorm(N * M), N)
RhpcBLASctl::blas_set_num_threads(2)
system.time(crossprod(X))
#> User System verstrichen
#> 2.492 0.331 1.339
RhpcBLASctl::blas_set_num_threads(1)
system.time(crossprod(X))
#> User System verstrichen
#> 2.319 0.052 2.316
По какой-то причине установка переменных среды OPENBLAS_NUM_THREADS
, GOTO_NUM_THREADS
или же OMP_NUM_THREADS
от R не дает желаемого эффекта. На CentOS даже RhpcBLASctl
не помогает, так как используемый OpenBLAS является однопоточным.
R распространяется с реализацией BLAS по умолчанию, но он не может быть оптимизирован для вашего компьютера. Внедрение оптимизированных версий BLAS через ATLAS или OpenBLAS до R, как рекомендовано в Руководстве по установке R, - это путь. Если вы нажмете на Download R for Linux
а затем на debian/
, Он сказал, что:
Вы можете установить автоматически настроенный Atlas или многопоточную библиотеку OpenBlas, чтобы повысить производительность операций с линейной алгеброй.
Источник R можно скачать здесь, а реализация BLAS находится в R-3.5.0/src/extra/blas
, Например, исходный код Fortran матричного умножения dgemm
находится в blas.f, вдоль большинства подпрограмм BLAS (в одном файле!).
В комментариях функции указывается:
-- Written on 8-February-1989.
Jack Dongarra, Argonne National Laboratory.
Iain Duff, AERE Harwell.
Jeremy Du Croz, Numerical Algorithms Group Ltd.
Sven Hammarling, Numerical Algorithms Group Ltd.
Те же самые строки можно найти в реализации netlib подпрограммы dgemm.
Напротив, OpenBLAS предоставляет разные реализации, по одной для каждого типа процессоров. Посмотрите, например, этот файл, посвященный dgemm для haswell микроархитектуры. Есть вызовы prefetcht0 для предварительной выборки и вызовы vfmadd231pd, векторной инструкции FMA SIMD, которая выполняет двойную точность d=a*b+c 4 раза за раз.
Использование оптимизированного BLAS может спасти день. Посмотрите, например, этот тест, где dgemm() netlib длится 64 секунды, тогда как dgemm MKL, OpenBLAS или ATLAS занимает менее 4 секунд.
Случай с R внутренним BLAS может быть хуже, чем у классической библиотеки Netlib. Действительно, как указано в приложении A.3.1.5 Shared BLAS
в R Installation and Administration
:
R предлагает вариант компиляции BLAS в динамическую библиотеку libRblas, хранящуюся в R_HOME/lib, и связывание как самого R, так и всех дополнительных пакетов с этой библиотекой..... При использовании совместно используемой BLAS могут возникнуть проблемы с производительностью.... Однако эксперименты показали, что во многих случаях использование общего BLAS было таким же быстрым, при условии использования высоких уровней оптимизации компилятора.
Глядя на файл config.site для R, написано, что уровень оптимизации равен -O2 для g77/gfortran. Поэтому настройка опции FFLAGS может оказаться полезной, если компилятор fortran не является g77/gfortran. На этапе настройки должна быть строка checking whether we are using the GNU Fortran 77 compiler... yes
(строка 7521 файла конфигурации).