Как вызвать model.matrix или эквивалент из RCPP, возможно, в многопоточном коде? - PullRequest
0 голосов
/ 30 апреля 2019

мы надеялись использовать потоки для ускорения процесса в алгоритме со многими циклами, результаты которых не являются взаимозависимыми.

в коде, который мы надеялись перенести в rcpp, есть вызов model.matrix.

Это не выглядело просто для порта.

Дальнейшее изучение этого (в отношении того, какой код выполняется для нашего варианта использования) показало, что метод S3 для объектов lm выполняет некоторую подготовительную работу с переменной, а затем вызывает версию функции по умолчанию, как видно из этой копии. -паста кода:

function (object, ...) 
{
    if (n_match <- match("x", names(object), 0L)) 
        object[[n_match]]
    else {
        data <- model.frame(object, xlev = object$xlevels, ...)
        if (exists(".GenericCallEnv", inherits = FALSE)) 
            NextMethod("model.matrix", data = data, contrasts.arg = object$contrasts)
        else {
            dots <- list(...)
            dots$data <- dots$contrasts.arg <- NULL
            do.call("model.matrix.default", c(list(object = object, 
                data = data, contrasts.arg = object$contrasts), 
                dots))
        }
    }
}

версия по умолчанию для функции превращает по крайней мере некоторые ее функции в скомпилированную функцию C:

function (object, data = environment(object), contrasts.arg = NULL, 
    xlev = NULL, ...) {
    t <- if (missing(data)) 
        terms(object)
    else terms(object, data = data)
    if (is.null(attr(data, "terms"))) 
        data <- model.frame(object, data, xlev = xlev)
    else {
        reorder <- match(vapply(attr(t, "variables"), deparse2, 
            "")[-1L], names(data))
        if (anyNA(reorder)) 
            stop("model frame and formula mismatch in model.matrix()")
        if (!identical(reorder, seq_len(ncol(data)))) 
            data <- data[, reorder, drop = FALSE]
    }
    int <- attr(t, "response")
    if (length(data)) {
        contr.funs <- as.character(getOption("contrasts"))
        namD <- names(data)
        for (i in namD) if (is.character(data[[i]])) 
            data[[i]] <- factor(data[[i]])
        isF <- vapply(data, function(x) is.factor(x) || is.logical(x), 
            NA)
        isF[int] <- FALSE
        isOF <- vapply(data, is.ordered, NA)
        for (nn in namD[isF]) if (is.null(attr(data[[nn]], "contrasts"))) 
            contrasts(data[[nn]]) <- contr.funs[1 + isOF[nn]]
        if (!is.null(contrasts.arg)) {
            if (!is.list(contrasts.arg)) 
                warning("non-list contrasts argument ignored")
            else {
                if (is.null(namC <- names(contrasts.arg))) 
                  stop("'contrasts.arg' argument must be named")
                for (nn in namC) {
                  if (is.na(ni <- match(nn, namD))) 
                    warning(gettextf("variable '%s' is absent, its contrast will be ignored", 
                      nn), domain = NA)
                  else {
                    ca <- contrasts.arg[[nn]]
                    if (is.matrix(ca)) 
                      contrasts(data[[ni]], ncol(ca)) <- ca
                    else contrasts(data[[ni]]) <- contrasts.arg[[nn]]
                  }
                }
            }
        }
    }
    else {
        isF <- FALSE
        data[["x"]] <- raw(nrow(data))
    }
    ans <- .External2(C_modelmatrix, t, data)
    if (any(isF)) 
        attr(ans, "contrasts") <- lapply(data[isF], attr, 
            "contrasts")
    ans
}

существует ли какой-либо способ вызова C_modelmatrix из Rcpp, является ли он одиночным или многопоточным? Есть ли какая-либо библиотека или пакет, которые делают по сути то же самое изнутри Rcpp, поэтому мне не нужно изобретать колесо здесь? Я бы предпочел не полностью повторно реализовывать все, что делает model.matrix, если я могу избежать этого.

поскольку у нас на самом деле нет функционирующего кода, пока еще нет ничего, чтобы показать это.

Соответствующая часть функции, которую мы пытались ускорить, вызывает model.matrix следующим образом: ("model.y is lm", данные являются копиями исходного объекта, возвращаемого model.frame (model.y) )

ymat.t <- model.matrix(terms(model.y), data=pred.data.t)
ymat.c <- model.matrix(terms(model.y), data=pred.data.c)

на самом деле это не вопрос, основанный на результатах, скорее вопрос, основанный на подходе / методах

1 Ответ

0 голосов
/ 01 мая 2019

Вы можете вызвать model.matrix из C ++, но вы не можете сделать это многопоточным способом.

Там также будут накладные расходы, но если вызов функции необходим глубоко в середине вашего кода, это может стоить этого для удобства.

Пример:

// [[Rcpp::export]]
RObject call(RObject x, RObject y){
  Environment env = Environment::global_env();
  Function f = env["model.matrix"];
  RObject res = f(x,y);
  return res;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...