1

I am trying to translate a for loop to a loop using foreach.

I have tried several output methods playing with the .combine argument, but I cannot output the two vectors that I create by first initilizing them to hold 1e4 zeros and then refilling each entry at each iteration.

In particular, I cannot recover the vectors that are created in this way:

Va = numeric(1e4)
Vb = numeric(1e4)

result = foreach(j = 1:1e4, .multicombine=TRUE) %dopar%
{

    ... rest of the code ...

    Va[j] = sample(4,1)
    Vb[j] = sample(5,1)
    list(retSLSP, retBH)
}

Note that j is the loop variable in the foreach loop. Note also that the computations I showed are not the actual computations I have in my code, but are equivalent for the purposes of the example.

lmo
  • 37,904
  • 9
  • 56
  • 69
Albert Dorador
  • 331
  • 2
  • 9
  • 2
    This is not how foreach loops work. They follow the functional programming paradigm insofar as they don't allow side effects. They are actually more similar to sapply than to for loops. In summary, you can't fill a vector with a foreach loop (well, there is a way, but it's bad practice and inferior to a for loop). – Roland Feb 22 '17 at 19:33
  • Thanks, I suspected it wasn't just difficult but perhaps (close to) impossible to do. The computation speed I gained from using a foreach loop instead of a for loop was noticeable but not critical. But still, maybe I can avoid this approach of filling vectors. Is there a way to let the foreach function know that I want those two values saved at each iteration (without creating the Va and Vb vectors at all)? – Albert Dorador Feb 22 '17 at 19:56
  • 1
    You can return c(a,b) and use .combine = rbind to get a matrix. Then just index the two columns to retrieve two vectors. – thc Feb 23 '17 at 00:21
  • Thanks thc! It works perfectly. I'm new to functional programming so thanks for answering what probably is a very basic question. – Albert Dorador Feb 23 '17 at 06:47
  • @AlbertDorador An easy solution would be to use shared memory. See my answer below. – F. Privé Jul 20 '17 at 06:51

1 Answers1

1

You can use shared-memory to be accessed by all threads.

library(bigmemory)
V <- big.matrix(1e4, 2)
desc <- describe(V)

result = foreach(j = 1:1e4, .multicombine=TRUE) %dopar%
{
    V <- bigmemory::attach.big.matrix(desc)

    ... rest of the code ...

    V[j, 1] = sample(4,1)
    V[j, 2] = sample(5,1)
    list(retSLSP, retBH)
}

Va <- V[, 1]
Vb <- V[, 2]
rm(V, desc)

Although, it would be better to parallelize by blocks than to do it for the whole loop. An example: https://stackoverflow.com/a/45196081/6103040

F. Privé
  • 11,423
  • 2
  • 27
  • 78