В чем причина ошибки узла FREESXP в Rcpp? - PullRequest
0 голосов
/ 27 мая 2018

Я использую два пакета R 'tidyverse' и 'Rcpp' для выполнения C ++ -функции внутри 'mutate', используемой для объекта tibble.

Я получаю следующую ошибку:

Error in mutate_impl(.data, dots) : 
  Evaluation error: GC encountered a node (0x112b8d800) with an unknown SEXP type: FREESXP at memory.c:1013. 

Я пытался использовать valgrind, но valgrind выдает ошибку, даже не выполняя, и я почему-то не могу исправить это на своем компьютере.Поэтому я хотел бы спросить, могут ли другие люди получить такую ​​же ошибку и могли бы решить ее.

Вот пример кода, который нужно выполнить:

# load necessary packages
library( tidyverse )
library( Rcpp )

# define C++ function inline
cppFunction( '
             IntegerVector lee_ready_vector( NumericVector & price, NumericVector &bidprice, 
                                NumericVector &askprice ) {
               const int nrows = price.length();
               IntegerVector indicator( nrows );
               if ( nrows < 3 ) {
                 return indicator;
               }
               if ( nrows != bidprice.length() || nrows != askprice.length() ) {
                 throw std::invalid_argument( "Arguments differ in lengths" );
             }

             NumericVector midprice = ( askprice + bidprice ) / 2.0;

             try {
               for( int i = 2; i <= nrows; ++i ) {
                 if ( price[i] == askprice[i] ) {
                   indicator[i] = 1;
                 } else if ( price[i] == bidprice[i] ) {
                   indicator[i] = -1;
                 } else {
                   if ( price[i] > midprice[i] ) {
                     indicator[i] = 1;
                   } else if ( price[i] < midprice[i] ) {
                     indicator[i] = -1;
                   } else { 
                   /* price == midpice */
                       if ( price[i] > price[i-1] ) {
                         indicator[i] = 1;
                       } else if ( price[i] < price[i-1] ) {
                         indicator[i] = -1;
                       } else {
                         if ( price[i] > price[i-2] ) {
                           indicator[i] = 1;
                       } else {
                           indicator[i] = -1;
                       }
                     }
                   }
                 }
               }
             } catch ( std::exception &ex ) {
               forward_exception_to_r( ex );
             } catch (...) {
               ::Rf_error( "c++ exception (unknown reason)" );
             }
             return indicator;
             }')
# define function for random dates inline
latemail <- function( N, st="2012/01/01", et="2012/03/31" ) {
  st <- as.POSIXct( as.Date( st ) )
  et <- as.POSIXct( as.Date( et ) )
  dt <- as.numeric( difftime( et,st,unit="sec" ) )
  ev <- sort(runif( N, 0, dt ) )
  rt <- st + ev
  sort( as.Date( rt ) )
}

# set random seed 
set.seed( 12345 )

# start test loop
# try 100 times to crash the session
# repeat this whole loop several times, if necessary
for ( i in 1:100 ) {
  # 500,000 observation altogether
  N <- 500000
  dates <- latemail( N )
  mid <- sample(seq(from=8.7, to=9.1, by = 0.01), N, TRUE)
  # bid and ask series lay around mid series
  bid <- mid - .1
  ask <- mid + .1
  # p is either equal to bid or ask or lays in the middle
  p <- rep( 0, N )
  for(i in 1:2000) {
    p[i] <- sample( c(mid[i], bid[i], ask[i]), 1 )
  }
  # create the dataset
  df <- tibble( dates, p, bid, ask )

  # execute the C++ function on grouped data
  df %>% group_by( dates ) %>% 
    mutate( ind = lee_ready_vector( p, bid, ask ) ) %>% 
    ungroup()
}  

Кто-нибудь может воспроизвести ошибку.Кто-нибудь может дать решение?

Ответы [ 2 ]

0 голосов
/ 16 июня 2018

Со времени моего последнего поста здесь я опробовал советы, которые Дирк дал выше.Выделение ошибки в некоторые конкретные строки данных оказалось довольно сложным: из-за двойной группировки этого большого набора данных и зависимости строк в алгоритме я потратил много времени на тестирование без какого-либо успеха и все еще многоработы, чтобы сделать.В какой-то момент я обратился к первому совету Дирка, а именно:

Ваш индекс цикла в C ++ равен for( int i = 2; i <= nrows; ++i ), что весьма вероятно неверно.Индексы в C и C ++ изменяются от 0 до n-1, поэтому вы, вероятно, хотите, чтобы for( int i = 1; i < nrows; ++i ) позволял один раз лагать.

Итак, я перекодировал свой цикл так, чтобы он составлял for( int i = 0; i < nrows - 2; ++i ), и скорректировал индексы:переменные внутри цикла соответственно и ошибка исчезла.Таким образом, казалось, что для некоторых строк - когда были достигнуты последние случаи в цикле - произошла ошибка индексации.С этого момента я всегда буду начинать цикл с 0. Хотя конкретные решения не могут быть даны, этот совет мне очень помог.Еще раз спасибо.

К пункту 2: В моем пакете я фактически использую атрибуты, я хотел дать пользователям возможность просто запустить скрипт в консоли.На будущее: что делать с cpp-файлами здесь?Просто публикуете код и имена файлов?

Пункт 3: Это интересный пакет.Я использовал его здесь и там при поиске ошибки с образцами данных, но я не слышал об этом раньше.Спасибо за упоминание этого.

Пункт 4: Я редактировал это выше.Мои извинения.

Относительно 5. Lee & Ready: в науке это по-прежнему наиболее приемлемый алгоритм для определения направления торговли, и поскольку более старая статья использовала этот алгоритм, сравнения с более старой литературой используют тот же алгоритм.Как я знаю, вы работаете в области количественного финансирования в течение очень долгого времени, какую альтернативу вы бы предложили, Дирк?

0 голосов
/ 27 мая 2018

В вашем коде много чего происходит, и этот пример не воспроизводим, что всегда является проблемой.Но давайте начнем где-нибудь:

  1. Ваш индекс цикла в C ++ равен for( int i = 2; i <= nrows; ++i ), что, скорее всего, неправильно.Индексы в C и C ++ изменяются от 0 до n-1, поэтому вы, вероятно, захотите for( int i = 1; i < nrows; ++i ), который позволяет задерживаться один раз.

  2. Использование inline и cppFunction устарело,Вместо этого используйте атрибуты Rcpp.Прочитайте недавнее вступление, такое как вводная виньетка , из нашей недавней статьи TAS .Это также освобождает вас от выполнения try/catch в конце.

  3. Ваше преобразование времени слишком сложное.Просто используйте anytime::anytime() на входе, чтобы получить POSIXct.

  4. Отсутствие отступов не помогает.Я написал бы основную часть в правильном редакторе для C ++ и, возможно, включил бы фрагмент кода R после /*** R или имел бы отдельный файл R.

  5. Lee и Ready - это хорошо, но не все, чтопрогнозирующий.

...