Преобразование функции косинусного расстояния в R в Rcpp

#r #matrix #rcpp

#r #матрица #rcpp

Вопрос:

Я разрабатывал пакет R для анализа РНК-последовательности отдельных клеток, и одна из функций, которые я неоднократно использовал, вычисляет матрицу косинусного различия для заданной матрицы из m клеток по n генам. Функция, которую я написал, заключается в следующем:

 CosineDist <- function(input = NULL) {
  if (is.null(input)) { stop("You forgot to provide an input matrix") }
  dist_mat <- as.dist(1 - input %*% t(input) / (sqrt(rowSums(input^2) %*% t(rowSums(input^2)))))
  return(dist_mat)
}
  

Этот код отлично работает для небольших наборов данных, но когда я запускаю его для чего-либо более 20 000 строк, это занимает целую вечность, а затем завершает работу моего сеанса R из-за проблем с памятью. Я считаю, что перенос этого в Rcpp сделал бы это быстрее и эффективнее с точки зрения памяти (я знаю, что это немного наивное убеждение, но мои знания C в целом ограничены). Наконец, выходные данные функции, хотя при возврате они не обязательно должны быть объектом матрицы расстояний, должны иметь возможность преобразования в этот формат после его генерации.

Как мне следует преобразовать эту функцию в Rcpp, а затем вызвать ее так же, как и любую другую функцию в моем пакете? В качестве альтернативы, это лучший способ решить проблему скорости / памяти?

Комментарии:

1. Как это соотносится с существующей функцией cosine() в пакете isa ?

2. Это должна быть простая функция в Rcpp, но ваш вопрос, по сути, «может ли кто-нибудь показать мне, как работает Rcpp, и преобразовать мою функцию в C ?». Это действительно выходит за рамки того, что возможно или по теме о переполнении стека. Гораздо лучше прочитать хороший бесплатный вводный текст Rcpp , который включает в себя главу о матрицах

3. Я не знал об этом пакете или функции, я попробую прямо сейчас.

4. из проверки исходного кода функция косинуса из isa также является чистой реализацией R

5. Кажется, я не могу найти этот isa пакет, хотя есть isa2 пакет, в котором нет функции косинусного расстояния.

Ответ №1:

Трудно вам помочь, поскольку, как указано в комментариях, вы в основном ищете вводную часть Rcpp.

Я попытаюсь дать вам несколько советов, о которых я уже частично упоминал в комментариях.

В целом использование C / C может обеспечить значительное ускорение (в зависимости от задачи, конечно). Но я достиг (интенсивный цикл, не оптимизированный код) 100-кратного ускорения.

Поскольку добавление C может быть сложным и иногда вызывать проблемы, прежде чем идти этим путем, проверьте следующее:

1. Оптимизирован ли ваш R-код?

Здесь вы можете сделать много неправильных решений (например, циклы в R медленные). Часто можно легко достичь ускорения кода R в 10 раз или намного больше, просто оптимизируя его.

2. Есть ли лучшие реализации в других пакетах?

Особенно, если это вспомогательные функции или общие функциональные возможности, часто они уже реализованы в других пакетах. Проведите сравнительный анализ различных существующих решений с помощью пакета «microbenchmark». Проще просто использовать оптимизированную функцию из другого пакета R, а затем делать все самостоятельно. (возможно, другие реализации пакета уже есть на C ). В основном я пытаюсь искать основные и популярные пакеты (поскольку они лучше протестированы и вряд ли внезапно выпадут из CRAN).

3. Профилируйте свой код

Посмотрите, какие части точно вызывают проблемы со скоростью / памятью. Возможно, вы можете сохранить части в R и создать функцию только для критических частей в C . Или вы найдете другой пакет, в котором есть функция R, реализованная на C именно для этой важной части.

В конце я бы сказал, что я предпочитаю использовать Rcpp / C вместо кода на C. Думаю, это самый простой способ. Для части обучения Rcpp вам нужно перейти к специальному руководству (а не к вопросу SO).

Комментарии:

1. Спасибо, я ценю все усилия, которые вы приложили, чтобы помочь мне в этом.