Использует ли RR SIMD при выполнении векторизованных вычислений?

Для такого кадра данных в R:

+---+---+
| X | Y |
+---+---+
| 1 | 2 |
| 2 | 4 |
| 4 | 5 |
+---+---+

Если на этом фрейме данных выполняется векторная операция, например:

data$Z <- data$X * data$Y

Будет ли это использовать возможности процессора с одной инструкцией и несколькими данными (SIMD) для оптимизации производительности? Это кажется идеальным для этого, но я не могу найти ничего, что подтверждает мою догадку.

Ответ 1

В качестве короткого ответа вам необходимо проверить, в какой библиотеке BLAS связан ваш R.

  • Если он связан с ссылкой BLAS, то, конечно, нет ответа;
  • Если он связан с оптимизированным BLAS, ответ, возможно, да. Я использовал "возможно", потому что пример операции, которую вы даете: element wise product, не сопоставляется с процедурой BLAS. Он может быть просто закодирован как простой цикл C.

Однако, я считаю, что когда вы ссылаетесь на SIMD, вы имеете в виду более общее использование векторизации SIMD в R. Итак, давайте сначала немного узнаем о реализации SIMD, а затем переходим к R.

SIMD

В моих ограниченных знаниях есть только пять способов реализации SIMD (и у меня есть только практический опыт в первых двух):

  • запись непосредственно архитектуры; Например, на архитектурах x86 мы можем использовать инструкции SSE/AVX;
  • с использованием специфических для архитектуры векторных свойств; например, на архитектурах intel x86, мы можем использовать intel SSE/AVX intrinsics; Это более простой вариант, чем сборка, потому что внутренними являются макросы C, поэтому программисты все еще кодируют в среде C;
  • с помощью векторных расширений для компилятора. Некоторые компиляторы будут определять свой собственный векторный тип данных, например, векторные расширения GCC можно найти здесь. Использование определенных векторных типов компилятора имеет одно потенциальное преимущество: вам не нужно беспокоиться о проблемах архитектуры. Компилятор скомпилирует ваш векторный код в совместимую сборку на этом компьютере;
  • с помощью автоматической прорисовки для компилятора. Например, для GCC мы можем попробовать флаг -ftree-vectorize;
  • используя OpenMP pragma: #pragma opm simd.

В заключение

  • вариант 1 требует записи значительного количества кода сборки;
  • вариант 2 и вариант 3 требуют некоторой перекодировки вашего скалярного кода C, путем ручного разворачивания цикла и векторизации вручную;
  • вариант 3 и вариант 4 не требуют изменения вашего скалярного кода на C; вы просто добавляете флаг компиляции или вставляете какую-то прагму компилятора.

Опции 1-3 обычно не переносятся: вам нужно изменить свой код при использовании другой архитектуры или другого компилятора. Опции 4-5 могут быть наименее ограниченными, но, как уже можно было предположить, они часто не дают оптимальной производительности по сравнению с вариантами 1-3, поскольку они полностью зависят от возможностей компилятора для векторизации.

Основная библиотека R: libR

Примитивные/внутренние функции (.Primitive(), .Internal()) в R, скомпилированы в эту библиотеку. Фундаментальные пакеты R, такие как base, stats, utils, связаны с этой библиотекой. Эта библиотека должна быть загружена при вызове R. Теперь, поскольку R необходимо достичь переносимости на разных архитектурах, ядро ​​R/ядро ​​должно быть написано простым, переносимым C-кодом. В результате сам libR не содержит SIMD, предлагаемого опциями 1-3.

У него также нет опции 4. R не имеет встроенного флага SIMD. У меня есть проверка на RHOME/etc/Makeconf (я использую linux, поэтому не уверен, что он называется файлом конфигурации make в окнах), то вы увидите, что для SIMD-управления нет доступного флага компиляции.

Вариант 5 интересен. R имеет флаг OpenMP, но я убежден, что ядро ​​R не использует какой-либо parallelism, включая SIMD. Я говорю "интересно", потому что сам не уверен, что этот флаг OpenMP позволяет писателям R писать код параллельного кода SIMD. Если кто-нибудь поможет мне прояснить этот момент, я буду очень благодарен.

Поддержка SIMD от libR не подразумевает поддержки SIMD для R. Позвольте проверить библиотеку BLAS.

Библиотека BLAS

Загрузка только libR недостаточна для выполнения R. Многие символы/функции в libR являются внешними: т.е. они используются в libR, но не определены в libR. R называет их интерфейсом иностранного языка. Важным набором таких символов является BLAS (основные подпрограммы линейной алгебры). Процедуры BLAS уровня 1-3 выполняют соответственно:

  • векторно-векторные операции (например, точечный продукт);
  • операции с матричным вектором (например, умножение матричного вектора);
  • операции матричной матрицы (например, матричное умножение и кросс-произведение)

и они лежат в центре научных вычислений. Например, оператор/функция R %*% для матричного умножения, наконец, будет ссылаться на символ _dgemm в libR. Хотя он не определен в libR, libR связан с какой-либо библиотекой BLAS, где он определен. Когда загружается libR, эта библиотека BLAS также загружается.

Разделение библиотеки libR и BLAS, хотя по многим причинам приведено в R установка и администрирование - общий BLAS, подразумевается:

libR лежит на уровне приложения и переносится, в то время как BLAS лежит на уровне вычислений и может быть настроен на архитектуру, что позволяет нам улучшить производительность R без восстановления R.

Существует два типа BLAS: эталонный BLAS и оптимизированный BLAS.

  • Ссылка BLAS ничего особенного. Он закодирован в тривиальном гнезде цикла в F77; их легко перекодировать на C без потери производительности. Он статический, не развивающийся. Его название "ссылка" исходит из стандартного дизайна. Например, стандартным стандартом для матрично-матричного умножения является операция dgemm: C <- beta * C + alpha * op(A) * op(B).
  • Оптимизированный BLAS постоянно развивается , ориентируясь на высокопроизводительные вычисления на различных основных архитектурах. Его дизайн очень сложный, с большим количеством рукописной сборки, предназначенной для разных архитектур. Оптимизированные библиотеки BLAS, либо ATLAS, OpenBLAS, либо Intel MKL кодируются с помощью оптимизации кеширования и векторизации SIMD, поэтому их вычисление может быть намного быстрее, чем использование ссылочного BLAS.

Загрузка BLAS в R

Когда R запущен, он будет искать несколько путей библиотеки для доступной библиотеки BLAS. Здесь есть принцип "первым пришел, первым служит".

  • Верхний приоритет libRblas в каталоге RHOME/lib. Это также каталог, где libR. Если этот libRblas существует, это означает, что при времени установки R он не обнаружил доступную библиотеку BLAS на машине, поэтому он создал свою собственную копию. Обычно эта копия является ссылкой BLAS. Тем не менее, мне недавно сказали, что на Mac (извините, я не использую Mac), двоичная версия R строит другую версию, используя OSX vecLIB BLAS. Этот R для Mac часто задает вопрос. Но по умолчанию R не привязан к этой оптимизированной версии; в FAQ дается подробная информация о том, как сделать псевдоним для загрузки оптимизированной библиотеки BLAS.
  • Теперь, если libRblas не существует, то это означает, что существующая библиотека BLAS была обнаружена в момент времени R, и R был автоматически связан с ней. Теперь это будет более тонким в этом случае. Мы должны сначала проверить, с какой библиотекой BLAS R связаны с: R CMD config BLAS_LIBS. На моем ноутбуке (работает ubuntu 14.04.3) я получаю -lblas. Это означает, что он связан с libblas, эталонным BLAS (единственным BLAS, который у меня был, когда я установил R). Теперь, если мы хотим связать R с другой версией BLAS, скажем OpenBLAS, мы должны сделать псевдоним libblas. Обратите внимание, что если есть несколько версий BLAS при времени установки R, к которым BLAS R будет ссылаться, возможно, менее предсказуем. В некоторых ситуациях на некоторых платформах Intel R может быть привязан к эталонному BLAS, даже если есть существующий Intel MKL. Это можно проверить, используя приведенный выше R CMD config BLAS_LIBS.

В приведенном выше документе я подробно рассказал о том, как BLAS находится по R, и как мы можем загружать в R с разницей BLAS путем сглаживания. Но настройка псевдонимов библиотек требует доступа root/Administrative. Недавно у меня была запись: без root-доступа: как запустить R с Tunded BLAS, когда R связано со ссылкой BLAS, которая предлагает некоторые решения на платформе Linux.

Ответ 2

Ну, мало известна дистрибуция R от Microsoft (художник, ранее известный как Revolution R), который можно найти здесь

Он поставляется с библиотекой Intel MKL, которая также использует несколько потоков и векторных операций (вам нужно запустить процессор Intel), и это действительно помогает с матрицами, такими как SVD и т.д.

Если вы не хотите писать код C/С++ с помощью встроенных SIMD-приложений, используя Rcpp или аналогичные интерфейсы, Microsoft R - лучший способ использовать SIMD

Загрузите и попробуйте