web-dev-qa-db-fra.com

Erreur de désérialisation (liste de chaussettes [[n]]): erreur de lecture de la connexion sous Unix

J'ai essayé d'exécuter le code suivant sur une machine Unix avec 20 CPU, en utilisant les packages R foreach, parallel, doParallel et party (mon objectif est pour que la fonction party/varimp fonctionne sur plusieurs CPU en parallèle):

parallel_compute_varimp <- function (object, mincriterion = 0, conditional = FALSE, threshold = 0.2, 
    nperm = 1, OOB = TRUE, pre1.0_0 = conditional) 
{
    response <- object@responses
    input <- object@data@get("input")
    xnames <- colnames(input)
    inp <- initVariableFrame(input, trafo = NULL)
    y <- object@responses@variables[[1]]
    error <- function(x, oob) mean((levels(y)[sapply(x, which.max)] != y)[oob])

    w <- object@initweights
    perror <- matrix(0, nrow = nperm * length(object@ensemble), ncol = length(xnames))
    colnames(perror) <- xnames

    data = foreach(b = 1:length(object@ensemble), .packages = c("party","stats"), .combine = rbind) %dopar%
    {
        try({
            tree <- object@ensemble[[b]]
            oob <- object@weights[[b]] == 0

            p <- .Call("R_predict", tree, inp, mincriterion, -1L, PACKAGE = "party")

            eoob <- error(p, oob)

            for (j in unique(varIDs(tree))) {
                for (per in 1:nperm) {
                    if (conditional || pre1.0_0) {
                      tmp <- inp
                      ccl <- create_cond_list(conditional, threshold, xnames[j], input)
                      if (is.null(ccl)) {
                        perm <- sample(which(oob))
                      }
                      else {
                        perm <- conditional_perm(ccl, xnames, input, tree, oob)
                      }
                      tmp@variables[[j]][which(oob)] <- tmp@variables[[j]][perm]
                      p <- .Call("R_predict", tree, tmp, mincriterion, -1L, PACKAGE = "party")
                    }
                    else {
                      p <- .Call("R_predict", tree, inp, mincriterion, as.integer(j), PACKAGE = "party")
                    }
                    perror[b, j] <- (error(p, oob) - eoob)
                }
            }

            ########
            # return data to the %dopar% loop data variable
            perror[b, ]
            ########

        }) # END OF TRY
    } # END OF LOOP WITH PARALLEL COMPUTING

    perror = data
    perror <- as.data.frame(perror)
    return(MeanDecreaseAccuracy = colMeans(perror))
}

environment(parallel_compute_varimp) <- asNamespace('party')


cl <- makeCluster(detectCores())
registerDoParallel(cl, cores = detectCores())
<...>
system.time(data.cforest.varimp <- parallel_compute_varimp(data.cforest, conditional = TRUE))

mais je reçois une erreur:

> system.time(data.cforest.varimp <- parallel_compute_varimp(data.cforest, conditional = TRUE))
Error in unserialize(socklist[[n]]) : error reading from connection
Timing stopped at: 58.302 13.197 709.307

Le code fonctionnait avec un ensemble de données plus petit sur 4 CPU.

Je suis à court d'idées. Quelqu'un peut-il suggérer un moyen d'atteindre mon objectif d'exécuter la fonction varimp du package de partie sur les processeurs parallèles?

23
Timothée HENRY

L'erreur:

Error in unserialize(socklist[[n]]) : error reading from connection

signifie que le processus maître a reçu une erreur lors de l'appel de unserialize pour lire à partir de la connexion socket à l'un des travailleurs. Cela signifie probablement que le travailleur correspondant est décédé, abandonnant ainsi son extrémité de la connexion de socket. Malheureusement, il peut être décédé pour un certain nombre de raisons, dont beaucoup sont très spécifiques au système.

Vous pouvez généralement comprendre pourquoi le travailleur est décédé en utilisant l'option "outfile" de makeCluster afin que le message d'erreur généré par le travailleur ne soit pas jeté. Je recommande généralement d'utiliser outfile="" comme décrit dans cette réponse . Notez que l'option "outfile" fonctionne de la même manière dans les packages snow et parallel.

Vous pouvez également vérifier que votre boucle foreach fonctionne correctement lorsqu'elle est exécutée séquentiellement en enregistrant le backend séquentiel:

registerDoSEQ()

Si vous êtes chanceux, la boucle foreach échouera lorsqu'elle sera exécutée séquentiellement, car il est généralement plus facile de comprendre ce qui ne va pas.

34
Steve Weston