Пользование библиотеками C++ в пакете R

Если Ваши значения hardcoded являются просто простыми парами "ключ-значение", необходимо посмотреть java.util. Свойства . Это намного более просто, чем xml, легче использовать, и отупляющим образом тривиальный для реализации.

, Если Вы работаете с Java и данными, Вы храните или получаете от диска, смоделирован как пара значения ключа (который это кажется, что находится в Вашем случае), тогда я действительно не могу вообразить лучшее решение.

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

, Конечно, это обладает огромным преимуществом не требования, чтобы любые сторонние библиотеки использовали.

16
задан Dirk Eddelbuettel 28 December 2014 в 15:26
поделиться

1 ответ

Прежде всего, отказ от ответственности: я постоянно использую Rcpp . Фактически, когда (к тому времени он был переименован из Rcpp) RcppTemplate уже был осиротевшим и без обновлений в течение двух лет, я начал поддерживать его под его первоначальным именем Rcpp (под которым он был добавлен в RQuantLib ). Это было около года назад, и я внес несколько дополнительных изменений, которые вы можете найти задокументированными в журнале изменений.

RcppTemplate совсем недавно вернулся после полных тридцати пяти месяцев без каких-либо обновлений или исправлений. Он содержит интересный новый код, но, похоже, он не имеет обратной совместимости, поэтому я не буду использовать его там, где я уже использовал Rcpp.

Rcppbind не очень активно поддерживался, когда я проверял. У Уита Армстронга также есть пакет шаблонного интерфейса под названием rabstraction .

Inline - это нечто совершенно иное: он упрощает цикл компиляции / компоновки, «встраивая» вашу программу в виде строки символов R, которая затем получает скомпилирован, связан и загружен. Я говорил с Олегом о встроенной поддержке Rcpp, что было бы неплохо.

Swig тоже интересен. Джо Ван проделал отличную работу и обернул всю QuantLib для R. Но когда я в последний раз попробовал ее, она перестала работать из-за некоторых изменений во внутреннем устройстве R. По словам кого-то из команды Swig, Джо все еще может работать над этим. В любом случае цель Swig - большие библиотеки. Этот проект, вероятно, можно было бы возродить, но он не лишен технических проблем.

Также следует упомянуть RInside , который работает с Rcpp и позволяет встраивать R в приложения C ++.

Подводя итог: Rcpp мне подходит, особенно для небольших исследовательских проектов, где вы просто хотите добавить одну или две функции. Основное внимание уделяется простоте использования и позволяет «скрыть» некоторые внутренние компоненты R, с которыми не всегда приятно работать. Я знаю многих других пользователей, которым я помогал то и дело по электронной почте. Так что я бы посоветовал пойти на это.

В моем руководстве «Введение в HPC с R» есть несколько примеров Rcpp, RInside и inline.

Редактировать: Итак, давайте рассмотрим конкретный пример (взятый из слайдов «HPC with R Intro» и заимствованный от Стивена Милборроу, который взял его у Венейблса и Рипли). Задача состоит в том, чтобы перечислить все возможные комбинации определителя матрицы 2x2, содержащей только одиночные цифры в каждой позиции. Это может быть сделано хитроумными векторизованными способами (как мы обсуждаем на слайдах учебника) или грубой силой следующим образом:

#include <Rcpp.h>

RcppExport SEXP dd_rcpp(SEXP v) {
  SEXP  rl = R_NilValue;        // Use this when there is nothing to be returned.
  char* exceptionMesg = NULL;   // msg var in case of error

  try {
    RcppVector<int> vec(v);     // vec parameter viewed as vector of ints
    int n = vec.size(), i = 0;
    if (n != 10000) 
       throw std::length_error("Wrong vector size");
    for (int a = 0; a < 9; a++)
      for (int b = 0; b < 9; b++)
        for (int c = 0; c < 9; c++)
          for (int d = 0; d < 9; d++)
            vec(i++) = a*b - c*d;

    RcppResultSet rs;           // Build result set to be returned as list to R
    rs.add("vec", vec);         // vec as named element with name 'vec'
    rl = rs.getReturnList();    // Get the list to be returned to R.
  } catch(std::exception& ex) {
    exceptionMesg = copyMessageToR(ex.what());
  } catch(...) {
    exceptionMesg = copyMessageToR("unknown reason");
  }

  if (exceptionMesg != NULL) 
     Rf_error(exceptionMesg);

  return rl;
}

Если вы сохраните это, скажем, как dd.rcpp.cpp и получите ] Rcpp установлен, затем просто используйте

PKG_CPPFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'`  \
    PKG_LIBS=`Rscript -e 'Rcpp:::LdFlags()'`  \
    R CMD SHLIB dd.rcpp.cpp

для создания разделяемой библиотеки. Мы используем Rscript (или r ), чтобы спросить Rcpp о его заголовке и расположении библиотеки. После сборки мы можем загрузить и использовать это из R следующим образом:

dyn.load("dd.rcpp.so")

dd.rcpp <- function() {
    x <- integer(10000)
    res <- .Call("dd_rcpp", x)
    tabulate(res$vec)
}

Таким же образом вы можете легко отправлять векторы, матрицы, ... различных типов данных R и C ++. Надеюсь, это немного поможет.

Редактировать 2 (примерно пять + лет спустя):

Итак, этот ответ только что получил положительный голос и, следовательно, поднялся в моей очереди. С тех пор, как я его написал, прошло много времени, и Rcpp стал намного богаче функциями. Поэтому я очень быстро написал это

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::IntegerVector dd2(Rcpp::IntegerVector vec) {
    int n = vec.size(), i = 0;
    if (n != 10000) 
        throw std::length_error("Wrong vector size");
    for (int a = 0; a < 9; a++)
        for (int b = 0; b < 9; b++)
            for (int c = 0; c < 9; c++)
                for (int d = 0; d < 9; d++)
                    vec(i++) = a*b - c*d;
    return vec;
}

/*** R
x <- integer(10000)
tabulate( dd2(x) )
*/

, которое можно использовать следующим образом с кодом в файле /tmp/dd.cpp

R> Rcpp::sourceCpp("/tmp/dd.cpp")    # on from any other file and path

R> x <- integer(10000)

R> tabulate( dd2(x) )
 [1]  87 132 105 155  93 158  91 161  72 104  45 147  41  96
[15]  72 120  36  90  32  87  67  42  26 120  41  36  27  75
[29]  20  62  16  69  19  28  49  45  12  18  11  57  14  48
[43]  10  18   7  12   6  46  23  10   4  10   4   6   3  38
[57]   2   4   2   3   2   2   1  17
R> 

Некоторые из ключевых отличий:

  • более простая сборка: всего sourceCpp () это; даже выполняет тестовый код R в конце
  • полнофункциональный IntegerVector тип
  • оболочка обработки исключений, автоматически добавляемая генератором кода sourceCpp ()
18
ответ дан 30 November 2019 в 22:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: