Можно ли сделать Rcpp::wrap без копирования для очень большого std::vector

У меня есть функция Rcpp, которая читает большой файл BAM (1-20 ГБ, используя htslib) и создает несколько очень длинных (до 80M элементов). Перед чтением количество элементов неизвестно, поэтому я не могу использовать Rcpp::IntegerVector а также Rcpp::CharacterVector. Насколько я понимаю, когда я Rcpp::wrapих для дальнейшего использования создается копия. Есть ли способ ускорить передачу данных из C ++ в R в этой ситуации? Есть ли структура данных, которую можно создать в функции Rcpp, как можно быстрее push_back элементы как std::vector есть, и передается по ссылке на R?

На всякий случай вот как я их сейчас создаю:

      std::vector<std::string> seq, xm;
std::vector<int> rname, strand, start;

А вот как я их заворачиваю и возвращаю:

      Rcpp::IntegerVector w_rname = Rcpp::wrap(rname);
w_rname.attr("class") = "factor";
w_rname.attr("levels") = chromosomes;  // chromosomes contain names of the reference sequences from BAM

Rcpp::IntegerVector w_strand = Rcpp::wrap(strand);
w_strand.attr("class") = "factor";
w_strand.attr("levels") = strands;  // std::vector<std::string> strands = {"+", "-"};
      
Rcpp::DataFrame res = Rcpp::DataFrame::create(
  Rcpp::Named("rname") = w_rname,
  Rcpp::Named("strand") = w_strand,
  Rcpp::Named("start") = start,
  Rcpp::Named("seq") = seq,
  Rcpp::Named("XM") = xm
);
      
return(res);

1 ответ

Мы используем из-за его надежной реализации в сочетании с отличной производительностью (поскольку обычно трудно увидеть победить в любом сравнении). Но он использует свой собственный распределитель для памяти, хранящейся вне R.

возвращает в R объекты, которые неотличимы от объектов, созданных R, поскольку они используют собственную структуру данных R и для этого требуется одна окончательная копия в память, используемую, принадлежащую и выделенную R. Нет никакого способа обойти это с текущим интерфейсом, если вы хотите вернуть все элементы в R.

В R теперь есть ALTREP, позволяющий альтернативное / внешнее представление, чтобы вы могли придумать что-то другое, но на самом деле это несколько сложно, поскольку API для ALTREP все еще несколько неполный и меняется. Некоторые пакеты были созданы с использованием ALTREP, но сейчас мне в голову не приходит ни один конкретный вариант использования.

Изменить: для ваших строковых векторов вы можете (и должны) попробовать пакет stringfish от Travers. Он использует ALTREP для строк, что может быть большим препятствием для производительности. Для вектор у меня нет альтернативы но, может быть, последний это также не так болезненно (в отличие от строк, которые обрабатываются по-разному внутри, что делает их более дорогими).

Другие вопросы по тегам