Как создать вектор RAWSXP из C char* ptr без перераспределения
Есть ли способ создать вектор RAWSXP, который поддерживается существующим C char* ptr.
Ниже я показываю свою текущую рабочую версию, которая требует перераспределения и копирования байтов, и вторую воображаемую версию, которой не существует.
// My current slow solution that uses lots of memory
SEXP getData() {
// has size, and data
Response resp = expensive_call();
//COPY OVER BYTE BY BYTE
SEXP respVec = Rf_allocVector(RAWSXP, resp.size);
Rbyte* ptr = RAW(respVec);
memcpy(ptr, resp.msg, resp.size);
// free the memory
free(resp.data);
return respVec;
}
// My imagined solution
SEXP getDataFast() {
// has size, and data
Response resp = expensive_call();
// reuse the ptr
SEXP respVec = Rf_allocVectorViaPtr(RAWSXP, resp.data, resp.size);
return respVec;
}
я тоже заметил
Rf_allocVector3
который, кажется, дает контроль над распределением памяти вектора, но я не мог заставить это работать. Это мой первый раз, когда я пишу расширение R, поэтому я думаю, что делаю что-то глупое. Я пытаюсь избежать копирования, так как данные будут около ГБ (очень большие, но разреженные матрицы).
1 ответ
Копирование более 1 ГБ занимает < 1 секунды. Если ваш звонок стоит дорого, это может быть предельная стоимость, которую вы должны профилировать, чтобы увидеть, действительно ли это узкое место.
Способ, которым вы пытаетесь что-то сделать, вероятно, невозможен, потому что откуда R узнает, как собирать данные мусором?
Но предполагая, что вы используете контейнеры STL, один изящный трюк, который я недавно видел , заключается в использовании второго аргумента шаблона контейнеров STL — распределителя.
template<
class T,
class Allocator = std::allocator<T>
> class vector;
Общий план стратегии таков:
- Создайте собственный распределитель с использованием R-памяти, отвечающий всем требованиям (по сути, вам просто нужно
allocate
иdeallocate
) - Каждый раз, когда вам нужно вернуть данные в R из контейнера STL, убедитесь, что вы инициализируете его с помощью своего собственного распределителя.
- При возврате данных извлеките базовые данные R, созданные вашим распределителем R-памяти — без копирования.
Этот подход дает вам всю гибкость контейнеров STL, используя только память, о которой знает R.