Почему функция Rcpp segfault работает только при вызове из пакета R, а не при прямом источнике через sourceCpp? - PullRequest
3 голосов
/ 19 марта 2019

У меня есть функция C ++, которая работает в R при независимом использовании Rcpp, но когда я включаю ее в скомпилированный пакет R, я получаю следующую ошибку: error: arma::memory::acquire(): out of memory.В этом посте я предоставил код C ++, содержащий функцию Znew_gen2, которую я хочу использовать в моем скомпилированном R-пакете.Используя рабочий пример, я могу показать, что функция Znew_gen2 работает, когда я получаю ее независимо (вне пакета R).Однако когда я вызываю эту же функцию из примера пакета R с именем HelpWithZnewgen2, функция больше не работает, и я получаю ошибку error: arma::memory::acquire(): out of memory.Весь код, упомянутый в этом посте, можно найти в репозитории GitHub https://github.com/hheiling/myrepo_R.

Мой рабочий пример представлен здесь:

# Working Example:

library(bigmemory)
library(Matrix)

set.seed(1)
U = matrix(rnorm(3000), nrow=100, ncol=30)
Z = matrix(rnorm(15000), nrow = 500, ncol = 30)
group = rep(1:10, each = 50)
cols = c(1,11,21)
n = 500
q = 3
d = 10 
Znew = big.matrix(nrow = nrow(Z)*nrow(U), ncol = 6)
J_SpMat = Matrix(0, 9, 6, sparse = TRUE)
  sumy = 0
  sumx = 0
  zeros = 0
  for(i in 1:3){
    J_SpMat[ sumx + zeros + 1:(3 - (i-1)), sumy + 1:(3 - (i-1))] = diag((3 - (i-1)))
    sumy = sumy + (3 - (i-1))
    sumx = sumy
    zeros = zeros + i
  }

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

library(Rcpp)

## Code to download the "Znew_gen2.cpp" file from the GitHub repo and 
## specify where you want the file to download to:
destination_file = "Source_Code_Znew_gen2.cpp" 
  # Can specify however you like, but must not have spaces in the filename
download.file(url = "https://raw.githubusercontent.com/hheiling/myrepo_R/master/Znew_gen2.cpp", 
              destfile = destination_file)
sourceCpp(file = destination_file)

# Calling the sourced `Znew_gen2` function:
Znew_gen2(U, Z, group, cols, n, q, d, Znew@address, J_SpMat)
## Output:

# First For Loop 
# Second For Loop 
# End of Function 

Однако, когда я помещаю эту же функцию Znew_gen2 в пакет R и вызываю эту функцию из пакета R, я получаю сообщение об ошибке: error: arma::memory::acquire(): out of memory.В целях иллюстрации я создал пакет R с именем HelpWithZnewgen2 и вызываю функцию Znew_gen2 Rcpp с помощью функции-оболочки с именем Znew_gen2.Rfunction.

# Instructions to download the `HelpWithZnewgen2` package:
library(devtools)
library(remotes)
install_github("hheiling/myrepo_R", subdir = "HelpWithZnewgen2")

library(HelpWithZnewgen2)

# Calling the function from the compiled package:
Znew_gen2.Rfunction(U, Z, group, cols, n, q, d, Znew@address, J_SpMat)

Получена ошибка:

# error: arma::memory::acquire(): out of memory
# Error in Znew_gen2(U, Z, group, cols, n, q, d, pBigMat, J) : 
#   std::bad_alloc

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

Поскольку сам код работает, когда он получен вне пакета R,Я подозреваю, что моя проблема связана с тем, как настроен мой пакет R.При поиске в Интернете я не удивлюсь, если возникнет проблема с одним или несколькими из следующих компонентов: строки в Znew_gen2.cpp перед строкой «using namespace Rcpp», мой файл описания или, возможно, какая-то строка, которую мне не хватаетв файле Makevars пакета R.Несмотря на мои подозрения (которые могут быть неверными, поскольку я относительно новичок в написании пакетов R), я не смог решить эту проблему.Поэтому я был бы очень признателен за любые предложения о том, как решить эту проблему.

Более подробная информация о коде Znew_gen2 (файл Znew_gen2.cpp, https://github.com/hheiling/myrepo_R/blob/master/Znew_gen2.cpp) и компоненты пакета HelpWithZnewgen2 предоставляются в репозитории Github https://github.com/hheiling/myrepo_R. Поскольку я не являюсьУбедитесь, что, если таковые имеются, эти подробности имеют отношение к ответу на вопрос, они не размещены здесь.

Весь приведенный выше код приведен в файле Stack Overflow Example.R https://github.com/hheiling/myrepo_R/blob/master/Stack%20Overflow%20Example.R.

1 Ответ

2 голосов
/ 24 марта 2019

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

 error: arma::memory::acquire(): out of memory
 Error in Znew_gen2(U, Z, group, cols, n, q, d, Znew@address, J_SpMat) : 
   std::bad_alloc
 Execution halted

Я добавил код, чтобы проверить ваши параметры, и действительно для

 Rcpp::Rcout << "n*nMC is " << n*nMC << ", J.ncols is " << J.n_cols << std::endl;

Понятно

 n*nMC is 50000, J.ncols is 25769803830

поэтому в настоящее время ваша проблема не в объекте bigmemory, а в разреженной матрице.

Отредактируйте немного позже: Оказывается, что проблема, вероятно, ваше использование #define ARMA_64BIT_WORD, что делает размеры матрицы за пределами int и, следовательно, появление этих значений YUGE. Если я удалил это, ваш код запускается.

Итак, урок переучился: делайте задачу все меньше и меньше, здесь это означает, что вы отделите использование разреженной матрицы от использования матрицы bigmemory.

...